Ole moved to archive

git-svn-id: svn://ultimatepp.org/upp/trunk@15668 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2021-01-14 13:03:01 +00:00
parent ee6ba69e44
commit 4e60ac4ca3
24 changed files with 3624 additions and 3624 deletions

View file

@ -11,7 +11,7 @@ file
ocx.def;
custom() "idl",
"midl /newtlb $(!/I) /h \"$(DIR)/$(TITLE)_idl.h\" /iid \"$(DIR)/$(TITLE"
"midl /newtlb $(!/I) /h \"$(DIR)/$(TITLE)_idl.h\" /iid \"$(DIR)/$(TITLE"
")_idl.cpp\" /tlb \"$(DIR)/$(TITLE).tlb\" \"$(PATH)\"\r\n",
"$(DIR)/$(TITLE)_idl.h\r\n$(DIR)/$(TITLE).tlb\r\n";

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
LIBRARY "test.ocx"
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
LIBRARY "test.ocx"
EXPORTS
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE

View file

@ -1,25 +1,25 @@
#include <Ole/Ctrl/OleCtrl.h>
#ifdef flagMAIN
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH: {
Ctrl::InitWin32(hinstDll);
AppInitEnvironment__();
break;
}
case DLL_PROCESS_DETACH: {
Ctrl::CloseTopCtrls();
break;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
#endif
#include <Ole/Ctrl/OleCtrl.h>
#ifdef flagMAIN
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH: {
Ctrl::InitWin32(hinstDll);
AppInitEnvironment__();
break;
}
case DLL_PROCESS_DETACH: {
Ctrl::CloseTopCtrls();
break;
}
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,27 +1,27 @@
#ifndef OLE_H
#define OLE_H
#include <Core/Core.h>
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) && defined(COMPILER_MSC)
#define Ptr Ptr_
#define StdFont StdFont_
#define Font Font_
#define Picture Picture_
#define byte win32_byte_ // RpcNdr defines byte -> class with Upp::byte
#define CY win32_CY_
#include <comdef.h>
#include <comip.h>
#undef Ptr
#undef StdFont
#undef Font
#undef Picture
#undef byte
#undef CY
#endif
#include "util.h"
#endif//OLE_H
#ifndef OLE_H
#define OLE_H
#include <Core/Core.h>
#if defined(PLATFORM_WIN32) && !defined(PLATFORM_WINCE) && defined(COMPILER_MSC)
#define Ptr Ptr_
#define StdFont StdFont_
#define Font Font_
#define Picture Picture_
#define byte win32_byte_ // RpcNdr defines byte -> class with Upp::byte
#define CY win32_CY_
#include <comdef.h>
#include <comip.h>
#undef Ptr
#undef StdFont
#undef Font
#undef Picture
#undef byte
#undef CY
#endif
#include "util.h"
#endif//OLE_H

View file

@ -1,3 +1,3 @@
TOPIC("ocx_en-us")
#include "ocx_en-us.tpp"
END_TOPIC
TOPIC("ocx_en-us")
#include "ocx_en-us.tpp"
END_TOPIC

View file

@ -1,455 +1,455 @@
#include "Ole.h"
#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC)
namespace Upp {
//////////////////////////////////////////////////////////////////////
// GUID
GUID GetCoClassGUID(const char *name, bool prog_id)
{
OleBstr uni = String(name);
GUID guid;
Zero(guid);
if(prog_id && *name != '{')
CLSIDFromProgID(~uni, &guid);
else
CLSIDFromString(~uni, &guid);
return guid;
}
hash_t GetHashValue(const GUID& guid) {
const dword *p = reinterpret_cast<const dword *>(&guid);
return CombineHash(p[0], p[1], p[2], p[3]);
}
String Format(const GUID& guid) {
String result;
wchar_t buffer[128];
int length;
if((length = StringFromGUID2(guid, buffer, __countof(buffer))) > 0)
result = AsString(buffer, length - 1);
return result;
}
String CFormat(const GUID& guid) {
String value = Format("{ 0x%08x, 0x%04x, 0x%04x, { ", (int)guid.Data1, (int)guid.Data2, (int)guid.Data3);
for(int i = 0; i < 8; i++)
value << Format("0x%02x, ", guid.Data4[i]);
return value << "} }";
}
String GetInterfaceName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "Interface\\" + goo, HKEY_CLASSES_ROOT), goo);
}
String GetCoClassName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "CLSID\\" + goo + "\\ProgID", HKEY_CLASSES_ROOT), goo);
}
String GetDisplayName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "CLSID\\" + goo, HKEY_CLASSES_ROOT), goo);
}
bool Guid::IsNullInstance() const
{
const dword *p = reinterpret_cast<const dword *>(&guid);
return (p[0] | p[1] | p[2] | p[3]) == 0;
}
//////////////////////////////////////////////////////////////////////
// VARIANT
Value AsValue(const VARIANT& variant)
{
switch(variant.vt) {
case VT_ERROR: return ErrorValue(GetErrorMessage(variant.scode));
case VT_EMPTY: return Value(); // void
case VT_NULL: return Null;
case VT_BOOL:
case VT_UI1: return (int)variant.bVal;
case VT_I2: return (int)variant.iVal;
case VT_I4: return (int)variant.lVal;
case VT_R4: return variant.fltVal;
case VT_R8: return variant.dblVal;
case VT_CY: return GetCurrency(variant.cyVal);
case VT_DATE: return FromDATE(variant.date);
case VT_BSTR: return BSTRToWString(variant.bstrVal);
case VT_DECIMAL: {
const DECIMAL& d = variant.decVal;
double h = (d.Lo32 + d.Mid32 * (65536.0 * 65536.0)) * pow(0.1, d.scale);
return d.sign ? -h : h;
}
case VT_ARRAY | VT_UI1: {
int nelem = variant.parray->rgsabound[0].cElements;
void *bits = 0;
if(SUCCEEDED(SafeArrayAccessData(variant.parray, &bits)) && bits) {
String out((const char *)bits, nelem);
SafeArrayUnaccessData(variant.parray);
return out;
}
break;
}
}
return ErrorValue(Format("Unknown variant type %d", variant.vt));
}
OleVariant AsVariant(Value value) {
OleVariant out(VT_NULL);
if(value.IsNull())
return out;
switch(value.GetType()) {
case BOOL_V: out.vt = VT_UI1; out.bVal = (byte)(int)value; break;
case INT_V: out.vt = VT_I4; out.lVal = (int)value; break;
case DOUBLE_V: out.vt = VT_R8; out.dblVal = value; break;
case STRING_V: out.vt = VT_BSTR; out.bstrVal = StringToBSTR(value); break;
case WSTRING_V: out.vt = VT_BSTR; out.bstrVal = WStringToBSTR(value); break;
case DATE_V:
case TIME_V: out.vt = VT_DATE; out.date = ToDATE((Time)value);
// todo: VALUEARRAY_V ??
default: break;
}
return out;
}
double GetCurrency(const win32_CY_& currency) {
return (currency.Hi * (65536.0 * 65536.0) + currency.Lo) / 10000.0;
}
OleVariant ValueToVariant(Value v)
{
if(IsTypeRaw< IRef<IDispatch> >(v))
{
OleVariant out(VT_DISPATCH);
IRef<IDispatch> disp = ValueTo< IRef<IDispatch> >(v);
if(!!disp) disp -> AddRef();
out.pdispVal = ~disp;
return out;
}
if(IsTypeRaw< IRef<IUnknown> >(v))
{
OleVariant out(VT_UNKNOWN);
IRef<IUnknown> unk = ValueTo< IRef<IUnknown> >(v);
if(!!unk) unk -> AddRef();
out.punkVal = ~unk;
return out;
}
return AsVariant(v);
}
void ReturnVariant(VARIANT *var, const Value& v)
{
*var = AsVariant(v);
}
//////////////////////////////////////////////////////////////////////
// BSTR
String BSTRToString(BSTR bstr)
{
int l;
if(!bstr || !(l = SysStringLen(bstr)))
return Null;
byte cs = GetDefaultCharset();
if(cs == CHARSET_UTF8)
return ToUtf8(TWchar(bstr));
StringBuffer out(l);
FromUnicode(out, TWchar(bstr), l, cs);
return out;
}
BSTR StringToBSTR(String s)
{
int len = s.GetLength();
if(len == 0)
return NULL;
byte cs = GetDefaultCharset();
if(cs == CHARSET_UTF8)
return WStringToBSTR(FromUtf8(s));
BSTR bstr = SysAllocStringLen(NULL, len);
ToUnicode(TWchar(bstr), s, len, cs);
return bstr;
}
void ReturnString(BSTR *dest, String s)
{
if(*dest)
SysFreeString(*dest);
*dest = StringToBSTR(s);
}
HRESULT CheckReturnString(BSTR *bstr, String s)
{
if(!bstr) return E_INVALIDARG;
ReturnString(bstr, s);
return S_OK;
}
void ReturnWString(BSTR *dest, WString s)
{
if(*dest)
SysFreeString(*dest);
*dest = WStringToBSTR(s);
}
HRESULT CheckReturnWString(BSTR *bstr, WString s)
{
if(!bstr) return E_INVALIDARG;
ReturnWString(bstr, s);
return S_OK;
}
static ValueArray SAFEARRAYToValueArrayPart(SAFEARRAY *array, long *indices, int dim_index)
{
Vector<Value> dim_array;
int nelem = array->rgsabound[dim_index].cElements;
dim_array.SetCount(nelem);
for(int e = 0; e < nelem; e++) {
indices[dim_index] = e;
if(dim_index > 0)
dim_array[e] = SAFEARRAYToValueArrayPart(array, indices, dim_index - 1);
else {
OleVariant var;
HRESULT hr = SafeArrayGetElement(array, indices, &var);
if(SUCCEEDED(hr))
dim_array[e] = AsValue(var);
else {
String dims;
for(int i = 0; i < dim_index; i++)
dims << (i ? ", " : "") << indices[i];
dim_array[e] = ErrorValue(NFormat("SafeArrayGetElement(%s): error %08lx", dims, hr));
}
}
}
return ValueArray(pick(dim_array));
}
ValueArray SAFEARRAYToValueArray(SAFEARRAY *array)
{
int ndims = array->cDims;
Vector<long> indices;
indices.SetCount(ndims, -1);
return SAFEARRAYToValueArrayPart(array, indices.Begin(), ndims - 1);
}
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array)
{
Vector<WString> out;
out.SetCount(array->rgsabound[0].cElements);
Vector<long> indices;
indices.SetCount(array->cDims, 0);
for(int i = 0; i < out.GetCount(); i++) {
OleBstr s;
indices[0] = i;
HRESULT hr = SafeArrayGetElement(array, indices.Begin(), s.Set());
out[i] = s;
}
return out;
}
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_VARIANT, 0, varray.GetCount());
if(!a)
return NULL;
for(long index = 0; index < varray.GetCount(); index++) {
OleVariant var = AsVariant(varray[(int)index]);
SafeArrayPutElement(a, &index, &var);
}
return a;
}
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& vstr)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_BSTR, 0, vstr.GetCount());
if(!a)
return NULL;
for(long index = 0; index < vstr.GetCount(); index++) {
OleBstr var = vstr[(int)index];
SafeArrayPutElement(a, &index, ~var);
}
return a;
}
//////////////////////////////////////////////////////////////////////
// special types
Color PackColor(long rgb)
{
if(rgb < 0)
return Null;
return Color((rgb >> 16) & 255, (rgb >> 8) & 255, (rgb >> 0) & 255);
}
long UnpackColor(Color c)
{
if(IsNull(c))
return -1;
return (c.GetR() << 16) | (c.GetG() << 8) | (c.GetB() << 0);
}
HRESULT CheckReturnColor(long *ptr, Color c)
{
if(!ptr)
return E_INVALIDARG;
*ptr = UnpackColor(c);
return S_OK;
}
//////////////////////////////////////////////////////////////////////
// errors
OleExc::OleExc(HRESULT hresult)
: Exc(NFormat("COM[%08x]: %s", (int)hresult, GetErrorMessage(hresult)))
, hresult(hresult)
{
}
OleExc::OleExc(HRESULT hresult, const char *text)
: Exc(NFormat("COM[%08x]: %s: %s", (int)hresult, GetErrorMessage(hresult), text))
, hresult(hresult)
{
LOG("OleExc::OleExc " << *this);
}
HRESULT LogResult(HRESULT hr)
{
LOGF("<= return 0x%08x: %s\r\n", hr, GetErrorMessage(hr));
return hr;
}
HRESULT LogError(HRESULT hr)
{
if(FAILED(hr))
LogResult(hr);
return hr;
}
//////////////////////////////////////////////////////////////////////
// interfaces
Value DispatchToValue(IDispatch *disp)
{
return RawPickToValue(IRef<IDispatch>(disp));
}
Value UnknownToValue(IUnknown *unk)
{
return RawPickToValue(IRef<IUnknown>(unk));
}
//////////////////////////////////////////////////////////////////////
// OleStream::
OleStream::OleStream(IUnknown *stream)
{
Open(stream);
}
bool OleStream::Open(IUnknown *stream)
{
Close();
if(!stream)
return false;
if(FAILED(stream -> QueryInterface(IID_IStream, (void **)&istream)))
return false;
STATSTG stat;
Zero(stat);
// HRESULT statres = istream -> Stat(&stat, STATFLAG_NONAME);
int mode = READWRITE;
// if(SUCCEEDED(statres) && (stat.grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ)
// mode = READ;
ULARGE_INTEGER pos = AsULarge(0), len;
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos))
|| FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_END, &len)))
SetError(hr);
current_offset = len.QuadPart;
OpenInit(mode, len.QuadPart);
Seek(pos.QuadPart);
return true;
}
void OleStream::Close()
{
if(!(bool)istream)
return;
int64 pos = GetPos();
Flush();
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, 0)))
SetError(hr);
istream = 0;
}
void OleStream::SetStreamSize(dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_WRITE));
HRESULT hr;
if(FAILED(hr = istream -> SetSize(AsULarge(size))))
SetError(hr);
ULARGE_INTEGER pos = AsULarge(0);
if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos)))
SetError(hr);
current_offset = pos.LowPart;
}
dword OleStream::Read(int64 at, void *ptr, dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_READ));
RawSeek(at);
dword done = 0;
HRESULT hr;
if(FAILED(hr = istream -> Read(ptr, size, &done)))
SetError(hr);
else
current_offset += done;
return done;
}
void OleStream::Write(int64 at, const void *data, dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_WRITE));
RawSeek(at);
dword done = 0;
HRESULT hr;
if(FAILED(hr = istream -> Write(data, size, &done)) || done != size)
SetError(hr);
current_offset += done;
}
void OleStream::RawSeek(int64 pos)
{
if(current_offset == pos)
return;
ULARGE_INTEGER new_pos = AsULarge(pos);
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, &new_pos)))
SetError(hr);
pos = new_pos.LowPart;
}
//////////////////////////////////////////////////////////////////////
}
#endif
#include "Ole.h"
#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC)
namespace Upp {
//////////////////////////////////////////////////////////////////////
// GUID
GUID GetCoClassGUID(const char *name, bool prog_id)
{
OleBstr uni = String(name);
GUID guid;
Zero(guid);
if(prog_id && *name != '{')
CLSIDFromProgID(~uni, &guid);
else
CLSIDFromString(~uni, &guid);
return guid;
}
hash_t GetHashValue(const GUID& guid) {
const dword *p = reinterpret_cast<const dword *>(&guid);
return CombineHash(p[0], p[1], p[2], p[3]);
}
String Format(const GUID& guid) {
String result;
wchar_t buffer[128];
int length;
if((length = StringFromGUID2(guid, buffer, __countof(buffer))) > 0)
result = AsString(buffer, length - 1);
return result;
}
String CFormat(const GUID& guid) {
String value = Format("{ 0x%08x, 0x%04x, 0x%04x, { ", (int)guid.Data1, (int)guid.Data2, (int)guid.Data3);
for(int i = 0; i < 8; i++)
value << Format("0x%02x, ", guid.Data4[i]);
return value << "} }";
}
String GetInterfaceName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "Interface\\" + goo, HKEY_CLASSES_ROOT), goo);
}
String GetCoClassName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "CLSID\\" + goo + "\\ProgID", HKEY_CLASSES_ROOT), goo);
}
String GetDisplayName(const GUID& guid) {
if(IsNull(Guid(guid)))
return Null;
String goo = Format(guid);
return Nvl(GetWinRegString(NULL, "CLSID\\" + goo, HKEY_CLASSES_ROOT), goo);
}
bool Guid::IsNullInstance() const
{
const dword *p = reinterpret_cast<const dword *>(&guid);
return (p[0] | p[1] | p[2] | p[3]) == 0;
}
//////////////////////////////////////////////////////////////////////
// VARIANT
Value AsValue(const VARIANT& variant)
{
switch(variant.vt) {
case VT_ERROR: return ErrorValue(GetErrorMessage(variant.scode));
case VT_EMPTY: return Value(); // void
case VT_NULL: return Null;
case VT_BOOL:
case VT_UI1: return (int)variant.bVal;
case VT_I2: return (int)variant.iVal;
case VT_I4: return (int)variant.lVal;
case VT_R4: return variant.fltVal;
case VT_R8: return variant.dblVal;
case VT_CY: return GetCurrency(variant.cyVal);
case VT_DATE: return FromDATE(variant.date);
case VT_BSTR: return BSTRToWString(variant.bstrVal);
case VT_DECIMAL: {
const DECIMAL& d = variant.decVal;
double h = (d.Lo32 + d.Mid32 * (65536.0 * 65536.0)) * pow(0.1, d.scale);
return d.sign ? -h : h;
}
case VT_ARRAY | VT_UI1: {
int nelem = variant.parray->rgsabound[0].cElements;
void *bits = 0;
if(SUCCEEDED(SafeArrayAccessData(variant.parray, &bits)) && bits) {
String out((const char *)bits, nelem);
SafeArrayUnaccessData(variant.parray);
return out;
}
break;
}
}
return ErrorValue(Format("Unknown variant type %d", variant.vt));
}
OleVariant AsVariant(Value value) {
OleVariant out(VT_NULL);
if(value.IsNull())
return out;
switch(value.GetType()) {
case BOOL_V: out.vt = VT_UI1; out.bVal = (byte)(int)value; break;
case INT_V: out.vt = VT_I4; out.lVal = (int)value; break;
case DOUBLE_V: out.vt = VT_R8; out.dblVal = value; break;
case STRING_V: out.vt = VT_BSTR; out.bstrVal = StringToBSTR(value); break;
case WSTRING_V: out.vt = VT_BSTR; out.bstrVal = WStringToBSTR(value); break;
case DATE_V:
case TIME_V: out.vt = VT_DATE; out.date = ToDATE((Time)value);
// todo: VALUEARRAY_V ??
default: break;
}
return out;
}
double GetCurrency(const win32_CY_& currency) {
return (currency.Hi * (65536.0 * 65536.0) + currency.Lo) / 10000.0;
}
OleVariant ValueToVariant(Value v)
{
if(IsTypeRaw< IRef<IDispatch> >(v))
{
OleVariant out(VT_DISPATCH);
IRef<IDispatch> disp = ValueTo< IRef<IDispatch> >(v);
if(!!disp) disp -> AddRef();
out.pdispVal = ~disp;
return out;
}
if(IsTypeRaw< IRef<IUnknown> >(v))
{
OleVariant out(VT_UNKNOWN);
IRef<IUnknown> unk = ValueTo< IRef<IUnknown> >(v);
if(!!unk) unk -> AddRef();
out.punkVal = ~unk;
return out;
}
return AsVariant(v);
}
void ReturnVariant(VARIANT *var, const Value& v)
{
*var = AsVariant(v);
}
//////////////////////////////////////////////////////////////////////
// BSTR
String BSTRToString(BSTR bstr)
{
int l;
if(!bstr || !(l = SysStringLen(bstr)))
return Null;
byte cs = GetDefaultCharset();
if(cs == CHARSET_UTF8)
return ToUtf8(TWchar(bstr));
StringBuffer out(l);
FromUnicode(out, TWchar(bstr), l, cs);
return out;
}
BSTR StringToBSTR(String s)
{
int len = s.GetLength();
if(len == 0)
return NULL;
byte cs = GetDefaultCharset();
if(cs == CHARSET_UTF8)
return WStringToBSTR(FromUtf8(s));
BSTR bstr = SysAllocStringLen(NULL, len);
ToUnicode(TWchar(bstr), s, len, cs);
return bstr;
}
void ReturnString(BSTR *dest, String s)
{
if(*dest)
SysFreeString(*dest);
*dest = StringToBSTR(s);
}
HRESULT CheckReturnString(BSTR *bstr, String s)
{
if(!bstr) return E_INVALIDARG;
ReturnString(bstr, s);
return S_OK;
}
void ReturnWString(BSTR *dest, WString s)
{
if(*dest)
SysFreeString(*dest);
*dest = WStringToBSTR(s);
}
HRESULT CheckReturnWString(BSTR *bstr, WString s)
{
if(!bstr) return E_INVALIDARG;
ReturnWString(bstr, s);
return S_OK;
}
static ValueArray SAFEARRAYToValueArrayPart(SAFEARRAY *array, long *indices, int dim_index)
{
Vector<Value> dim_array;
int nelem = array->rgsabound[dim_index].cElements;
dim_array.SetCount(nelem);
for(int e = 0; e < nelem; e++) {
indices[dim_index] = e;
if(dim_index > 0)
dim_array[e] = SAFEARRAYToValueArrayPart(array, indices, dim_index - 1);
else {
OleVariant var;
HRESULT hr = SafeArrayGetElement(array, indices, &var);
if(SUCCEEDED(hr))
dim_array[e] = AsValue(var);
else {
String dims;
for(int i = 0; i < dim_index; i++)
dims << (i ? ", " : "") << indices[i];
dim_array[e] = ErrorValue(NFormat("SafeArrayGetElement(%s): error %08lx", dims, hr));
}
}
}
return ValueArray(pick(dim_array));
}
ValueArray SAFEARRAYToValueArray(SAFEARRAY *array)
{
int ndims = array->cDims;
Vector<long> indices;
indices.SetCount(ndims, -1);
return SAFEARRAYToValueArrayPart(array, indices.Begin(), ndims - 1);
}
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array)
{
Vector<WString> out;
out.SetCount(array->rgsabound[0].cElements);
Vector<long> indices;
indices.SetCount(array->cDims, 0);
for(int i = 0; i < out.GetCount(); i++) {
OleBstr s;
indices[0] = i;
HRESULT hr = SafeArrayGetElement(array, indices.Begin(), s.Set());
out[i] = s;
}
return out;
}
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_VARIANT, 0, varray.GetCount());
if(!a)
return NULL;
for(long index = 0; index < varray.GetCount(); index++) {
OleVariant var = AsVariant(varray[(int)index]);
SafeArrayPutElement(a, &index, &var);
}
return a;
}
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& vstr)
{
SAFEARRAY *a = SafeArrayCreateVector(VT_BSTR, 0, vstr.GetCount());
if(!a)
return NULL;
for(long index = 0; index < vstr.GetCount(); index++) {
OleBstr var = vstr[(int)index];
SafeArrayPutElement(a, &index, ~var);
}
return a;
}
//////////////////////////////////////////////////////////////////////
// special types
Color PackColor(long rgb)
{
if(rgb < 0)
return Null;
return Color((rgb >> 16) & 255, (rgb >> 8) & 255, (rgb >> 0) & 255);
}
long UnpackColor(Color c)
{
if(IsNull(c))
return -1;
return (c.GetR() << 16) | (c.GetG() << 8) | (c.GetB() << 0);
}
HRESULT CheckReturnColor(long *ptr, Color c)
{
if(!ptr)
return E_INVALIDARG;
*ptr = UnpackColor(c);
return S_OK;
}
//////////////////////////////////////////////////////////////////////
// errors
OleExc::OleExc(HRESULT hresult)
: Exc(NFormat("COM[%08x]: %s", (int)hresult, GetErrorMessage(hresult)))
, hresult(hresult)
{
}
OleExc::OleExc(HRESULT hresult, const char *text)
: Exc(NFormat("COM[%08x]: %s: %s", (int)hresult, GetErrorMessage(hresult), text))
, hresult(hresult)
{
LOG("OleExc::OleExc " << *this);
}
HRESULT LogResult(HRESULT hr)
{
LOGF("<= return 0x%08x: %s\r\n", hr, GetErrorMessage(hr));
return hr;
}
HRESULT LogError(HRESULT hr)
{
if(FAILED(hr))
LogResult(hr);
return hr;
}
//////////////////////////////////////////////////////////////////////
// interfaces
Value DispatchToValue(IDispatch *disp)
{
return RawPickToValue(IRef<IDispatch>(disp));
}
Value UnknownToValue(IUnknown *unk)
{
return RawPickToValue(IRef<IUnknown>(unk));
}
//////////////////////////////////////////////////////////////////////
// OleStream::
OleStream::OleStream(IUnknown *stream)
{
Open(stream);
}
bool OleStream::Open(IUnknown *stream)
{
Close();
if(!stream)
return false;
if(FAILED(stream -> QueryInterface(IID_IStream, (void **)&istream)))
return false;
STATSTG stat;
Zero(stat);
// HRESULT statres = istream -> Stat(&stat, STATFLAG_NONAME);
int mode = READWRITE;
// if(SUCCEEDED(statres) && (stat.grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE)) == STGM_READ)
// mode = READ;
ULARGE_INTEGER pos = AsULarge(0), len;
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos))
|| FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_END, &len)))
SetError(hr);
current_offset = len.QuadPart;
OpenInit(mode, len.QuadPart);
Seek(pos.QuadPart);
return true;
}
void OleStream::Close()
{
if(!(bool)istream)
return;
int64 pos = GetPos();
Flush();
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, 0)))
SetError(hr);
istream = 0;
}
void OleStream::SetStreamSize(dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_WRITE));
HRESULT hr;
if(FAILED(hr = istream -> SetSize(AsULarge(size))))
SetError(hr);
ULARGE_INTEGER pos = AsULarge(0);
if(FAILED(hr = istream -> Seek(AsLarge(0), STREAM_SEEK_CUR, &pos)))
SetError(hr);
current_offset = pos.LowPart;
}
dword OleStream::Read(int64 at, void *ptr, dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_READ));
RawSeek(at);
dword done = 0;
HRESULT hr;
if(FAILED(hr = istream -> Read(ptr, size, &done)))
SetError(hr);
else
current_offset += done;
return done;
}
void OleStream::Write(int64 at, const void *data, dword size)
{
ASSERT((bool)istream && (GetStyle() & STRM_WRITE));
RawSeek(at);
dword done = 0;
HRESULT hr;
if(FAILED(hr = istream -> Write(data, size, &done)) || done != size)
SetError(hr);
current_offset += done;
}
void OleStream::RawSeek(int64 pos)
{
if(current_offset == pos)
return;
ULARGE_INTEGER new_pos = AsULarge(pos);
HRESULT hr;
if(FAILED(hr = istream -> Seek(AsLarge(pos), STREAM_SEEK_SET, &new_pos)))
SetError(hr);
pos = new_pos.LowPart;
}
//////////////////////////////////////////////////////////////////////
}
#endif

View file

@ -1,327 +1,327 @@
#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC)
namespace Upp {
#ifdef COMPILER_MSC
typedef __int64 longlong_t;
#define LL_(x) COMBINE(x, i64)
#else
typedef long long longlong_t;
#define LL_(x) COMBINE(x, LL)
#endif//COMPILER
inline void OleInit() { CoInitialize(NULL); }
inline const wchar_t *WcharT(const wchar *w) { return (const wchar_t *)w; }
inline wchar_t *WcharT(wchar *w) { return (wchar_t *)w; }
inline const wchar *TWchar(const wchar_t *w) { return (const wchar *)w; }
inline wchar *TWchar(wchar_t *w) { return (wchar *)w; }
template <class T>
class OleBuffer
{
public:
OleBuffer(T *ptr = 0) : ptr(ptr) {}
~OleBuffer() { Clear(); }
void Clear() { if(ptr) { CoTaskMemFree(ptr); ptr = 0; } }
T **Set() { Clear(); return &ptr; }
operator T * () { return ptr; }
operator const T * () const { return ptr; }
private:
T *ptr;
};
hash_t GetHashValue(const GUID& guid);
String Format(const GUID& guid);
String CFormat(const GUID& guid);
inline void Serialize(Stream& stream, GUID& guid) { stream.SerializeRaw((byte *)&guid, sizeof(GUID)); }
String GetInterfaceName(const GUID& guid);
String GetCoClassName(const GUID& guid);
String GetDisplayName(const GUID& guid);
GUID GetCoClassGUID(const char *name, bool prog_id = true);
class Guid : public ValueType<Guid, 70, Moveable<Guid> >
{
public:
Guid(const Nuller& = Null) { Clear(); }
Guid(const char *text, bool prid = true) { guid = GetCoClassGUID(text, prid); }
Guid(const GUID& guid_) : guid(guid_) {}
Guid(const Guid& guid_) : guid(guid_.guid) {}
Guid(IDispatchPtr& dispatch); // dynamic GUID of a dispatch object
Guid(Value v) { *this = ValueTo<Guid>(v); }
operator Value () const { return RichValue<Guid>(*this); }
operator const GUID& () const { return guid; }
operator GUID& () { return guid; }
const GUID& operator ~() const { return guid; }
Guid& operator = (const GUID& _guid) { guid = _guid; return *this; }
bool IsNullInstance() const;
bool IsEmpty() const { return IsNullInstance(); }
void Clear() { Zero(guid); }
operator String () const { return UPP::Format(guid); }
String CFormat() const { return UPP::CFormat(guid); }
void Serialize(Stream& stream) { UPP::Serialize(stream, guid); }
private:
GUID guid;
};
template <>
inline hash_t GetHashValue(const Guid& guid) { return GetHashValue(~guid); }
template <>
inline String AsString(const GUID& guid) { return Format(guid); }
template <>
inline String AsString(const Guid& guid) { return Format(~guid); }
inline bool operator == (const Guid& a, const Guid& b) { return ~a == ~b; }
inline bool operator != (const Guid& a, const Guid& b) { return ~a != ~b; }
class OleExc : public Exc
{
public:
OleExc(HRESULT hresult);
OleExc(HRESULT hresult, const char *text);
public:
HRESULT hresult;
};
HRESULT LogResult(HRESULT hr);
HRESULT LogError(HRESULT hr);
inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); }
inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); }
#define OLE_VERIFY(c) OleVerify(c, #c)
class OleVariant : public VARIANT
{
public:
OleVariant(int vtype = VT_EMPTY) { VariantInit(this); vt = vtype; }
OleVariant(const OleVariant& o) { VariantInit(this); VariantCopy(this, const_cast<OleVariant *>(&o)); }
~OleVariant() { VariantClear(this); }
OleVariant(const VARIANT& var) { VariantInit(this); VariantCopy(this, const_cast<VARIANT *>(&var)); }
OleVariant& operator = (const OleVariant& var) { if(this != &var) { VariantClear(this); VariantCopy(this, const_cast<VARIANT *>((VARIANT *)&var)); } return *this; }
VARIANT operator ~ () const { VARIANT v; VariantInit(&v); VariantCopy(&v, const_cast<OleVariant *>(this)); return v; }
};
Value AsValue(const VARIANT& variant);
OleVariant AsVariant(Value value);
//inline ULARGE_INTEGER AsULarge(dword value) { ULARGE_INTEGER i; i.QuadPart = value; return i; }
//inline LARGE_INTEGER AsLarge(int value) { LARGE_INTEGER i; i.QuadPart = value; return i; }
inline ULARGE_INTEGER AsULarge(int64 value) { ULARGE_INTEGER i; i.QuadPart = value; return i; }
inline LARGE_INTEGER AsLarge(int64 value) { LARGE_INTEGER i; i.QuadPart = value; return i; }
double GetCurrency(const win32_CY_& currency);
inline DATE ToDATE(Date date) { return date - Date(1899, 12, 30); }
inline DATE ToDATE(Time time) { return (time - Time(1899, 12, 30)) / 86400.0; }
inline Time FromDATE(DATE date) { return Time(1899, 12, 30) + (int64)floor(date * 86400.0 + 0.5); }
OleVariant ValueToVariant(Value v);
void ReturnVariant(VARIANT *var, Value v);
inline WString BSTRToWString(BSTR bstr) { return WString((wchar *)bstr, SysStringLen(bstr)); }
inline BSTR WStringToBSTR(WString w) { return SysAllocStringLen((BSTR)~w, w.GetLength()); }
String BSTRToString(BSTR bstr);
BSTR StringToBSTR(String s);
void ReturnString(BSTR *dest, String s);
HRESULT CheckReturnString(BSTR *bstr, String s);
void ReturnWString(BSTR *dest, WString s);
HRESULT CheckReturnWString(BSTR *bstr, WString s);
ValueArray SAFEARRAYToValueArray(SAFEARRAY *array);
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array);
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray);
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& varray);
void ReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
void ReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
class OleSafeArray {
public:
OleSafeArray() : array(NULL) {}
OleSafeArray(const ValueArray& va) { array = ToSAFEARRAY(va); }
OleSafeArray(const Vector<WString>& vs) { array = ToSAFEARRAY(vs); }
OleSafeArray(const OleSafeArray& a) { array = NULL; if(a.array) OleVerify(SafeArrayCopy(a.array, &array)); }
~OleSafeArray() { if(array) SafeArrayDestroy(array); }
operator ValueArray () const { return SAFEARRAYToValueArray(array); }
operator Vector<WString> () const { return SAFEARRAYToWStringVector(array); }
SAFEARRAY *operator ~ () const { return array; }
private:
SAFEARRAY *array;
};
class OleBstr
{
public:
OleBstr(const Nuller& = Null) : bstr(NULL) {}
OleBstr(WString w) : bstr(WStringToBSTR(w)) {}
OleBstr(String s) : bstr(StringToBSTR(s)) {}
~OleBstr() { if(bstr) SysFreeString(bstr); }
void Clear() { if(bstr) { SysFreeString(bstr); bstr = NULL; } }
BSTR *Set() { Clear(); return &bstr; }
operator WString () const { return BSTRToWString(bstr); }
operator String () const { return BSTRToString(bstr); }
String ToString() const { return BSTRToString(bstr); }
// operator BSTR () const { return bstr; }
BSTR operator ~ () const { return bstr; }
int GetLength() const { return SysStringLen(bstr); }
private:
BSTR bstr;
};
inline const RECTL& ToRectL(const Rect& rc) { return reinterpret_cast<const RECTL&>(rc); }
inline const Rect& ToRect(const RECTL& rc) { return reinterpret_cast<const Rect&>(rc); }
Color PackColor(long rgb);
long UnpackColor(Color c);
HRESULT CheckReturnColor(long *ptr, Color c);
template <class T>
class IRefBase : Moveable< IRefBase<T> >
{
public:
IRefBase(T *ptr = NULL) : ptr(ptr) { if(ptr) ptr->AddRef(); }
IRefBase(const IRefBase& i) { if(ptr = i.ptr) ptr->AddRef(); }
~IRefBase() { if(ptr) ptr->Release(); }
static GUID GetIID() { return __uuidof(T); }
HRESULT Create(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER)
{ return CoCreateInstance(clsid, NULL, flags, GetIID(), (void **)Set()); }
void Clear() { if(ptr) { ptr->Release(); ptr = 0; } }
T *operator->() const { ASSERT(ptr); return ptr; }
T& operator * () const { ASSERT(ptr); return *ptr; }
T *operator ~ () const { return ptr; }
T **Set() { Clear(); return &ptr; }
IUnknown **SetUnk() { Clear(); return (IUnknown **)&ptr; }
void **SetVoid() { Clear(); return (void **)&ptr; }
void Set(T *p) { T *old = ptr; if(ptr = p) ptr->AddRef(); if(old) old->Release(); }
bool operator !() const { return !ptr; }
T *AddRef() { if(ptr) ptr->AddRef(); return ptr; }
T *Detach() { T *out = ptr; ptr = 0; return out; }
T *operator - () { return Detach(); }
protected:
mutable T *ptr;
};
template <class T>
class IRef : public Moveable< IRef<T>, IRefBase<T> >
{
public:
IRef() {}
IRef(IUnknown *u) { if(u) OleVerify(u->QueryInterface(__uuidof(T), (void **)&ptr)); }
IRef(T *t) { if(ptr = t) ptr->AddRef(); }
IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); }
IRef(const IRef<T>& x) : Moveable< IRef<T>, IRefBase<T> >(x) {}
explicit IRef(const VARIANT& v)
{
ptr = NULL;
if(v.vt == VT_DISPATCH)
OleVerify(v.pdispVal->QueryInterface(__uuidof(T), (void **)&ptr));
else if(v.vt == VT_UNKNOWN)
OleVerify(v.punkVal->QueryInterface(__uuidof(T), (void **)&ptr));
else
{
ASSERT(v.vt == VT_EMPTY || v.vt == VT_NULL);
}
}
IRef& operator = (const IRef<T>& x) { Set(x.ptr); return *this; }
};
template <>
class IRef<IUnknown> : public IRefBase<IUnknown>
{
public:
IRef() {}
IRef(IUnknown *u) : IRefBase<IUnknown>(u) {}
IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); }
IRef(const IRef<IUnknown>& x) : IRefBase<IUnknown>(x.ptr) {}
IRef& operator = (const IRef<IUnknown>& x) { Set(x.ptr); return *this; }
};
Value DispatchToValue(IDispatch *disp);
Value UnknownToValue(IUnknown *unk);
template <class I>
OleVariant DispVar(I& iface)
{
IRef<IDispatch> disp = iface;
OleVariant out(VT_DISPATCH);
if(!!disp) disp->AddRef();
out.pdispVal = ~disp;
return out;
}
template <class T>
struct OleType : Moveable< OleType<T> >
{
friend T *Ptr(T& t) { return reinterpret_cast<T *>(&reinterpret_cast<char &>(t)); }
friend T& Deref(T *t) { return reinterpret_cast<T&>(*reinterpret_cast<char *>(t)); }
friend void Destroy(T& t) { t.~T(); }
friend T& Construct(T& t) { return Deref(new(Ptr(t)) T); }
friend void CopyConstruct(T& t, T& x) { new(Ptr(t)) T(x); }
friend void DeepCopyConstruct(T& t, const T& x) { new(Ptr(t)) T(x); }
};
template <class T, class U>
inline HRESULT QueryInterface(T& src, U& dest, const GUID& guid)
{
return src->QueryInterface(guid, (void **)dest.Set());
}
template <class T, class U>
inline HRESULT QueryInterface(T& src, U& dest)
{
return QueryInterface(src, dest, dest.GetIID());
}
class OleStream : public BlockStream
{
public:
OleStream(IUnknown *stream = 0);
bool Open(IUnknown *stream);
virtual void Close();
virtual bool IsOpen() const { return istream; }
protected:
virtual void SetStreamSize(dword size);
virtual dword Read(int64 at, void *ptr, dword size);
virtual void Write(int64 at, const void *data, dword size);
void RawSeek(int64 pos);
protected:
IStreamPtr istream;
int64 current_offset;
};
}
#endif
#if defined(PLATFORM_WIN32) && defined(COMPILER_MSC)
namespace Upp {
#ifdef COMPILER_MSC
typedef __int64 longlong_t;
#define LL_(x) COMBINE(x, i64)
#else
typedef long long longlong_t;
#define LL_(x) COMBINE(x, LL)
#endif//COMPILER
inline void OleInit() { CoInitialize(NULL); }
inline const wchar_t *WcharT(const wchar *w) { return (const wchar_t *)w; }
inline wchar_t *WcharT(wchar *w) { return (wchar_t *)w; }
inline const wchar *TWchar(const wchar_t *w) { return (const wchar *)w; }
inline wchar *TWchar(wchar_t *w) { return (wchar *)w; }
template <class T>
class OleBuffer
{
public:
OleBuffer(T *ptr = 0) : ptr(ptr) {}
~OleBuffer() { Clear(); }
void Clear() { if(ptr) { CoTaskMemFree(ptr); ptr = 0; } }
T **Set() { Clear(); return &ptr; }
operator T * () { return ptr; }
operator const T * () const { return ptr; }
private:
T *ptr;
};
hash_t GetHashValue(const GUID& guid);
String Format(const GUID& guid);
String CFormat(const GUID& guid);
inline void Serialize(Stream& stream, GUID& guid) { stream.SerializeRaw((byte *)&guid, sizeof(GUID)); }
String GetInterfaceName(const GUID& guid);
String GetCoClassName(const GUID& guid);
String GetDisplayName(const GUID& guid);
GUID GetCoClassGUID(const char *name, bool prog_id = true);
class Guid : public ValueType<Guid, 70, Moveable<Guid> >
{
public:
Guid(const Nuller& = Null) { Clear(); }
Guid(const char *text, bool prid = true) { guid = GetCoClassGUID(text, prid); }
Guid(const GUID& guid_) : guid(guid_) {}
Guid(const Guid& guid_) : guid(guid_.guid) {}
Guid(IDispatchPtr& dispatch); // dynamic GUID of a dispatch object
Guid(Value v) { *this = ValueTo<Guid>(v); }
operator Value () const { return RichValue<Guid>(*this); }
operator const GUID& () const { return guid; }
operator GUID& () { return guid; }
const GUID& operator ~() const { return guid; }
Guid& operator = (const GUID& _guid) { guid = _guid; return *this; }
bool IsNullInstance() const;
bool IsEmpty() const { return IsNullInstance(); }
void Clear() { Zero(guid); }
operator String () const { return UPP::Format(guid); }
String CFormat() const { return UPP::CFormat(guid); }
void Serialize(Stream& stream) { UPP::Serialize(stream, guid); }
private:
GUID guid;
};
template <>
inline hash_t GetHashValue(const Guid& guid) { return GetHashValue(~guid); }
template <>
inline String AsString(const GUID& guid) { return Format(guid); }
template <>
inline String AsString(const Guid& guid) { return Format(~guid); }
inline bool operator == (const Guid& a, const Guid& b) { return ~a == ~b; }
inline bool operator != (const Guid& a, const Guid& b) { return ~a != ~b; }
class OleExc : public Exc
{
public:
OleExc(HRESULT hresult);
OleExc(HRESULT hresult, const char *text);
public:
HRESULT hresult;
};
HRESULT LogResult(HRESULT hr);
HRESULT LogError(HRESULT hr);
inline void OleVerify(HRESULT hr) { if(FAILED(hr)) throw OleExc(hr); }
inline void OleVerify(HRESULT hr, const char *text) { if(FAILED(hr)) throw OleExc(hr, text); }
#define OLE_VERIFY(c) OleVerify(c, #c)
class OleVariant : public VARIANT
{
public:
OleVariant(int vtype = VT_EMPTY) { VariantInit(this); vt = vtype; }
OleVariant(const OleVariant& o) { VariantInit(this); VariantCopy(this, const_cast<OleVariant *>(&o)); }
~OleVariant() { VariantClear(this); }
OleVariant(const VARIANT& var) { VariantInit(this); VariantCopy(this, const_cast<VARIANT *>(&var)); }
OleVariant& operator = (const OleVariant& var) { if(this != &var) { VariantClear(this); VariantCopy(this, const_cast<VARIANT *>((VARIANT *)&var)); } return *this; }
VARIANT operator ~ () const { VARIANT v; VariantInit(&v); VariantCopy(&v, const_cast<OleVariant *>(this)); return v; }
};
Value AsValue(const VARIANT& variant);
OleVariant AsVariant(Value value);
//inline ULARGE_INTEGER AsULarge(dword value) { ULARGE_INTEGER i; i.QuadPart = value; return i; }
//inline LARGE_INTEGER AsLarge(int value) { LARGE_INTEGER i; i.QuadPart = value; return i; }
inline ULARGE_INTEGER AsULarge(int64 value) { ULARGE_INTEGER i; i.QuadPart = value; return i; }
inline LARGE_INTEGER AsLarge(int64 value) { LARGE_INTEGER i; i.QuadPart = value; return i; }
double GetCurrency(const win32_CY_& currency);
inline DATE ToDATE(Date date) { return date - Date(1899, 12, 30); }
inline DATE ToDATE(Time time) { return (time - Time(1899, 12, 30)) / 86400.0; }
inline Time FromDATE(DATE date) { return Time(1899, 12, 30) + (int64)floor(date * 86400.0 + 0.5); }
OleVariant ValueToVariant(Value v);
void ReturnVariant(VARIANT *var, Value v);
inline WString BSTRToWString(BSTR bstr) { return WString((wchar *)bstr, SysStringLen(bstr)); }
inline BSTR WStringToBSTR(WString w) { return SysAllocStringLen((BSTR)~w, w.GetLength()); }
String BSTRToString(BSTR bstr);
BSTR StringToBSTR(String s);
void ReturnString(BSTR *dest, String s);
HRESULT CheckReturnString(BSTR *bstr, String s);
void ReturnWString(BSTR *dest, WString s);
HRESULT CheckReturnWString(BSTR *bstr, WString s);
ValueArray SAFEARRAYToValueArray(SAFEARRAY *array);
Vector<WString> SAFEARRAYToWStringVector(SAFEARRAY *array);
SAFEARRAY *ToSAFEARRAY(const ValueArray& varray);
SAFEARRAY *ToSAFEARRAY(const Vector<WString>& varray);
void ReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
void ReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const ValueArray& array);
HRESULT CheckReturnSAFEARRAY(SAFEARRAY *dest, const Vector<WString>& array);
class OleSafeArray {
public:
OleSafeArray() : array(NULL) {}
OleSafeArray(const ValueArray& va) { array = ToSAFEARRAY(va); }
OleSafeArray(const Vector<WString>& vs) { array = ToSAFEARRAY(vs); }
OleSafeArray(const OleSafeArray& a) { array = NULL; if(a.array) OleVerify(SafeArrayCopy(a.array, &array)); }
~OleSafeArray() { if(array) SafeArrayDestroy(array); }
operator ValueArray () const { return SAFEARRAYToValueArray(array); }
operator Vector<WString> () const { return SAFEARRAYToWStringVector(array); }
SAFEARRAY *operator ~ () const { return array; }
private:
SAFEARRAY *array;
};
class OleBstr
{
public:
OleBstr(const Nuller& = Null) : bstr(NULL) {}
OleBstr(WString w) : bstr(WStringToBSTR(w)) {}
OleBstr(String s) : bstr(StringToBSTR(s)) {}
~OleBstr() { if(bstr) SysFreeString(bstr); }
void Clear() { if(bstr) { SysFreeString(bstr); bstr = NULL; } }
BSTR *Set() { Clear(); return &bstr; }
operator WString () const { return BSTRToWString(bstr); }
operator String () const { return BSTRToString(bstr); }
String ToString() const { return BSTRToString(bstr); }
// operator BSTR () const { return bstr; }
BSTR operator ~ () const { return bstr; }
int GetLength() const { return SysStringLen(bstr); }
private:
BSTR bstr;
};
inline const RECTL& ToRectL(const Rect& rc) { return reinterpret_cast<const RECTL&>(rc); }
inline const Rect& ToRect(const RECTL& rc) { return reinterpret_cast<const Rect&>(rc); }
Color PackColor(long rgb);
long UnpackColor(Color c);
HRESULT CheckReturnColor(long *ptr, Color c);
template <class T>
class IRefBase : Moveable< IRefBase<T> >
{
public:
IRefBase(T *ptr = NULL) : ptr(ptr) { if(ptr) ptr->AddRef(); }
IRefBase(const IRefBase& i) { if(ptr = i.ptr) ptr->AddRef(); }
~IRefBase() { if(ptr) ptr->Release(); }
static GUID GetIID() { return __uuidof(T); }
HRESULT Create(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER)
{ return CoCreateInstance(clsid, NULL, flags, GetIID(), (void **)Set()); }
void Clear() { if(ptr) { ptr->Release(); ptr = 0; } }
T *operator->() const { ASSERT(ptr); return ptr; }
T& operator * () const { ASSERT(ptr); return *ptr; }
T *operator ~ () const { return ptr; }
T **Set() { Clear(); return &ptr; }
IUnknown **SetUnk() { Clear(); return (IUnknown **)&ptr; }
void **SetVoid() { Clear(); return (void **)&ptr; }
void Set(T *p) { T *old = ptr; if(ptr = p) ptr->AddRef(); if(old) old->Release(); }
bool operator !() const { return !ptr; }
T *AddRef() { if(ptr) ptr->AddRef(); return ptr; }
T *Detach() { T *out = ptr; ptr = 0; return out; }
T *operator - () { return Detach(); }
protected:
mutable T *ptr;
};
template <class T>
class IRef : public Moveable< IRef<T>, IRefBase<T> >
{
public:
IRef() {}
IRef(IUnknown *u) { if(u) OleVerify(u->QueryInterface(__uuidof(T), (void **)&ptr)); }
IRef(T *t) { if(ptr = t) ptr->AddRef(); }
IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); }
IRef(const IRef<T>& x) : Moveable< IRef<T>, IRefBase<T> >(x) {}
explicit IRef(const VARIANT& v)
{
ptr = NULL;
if(v.vt == VT_DISPATCH)
OleVerify(v.pdispVal->QueryInterface(__uuidof(T), (void **)&ptr));
else if(v.vt == VT_UNKNOWN)
OleVerify(v.punkVal->QueryInterface(__uuidof(T), (void **)&ptr));
else
{
ASSERT(v.vt == VT_EMPTY || v.vt == VT_NULL);
}
}
IRef& operator = (const IRef<T>& x) { Set(x.ptr); return *this; }
};
template <>
class IRef<IUnknown> : public IRefBase<IUnknown>
{
public:
IRef() {}
IRef(IUnknown *u) : IRefBase<IUnknown>(u) {}
IRef(const GUID& clsid, dword flags = CLSCTX_INPROC_SERVER) { OleVerify(Create(clsid, flags)); }
IRef(const IRef<IUnknown>& x) : IRefBase<IUnknown>(x.ptr) {}
IRef& operator = (const IRef<IUnknown>& x) { Set(x.ptr); return *this; }
};
Value DispatchToValue(IDispatch *disp);
Value UnknownToValue(IUnknown *unk);
template <class I>
OleVariant DispVar(I& iface)
{
IRef<IDispatch> disp = iface;
OleVariant out(VT_DISPATCH);
if(!!disp) disp->AddRef();
out.pdispVal = ~disp;
return out;
}
template <class T>
struct OleType : Moveable< OleType<T> >
{
friend T *Ptr(T& t) { return reinterpret_cast<T *>(&reinterpret_cast<char &>(t)); }
friend T& Deref(T *t) { return reinterpret_cast<T&>(*reinterpret_cast<char *>(t)); }
friend void Destroy(T& t) { t.~T(); }
friend T& Construct(T& t) { return Deref(new(Ptr(t)) T); }
friend void CopyConstruct(T& t, T& x) { new(Ptr(t)) T(x); }
friend void DeepCopyConstruct(T& t, const T& x) { new(Ptr(t)) T(x); }
};
template <class T, class U>
inline HRESULT QueryInterface(T& src, U& dest, const GUID& guid)
{
return src->QueryInterface(guid, (void **)dest.Set());
}
template <class T, class U>
inline HRESULT QueryInterface(T& src, U& dest)
{
return QueryInterface(src, dest, dest.GetIID());
}
class OleStream : public BlockStream
{
public:
OleStream(IUnknown *stream = 0);
bool Open(IUnknown *stream);
virtual void Close();
virtual bool IsOpen() const { return istream; }
protected:
virtual void SetStreamSize(dword size);
virtual dword Read(int64 at, void *ptr, dword size);
virtual void Write(int64 at, const void *data, dword size);
void RawSeek(int64 pos);
protected:
IStreamPtr istream;
int64 current_offset;
};
}
#endif