diff options
Diffstat (limited to 'src/VisVim/OleAut.cpp')
-rw-r--r-- | src/VisVim/OleAut.cpp | 781 |
1 files changed, 781 insertions, 0 deletions
diff --git a/src/VisVim/OleAut.cpp b/src/VisVim/OleAut.cpp new file mode 100644 index 0000000..6902df9 --- /dev/null +++ b/src/VisVim/OleAut.cpp @@ -0,0 +1,781 @@ +// +// Class for creating OLE automation controllers. +// +// CreateObject() creates an automation object +// Invoke() will call a property or method of the automation object. +// GetProperty() returns a property +// SetProperty() changes a property +// Method() invokes a method +// +// For example, the following VB code will control Microsoft Word: +// +// Private Sub Form_Load() +// Dim wb As Object +// Set wb = CreateObject("Word.Basic") +// wb.AppShow +// wb.FileNewDefault +// wb.Insert "This is a test" +// wb.FileSaveAs "c:\sample.doc)" +// End Sub +// +// A C++ automation controller that does the same can be written as follows: +// the helper functions: +// +// Void FormLoad () +// { +// COleAutomationControl Aut; +// Aut.CreateObject("Word.Basic"); +// Aut.Method ("AppShow"); +// Aut.Method ("FileNewDefault"); +// Aut.Method ("Insert", "s", (LPOLESTR) OLESTR ("This is a test")); +// Aut.Method ("FileSaveAs", "s", OLESTR ("c:\\sample.doc")); +// } +// +// + +#include "stdafx.h" +#include <stdarg.h> +#include "oleaut.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +static bool CountArgsInFormat (LPCTSTR Format, UINT* nArgs); +static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType); + + +COleAutomationControl::COleAutomationControl () +{ + m_pDispatch = NULL; + m_hResult = NOERROR; + m_nErrArg = 0; + VariantInit (&m_VariantResult); +} + +COleAutomationControl::~COleAutomationControl () +{ + DeleteObject (); +} + +void COleAutomationControl::DeleteObject () +{ + if (m_pDispatch) + { + m_pDispatch->Release (); + m_pDispatch = NULL; + } +} + +// Creates an instance of the Automation object and +// obtains it's IDispatch interface. +// +// Parameters: +// ProgId ProgID of Automation object +// +bool COleAutomationControl::CreateObject (char* ProgId) +{ + CLSID ClsId; // CLSID of automation object + LPUNKNOWN pUnknown = NULL; // IUnknown of automation object + + // Retrieve CLSID from the progID that the user specified + LPOLESTR OleProgId = TO_OLE_STR (ProgId); + m_hResult = CLSIDFromProgID (OleProgId, &ClsId); + if (FAILED (m_hResult)) + goto error; + + // Create an instance of the automation object and ask for the + // IDispatch interface + m_hResult = CoCreateInstance (ClsId, NULL, CLSCTX_SERVER, + IID_IUnknown, (void**) &pUnknown); + if (FAILED (m_hResult)) + goto error; + + m_hResult = pUnknown->QueryInterface (IID_IDispatch, (void**) &m_pDispatch); + if (FAILED (m_hResult)) + goto error; + + pUnknown->Release (); + return true; + +error: + if (pUnknown) + pUnknown->Release (); + if (m_pDispatch) + m_pDispatch->Release (); + return false; +} + +// Return the dispatch id of a named service +// This id can be used in subsequent calls to GetProperty (), SetProperty () and +// Method (). This is the preferred method when performance is important. +// +DISPID COleAutomationControl::GetDispatchId (char* Name) +{ + DISPID DispatchId; + + ASSERT (m_pDispatch); + + // Get DISPID of property/method + LPOLESTR OleName = TO_OLE_STR (Name); + m_hResult = m_pDispatch->GetIDsOfNames (IID_NULL, &OleName, 1, + LOCALE_USER_DEFAULT, &DispatchId); + if (FAILED (m_hResult)) + return NULL; + return DispatchId; +} + +// The following functions use these parameters: +// +// Parameters: +// +// Name Name of property or method. +// +// Format Format string that describes the variable list of parameters that +// follows. The format string can contain the following characters. +// & = mark the following format character as VT_BYREF +// B = VT_BOOL +// i = VT_I2 +// I = VT_I4 +// r = VT_R2 +// R = VT_R4 +// c = VT_CY +// s = VT_BSTR (string pointer can be passed, +// BSTR will be allocated by this function). +// e = VT_ERROR +// d = VT_DATE +// v = VT_VARIANT. Use this to pass data types that are not described +// in the format string. (For example SafeArrays). +// D = VT_DISPATCH +// U = VT_UNKNOWN +// +// ... Arguments of the property or method. +// Arguments are described by Format. +// + +bool COleAutomationControl::GetProperty (char* Name) +{ + return Invoke (DISPATCH_PROPERTYGET, Name, NULL, NULL); +} + +bool COleAutomationControl::GetProperty (DISPID DispatchId) +{ + return Invoke (DISPATCH_PROPERTYGET, DispatchId, NULL, NULL); +} + +bool COleAutomationControl::PutProperty (char* Name, LPCTSTR Format, ...) +{ + va_list ArgList; + + va_start (ArgList, Format); + bool bRet = Invoke (DISPATCH_PROPERTYPUT, Name, Format, ArgList); + va_end (ArgList); + return bRet; +} + +bool COleAutomationControl::PutProperty (DISPID DispatchId, LPCTSTR Format, ...) +{ + va_list ArgList; + + va_start (ArgList, Format); + bool bRet = Invoke (DISPATCH_PROPERTYPUT, DispatchId, Format, ArgList); + va_end (ArgList); + return bRet; +} + +bool COleAutomationControl::Method (char* Name, LPCTSTR Format, ...) +{ + va_list ArgList; + + va_start (ArgList, Format); + bool bRet = Invoke (DISPATCH_METHOD, Name, Format, ArgList); + va_end (ArgList); + return bRet; +} + +bool COleAutomationControl::Method (DISPID DispatchId, LPCTSTR Format, ...) +{ + va_list ArgList; + + va_start (ArgList, Format); + bool bRet = Invoke (DISPATCH_METHOD, DispatchId, Format, ArgList); + va_end (ArgList); + return bRet; +} + +bool COleAutomationControl::Invoke (WORD Flags, char* Name, + LPCTSTR Format, va_list ArgList) +{ + DISPID DispatchId = GetDispatchId (Name); + if (! DispatchId) + return false; + return Invoke (Flags, DispatchId, Format, ArgList); +} + +bool COleAutomationControl::Invoke (WORD Flags, DISPID DispatchId, + LPCTSTR Format, va_list ArgList) +{ + UINT ArgCount = 0; + VARIANTARG* ArgVector = NULL; + + ASSERT (m_pDispatch); + + DISPPARAMS DispatchParams; + memset (&DispatchParams, 0, sizeof (DispatchParams)); + + // Determine number of arguments + if (Format) + CountArgsInFormat (Format, &ArgCount); + + // Property puts have a named argument that represents the value that + // the property is being assigned. + DISPID DispIdNamed = DISPID_PROPERTYPUT; + if (Flags & DISPATCH_PROPERTYPUT) + { + if (ArgCount == 0) + { + m_hResult = ResultFromScode (E_INVALIDARG); + return false; + } + DispatchParams.cNamedArgs = 1; + DispatchParams.rgdispidNamedArgs = &DispIdNamed; + } + + if (ArgCount) + { + // Allocate memory for all VARIANTARG parameters + ArgVector = (VARIANTARG*) CoTaskMemAlloc ( + ArgCount * sizeof (VARIANTARG)); + if (! ArgVector) + { + m_hResult = ResultFromScode (E_OUTOFMEMORY); + return false; + } + memset (ArgVector, 0, sizeof (VARIANTARG) * ArgCount); + + // Get ready to walk vararg list + LPCTSTR s = Format; + + VARIANTARG *p = ArgVector + ArgCount - 1; // Params go in opposite order + + for (;;) + { + VariantInit (p); + if (! (s = GetNextVarType (s, &p->vt))) + break; + + if (p < ArgVector) + { + m_hResult = ResultFromScode (E_INVALIDARG); + goto Cleanup; + } + switch (p->vt) + { + case VT_I2: + V_I2 (p) = va_arg (ArgList, short); + break; + case VT_I4: + V_I4 (p) = va_arg (ArgList, long); + break; + case VT_R4: + V_R4 (p) = va_arg (ArgList, float); + break; + case VT_DATE: + case VT_R8: + V_R8 (p) = va_arg (ArgList, double); + break; + case VT_CY: + V_CY (p) = va_arg (ArgList, CY); + break; + case VT_BSTR: + V_BSTR (p) = SysAllocString (va_arg (ArgList, + OLECHAR*)); + if (! p->bstrVal) + { + m_hResult = ResultFromScode (E_OUTOFMEMORY); + p->vt = VT_EMPTY; + goto Cleanup; + } + break; + case VT_DISPATCH: + V_DISPATCH (p) = va_arg (ArgList, LPDISPATCH); + break; + case VT_ERROR: + V_ERROR (p) = va_arg (ArgList, SCODE); + break; + case VT_BOOL: + V_BOOL (p) = va_arg (ArgList, BOOL) ? -1 : 0; + break; + case VT_VARIANT: + *p = va_arg (ArgList, VARIANTARG); + break; + case VT_UNKNOWN: + V_UNKNOWN (p) = va_arg (ArgList, LPUNKNOWN); + break; + + case VT_I2 | VT_BYREF: + V_I2REF (p) = va_arg (ArgList, short*); + break; + case VT_I4 | VT_BYREF: + V_I4REF (p) = va_arg (ArgList, long*); + break; + case VT_R4 | VT_BYREF: + V_R4REF (p) = va_arg (ArgList, float*); + break; + case VT_R8 | VT_BYREF: + V_R8REF (p) = va_arg (ArgList, double*); + break; + case VT_DATE | VT_BYREF: + V_DATEREF (p) = va_arg (ArgList, DATE*); + break; + case VT_CY | VT_BYREF: + V_CYREF (p) = va_arg (ArgList, CY*); + break; + case VT_BSTR | VT_BYREF: + V_BSTRREF (p) = va_arg (ArgList, BSTR*); + break; + case VT_DISPATCH | VT_BYREF: + V_DISPATCHREF (p) = va_arg (ArgList, LPDISPATCH*); + break; + case VT_ERROR | VT_BYREF: + V_ERRORREF (p) = va_arg (ArgList, SCODE*); + break; + case VT_BOOL | VT_BYREF: + { + BOOL* pBool = va_arg (ArgList, BOOL*); + + *pBool = 0; + V_BOOLREF (p) = (VARIANT_BOOL*) pBool; + } + break; + case VT_VARIANT | VT_BYREF: + V_VARIANTREF (p) = va_arg (ArgList, VARIANTARG*); + break; + case VT_UNKNOWN | VT_BYREF: + V_UNKNOWNREF (p) = va_arg (ArgList, LPUNKNOWN*); + break; + + default: + { + m_hResult = ResultFromScode (E_INVALIDARG); + goto Cleanup; + } + break; + } + + --p; // Get ready to fill next argument + } + } + + DispatchParams.cArgs = ArgCount; + DispatchParams.rgvarg = ArgVector; + + // Initialize return variant, in case caller forgot. Caller can pass + // NULL if return value is not expected. + VariantInit (&m_VariantResult); + + // Make the call + m_hResult = m_pDispatch->Invoke (DispatchId, IID_NULL, LOCALE_USER_DEFAULT, + Flags, &DispatchParams, &m_VariantResult, + &m_ExceptionInfo, &m_nErrArg); + + Cleanup: + // Cleanup any arguments that need cleanup + if (ArgCount) + { + VARIANTARG* p = ArgVector; + + while (ArgCount--) + { + switch (p->vt) + { + case VT_BSTR: + VariantClear (p); + break; + } + ++p; + } + CoTaskMemFree (ArgVector); + } + + return FAILED (m_hResult) ? false : true; +} + +#define CASE_SCODE(sc) \ + case sc: \ + lstrcpy((char*)ErrName, (char*)#sc); \ + break; + +void COleAutomationControl::ErrDiag () +{ + char ErrName[200]; + + SCODE sc = GetScode (m_hResult); + switch (sc) + { + // SCODE's defined in SCODE.H + CASE_SCODE (S_OK) + CASE_SCODE (S_FALSE) + CASE_SCODE (E_UNEXPECTED) + CASE_SCODE (E_OUTOFMEMORY) + CASE_SCODE (E_INVALIDARG) + CASE_SCODE (E_NOINTERFACE) + CASE_SCODE (E_POINTER) + CASE_SCODE (E_HANDLE) + CASE_SCODE (E_ABORT) + CASE_SCODE (E_FAIL) + CASE_SCODE (E_ACCESSDENIED) + + // SCODE's defined in OLE2.H + CASE_SCODE (OLE_E_OLEVERB) + CASE_SCODE (OLE_E_ADVF) + CASE_SCODE (OLE_E_ENUM_NOMORE) + CASE_SCODE (OLE_E_ADVISENOTSUPPORTED) + CASE_SCODE (OLE_E_NOCONNECTION) + CASE_SCODE (OLE_E_NOTRUNNING) + CASE_SCODE (OLE_E_NOCACHE) + CASE_SCODE (OLE_E_BLANK) + CASE_SCODE (OLE_E_CLASSDIFF) + CASE_SCODE (OLE_E_CANT_GETMONIKER) + CASE_SCODE (OLE_E_CANT_BINDTOSOURCE) + CASE_SCODE (OLE_E_STATIC) + CASE_SCODE (OLE_E_PROMPTSAVECANCELLED) + CASE_SCODE (OLE_E_INVALIDRECT) + CASE_SCODE (OLE_E_WRONGCOMPOBJ) + CASE_SCODE (OLE_E_INVALIDHWND) + CASE_SCODE (OLE_E_NOT_INPLACEACTIVE) + CASE_SCODE (OLE_E_CANTCONVERT) + CASE_SCODE (OLE_E_NOSTORAGE) + + CASE_SCODE (DV_E_FORMATETC) + CASE_SCODE (DV_E_DVTARGETDEVICE) + CASE_SCODE (DV_E_STGMEDIUM) + CASE_SCODE (DV_E_STATDATA) + CASE_SCODE (DV_E_LINDEX) + CASE_SCODE (DV_E_TYMED) + CASE_SCODE (DV_E_CLIPFORMAT) + CASE_SCODE (DV_E_DVASPECT) + CASE_SCODE (DV_E_DVTARGETDEVICE_SIZE) + CASE_SCODE (DV_E_NOIVIEWOBJECT) + + CASE_SCODE (OLE_S_USEREG) + CASE_SCODE (OLE_S_STATIC) + CASE_SCODE (OLE_S_MAC_CLIPFORMAT) + + CASE_SCODE (CONVERT10_E_OLESTREAM_GET) + CASE_SCODE (CONVERT10_E_OLESTREAM_PUT) + CASE_SCODE (CONVERT10_E_OLESTREAM_FMT) + CASE_SCODE (CONVERT10_E_OLESTREAM_BITMAP_TO_DIB) + CASE_SCODE (CONVERT10_E_STG_FMT) + CASE_SCODE (CONVERT10_E_STG_NO_STD_STREAM) + CASE_SCODE (CONVERT10_E_STG_DIB_TO_BITMAP) + CASE_SCODE (CONVERT10_S_NO_PRESENTATION) + + CASE_SCODE (CLIPBRD_E_CANT_OPEN) + CASE_SCODE (CLIPBRD_E_CANT_EMPTY) + CASE_SCODE (CLIPBRD_E_CANT_SET) + CASE_SCODE (CLIPBRD_E_BAD_DATA) + CASE_SCODE (CLIPBRD_E_CANT_CLOSE) + + CASE_SCODE (DRAGDROP_E_NOTREGISTERED) + CASE_SCODE (DRAGDROP_E_ALREADYREGISTERED) + CASE_SCODE (DRAGDROP_E_INVALIDHWND) + CASE_SCODE (DRAGDROP_S_DROP) + CASE_SCODE (DRAGDROP_S_CANCEL) + CASE_SCODE (DRAGDROP_S_USEDEFAULTCURSORS) + + CASE_SCODE (OLEOBJ_E_NOVERBS) + CASE_SCODE (OLEOBJ_E_INVALIDVERB) + CASE_SCODE (OLEOBJ_S_INVALIDVERB) + CASE_SCODE (OLEOBJ_S_CANNOT_DOVERB_NOW) + CASE_SCODE (OLEOBJ_S_INVALIDHWND) + CASE_SCODE (INPLACE_E_NOTUNDOABLE) + CASE_SCODE (INPLACE_E_NOTOOLSPACE) + CASE_SCODE (INPLACE_S_TRUNCATED) + + // SCODE's defined in COMPOBJ.H + CASE_SCODE (CO_E_NOTINITIALIZED) + CASE_SCODE (CO_E_ALREADYINITIALIZED) + CASE_SCODE (CO_E_CANTDETERMINECLASS) + CASE_SCODE (CO_E_CLASSSTRING) + CASE_SCODE (CO_E_IIDSTRING) + CASE_SCODE (CO_E_APPNOTFOUND) + CASE_SCODE (CO_E_APPSINGLEUSE) + CASE_SCODE (CO_E_ERRORINAPP) + CASE_SCODE (CO_E_DLLNOTFOUND) + CASE_SCODE (CO_E_ERRORINDLL) + CASE_SCODE (CO_E_WRONGOSFORAPP) + CASE_SCODE (CO_E_OBJNOTREG) + CASE_SCODE (CO_E_OBJISREG) + CASE_SCODE (CO_E_OBJNOTCONNECTED) + CASE_SCODE (CO_E_APPDIDNTREG) + CASE_SCODE (CLASS_E_NOAGGREGATION) + CASE_SCODE (CLASS_E_CLASSNOTAVAILABLE) + CASE_SCODE (REGDB_E_READREGDB) + CASE_SCODE (REGDB_E_WRITEREGDB) + CASE_SCODE (REGDB_E_KEYMISSING) + CASE_SCODE (REGDB_E_INVALIDVALUE) + CASE_SCODE (REGDB_E_CLASSNOTREG) + CASE_SCODE (REGDB_E_IIDNOTREG) + CASE_SCODE (RPC_E_CALL_REJECTED) + CASE_SCODE (RPC_E_CALL_CANCELED) + CASE_SCODE (RPC_E_CANTPOST_INSENDCALL) + CASE_SCODE (RPC_E_CANTCALLOUT_INASYNCCALL) + CASE_SCODE (RPC_E_CANTCALLOUT_INEXTERNALCALL) + CASE_SCODE (RPC_E_CONNECTION_TERMINATED) + CASE_SCODE (RPC_E_SERVER_DIED) + CASE_SCODE (RPC_E_CLIENT_DIED) + CASE_SCODE (RPC_E_INVALID_DATAPACKET) + CASE_SCODE (RPC_E_CANTTRANSMIT_CALL) + CASE_SCODE (RPC_E_CLIENT_CANTMARSHAL_DATA) + CASE_SCODE (RPC_E_CLIENT_CANTUNMARSHAL_DATA) + CASE_SCODE (RPC_E_SERVER_CANTMARSHAL_DATA) + CASE_SCODE (RPC_E_SERVER_CANTUNMARSHAL_DATA) + CASE_SCODE (RPC_E_INVALID_DATA) + CASE_SCODE (RPC_E_INVALID_PARAMETER) + CASE_SCODE (RPC_E_CANTCALLOUT_AGAIN) + CASE_SCODE (RPC_E_UNEXPECTED) + + // SCODE's defined in DVOBJ.H + CASE_SCODE (DATA_S_SAMEFORMATETC) + CASE_SCODE (VIEW_E_DRAW) + CASE_SCODE (VIEW_S_ALREADY_FROZEN) + CASE_SCODE (CACHE_E_NOCACHE_UPDATED) + CASE_SCODE (CACHE_S_FORMATETC_NOTSUPPORTED) + CASE_SCODE (CACHE_S_SAMECACHE) + CASE_SCODE (CACHE_S_SOMECACHES_NOTUPDATED) + + // SCODE's defined in STORAGE.H + CASE_SCODE (STG_E_INVALIDFUNCTION) + CASE_SCODE (STG_E_FILENOTFOUND) + CASE_SCODE (STG_E_PATHNOTFOUND) + CASE_SCODE (STG_E_TOOMANYOPENFILES) + CASE_SCODE (STG_E_ACCESSDENIED) + CASE_SCODE (STG_E_INVALIDHANDLE) + CASE_SCODE (STG_E_INSUFFICIENTMEMORY) + CASE_SCODE (STG_E_INVALIDPOINTER) + CASE_SCODE (STG_E_NOMOREFILES) + CASE_SCODE (STG_E_DISKISWRITEPROTECTED) + CASE_SCODE (STG_E_SEEKERROR) + CASE_SCODE (STG_E_WRITEFAULT) + CASE_SCODE (STG_E_READFAULT) + CASE_SCODE (STG_E_SHAREVIOLATION) + CASE_SCODE (STG_E_LOCKVIOLATION) + CASE_SCODE (STG_E_FILEALREADYEXISTS) + CASE_SCODE (STG_E_INVALIDPARAMETER) + CASE_SCODE (STG_E_MEDIUMFULL) + CASE_SCODE (STG_E_ABNORMALAPIEXIT) + CASE_SCODE (STG_E_INVALIDHEADER) + CASE_SCODE (STG_E_INVALIDNAME) + CASE_SCODE (STG_E_UNKNOWN) + CASE_SCODE (STG_E_UNIMPLEMENTEDFUNCTION) + CASE_SCODE (STG_E_INVALIDFLAG) + CASE_SCODE (STG_E_INUSE) + CASE_SCODE (STG_E_NOTCURRENT) + CASE_SCODE (STG_E_REVERTED) + CASE_SCODE (STG_E_CANTSAVE) + CASE_SCODE (STG_E_OLDFORMAT) + CASE_SCODE (STG_E_OLDDLL) + CASE_SCODE (STG_E_SHAREREQUIRED) + CASE_SCODE (STG_E_NOTFILEBASEDSTORAGE) + CASE_SCODE (STG_E_EXTANTMARSHALLINGS) + CASE_SCODE (STG_S_CONVERTED) + + // SCODE's defined in STORAGE.H + CASE_SCODE (MK_E_CONNECTMANUALLY) + CASE_SCODE (MK_E_EXCEEDEDDEADLINE) + CASE_SCODE (MK_E_NEEDGENERIC) + CASE_SCODE (MK_E_UNAVAILABLE) + CASE_SCODE (MK_E_SYNTAX) + CASE_SCODE (MK_E_NOOBJECT) + CASE_SCODE (MK_E_INVALIDEXTENSION) + CASE_SCODE (MK_E_INTERMEDIATEINTERFACENOTSUPPORTED) + CASE_SCODE (MK_E_NOTBINDABLE) + CASE_SCODE (MK_E_NOTBOUND) + CASE_SCODE (MK_E_CANTOPENFILE) + CASE_SCODE (MK_E_MUSTBOTHERUSER) + CASE_SCODE (MK_E_NOINVERSE) + CASE_SCODE (MK_E_NOSTORAGE) + CASE_SCODE (MK_E_NOPREFIX) + CASE_SCODE (MK_S_REDUCED_TO_SELF) + CASE_SCODE (MK_S_ME) + CASE_SCODE (MK_S_HIM) + CASE_SCODE (MK_S_US) + CASE_SCODE (MK_S_MONIKERALREADYREGISTERED) + + // SCODE's defined in DISPATCH.H + CASE_SCODE (DISP_E_UNKNOWNINTERFACE) + CASE_SCODE (DISP_E_MEMBERNOTFOUND) + CASE_SCODE (DISP_E_PARAMNOTFOUND) + CASE_SCODE (DISP_E_TYPEMISMATCH) + CASE_SCODE (DISP_E_UNKNOWNNAME) + CASE_SCODE (DISP_E_NONAMEDARGS) + CASE_SCODE (DISP_E_BADVARTYPE) + CASE_SCODE (DISP_E_EXCEPTION) + CASE_SCODE (DISP_E_OVERFLOW) + CASE_SCODE (DISP_E_BADINDEX) + CASE_SCODE (DISP_E_UNKNOWNLCID) + CASE_SCODE (DISP_E_ARRAYISLOCKED) + CASE_SCODE (DISP_E_BADPARAMCOUNT) + CASE_SCODE (DISP_E_PARAMNOTOPTIONAL) + CASE_SCODE (DISP_E_BADCALLEE) + CASE_SCODE (DISP_E_NOTACOLLECTION) + + CASE_SCODE (TYPE_E_BUFFERTOOSMALL) + CASE_SCODE (TYPE_E_INVDATAREAD) + CASE_SCODE (TYPE_E_UNSUPFORMAT) + CASE_SCODE (TYPE_E_REGISTRYACCESS) + CASE_SCODE (TYPE_E_LIBNOTREGISTERED) + CASE_SCODE (TYPE_E_UNDEFINEDTYPE) + CASE_SCODE (TYPE_E_QUALIFIEDNAMEDISALLOWED) + CASE_SCODE (TYPE_E_INVALIDSTATE) + CASE_SCODE (TYPE_E_WRONGTYPEKIND) + CASE_SCODE (TYPE_E_ELEMENTNOTFOUND) + CASE_SCODE (TYPE_E_AMBIGUOUSNAME) + CASE_SCODE (TYPE_E_NAMECONFLICT) + CASE_SCODE (TYPE_E_UNKNOWNLCID) + CASE_SCODE (TYPE_E_DLLFUNCTIONNOTFOUND) + CASE_SCODE (TYPE_E_BADMODULEKIND) + CASE_SCODE (TYPE_E_SIZETOOBIG) + CASE_SCODE (TYPE_E_DUPLICATEID) + CASE_SCODE (TYPE_E_TYPEMISMATCH) + CASE_SCODE (TYPE_E_OUTOFBOUNDS) + CASE_SCODE (TYPE_E_IOERROR) + CASE_SCODE (TYPE_E_CANTCREATETMPFILE) + CASE_SCODE (TYPE_E_CANTLOADLIBRARY) + CASE_SCODE (TYPE_E_INCONSISTENTPROPFUNCS) + CASE_SCODE (TYPE_E_CIRCULARTYPE) + + default: + lstrcpy (ErrName, "UNKNOWN SCODE"); + } + + char Buf[256]; + sprintf (Buf, "An OLE error occurred:\r\nCode = %s\r\nResult = %lx.", + (char*) ErrName, m_hResult); + MessageBox (NULL, Buf, "OLE Error", MB_OK); +} + + +static bool CountArgsInFormat (LPCTSTR Format, UINT* pArgCount) +{ + *pArgCount = 0; + + if (! Format) + return true; + + while (*Format) + { + if (*Format == '&') + Format++; + + switch (*Format) + { + case 'b': + case 'i': + case 'I': + case 'r': + case 'R': + case 'c': + case 's': + case 'e': + case 'd': + case 'v': + case 'D': + case 'U': + ++ (*pArgCount); + Format++; + break; + case '\0': + default: + return false; + } + } + return true; +} + +static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType) +{ + *pVarType = 0; + if (*Format == '&') + { + *pVarType = VT_BYREF; + Format++; + if (!*Format) + return NULL; + } + switch (*Format) + { + case 'b': + *pVarType |= VT_BOOL; + break; + case 'i': + *pVarType |= VT_I2; + break; + case 'I': + *pVarType |= VT_I4; + break; + case 'r': + *pVarType |= VT_R4; + break; + case 'R': + *pVarType |= VT_R8; + break; + case 'c': + *pVarType |= VT_CY; + break; + case 's': + *pVarType |= VT_BSTR; + break; + case 'e': + *pVarType |= VT_ERROR; + break; + case 'd': + *pVarType |= VT_DATE; + break; + case 'v': + *pVarType |= VT_VARIANT; + break; + case 'U': + *pVarType |= VT_UNKNOWN; + break; + case 'D': + *pVarType |= VT_DISPATCH; + break; + case '\0': + return NULL; // End of Format string + default: + return NULL; + } + return ++Format; +} + +#ifndef UNICODE +char* ConvertToAnsi (OLECHAR* sUnicode) +{ + static char BufAscii[MAX_OLE_STR]; + return ConvertToAnsiBuf (sUnicode, BufAscii); +} + +char* ConvertToAnsiBuf (OLECHAR* sUnicode, char* BufAscii) +{ + WideCharToMultiByte (CP_ACP, 0, sUnicode, -1, BufAscii, MAX_OLE_STR, NULL, NULL); + return BufAscii; +} + +OLECHAR* ConvertToUnicode (char* sAscii) +{ + static OLECHAR BufUnicode[MAX_OLE_STR]; + return ConvertToUnicodeBuf (sAscii, BufUnicode); +} + +OLECHAR* ConvertToUnicodeBuf (char* sAscii, OLECHAR* BufUnicode) +{ + MultiByteToWideChar (CP_ACP, 0, sAscii, -1, BufUnicode, MAX_OLE_STR); + return BufUnicode; +} +#endif + |