OleAut.cpp
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:21k
源码类别:

编辑器/阅读器

开发平台:

DOS

  1. //
  2. // Class for creating OLE automation controllers.
  3. //
  4. // CreateObject() creates an automation object
  5. // Invoke() will call a property or method of the automation object.
  6. // GetProperty() returns a property
  7. // SetProperty() changes a property
  8. // Method() invokes a method
  9. //
  10. // For example, the following VB code will control Microsoft Word:
  11. //
  12. //    Private Sub Form_Load()
  13. //    Dim wb As Object
  14. //    Set wb = CreateObject("Word.Basic")
  15. //    wb.AppShow
  16. //    wb.FileNewDefault
  17. //    wb.Insert "This is a test"
  18. //    wb.FileSaveAs "c:sample.doc)"
  19. //    End Sub
  20. //
  21. // A C++ automation controller that does the same can be written as follows:
  22. // the helper functions:
  23. //
  24. //   Void FormLoad ()
  25. //   {
  26. //       COleAutomationControl Aut;
  27. //       Aut.CreateObject("Word.Basic");
  28. //       Aut.Method ("AppShow");
  29. //       Aut.Method ("FileNewDefault");
  30. //       Aut.Method ("Insert", "s", (LPOLESTR) OLESTR ("This is a test"));
  31. //       Aut.Method ("FileSaveAs", "s", OLESTR ("c:\sample.doc"));
  32. //   }
  33. //
  34. //
  35. #include "stdafx.h"
  36. #include <stdarg.h>
  37. #include "oleaut.h"
  38. #ifdef _DEBUG
  39. #define new DEBUG_NEW
  40. #undef THIS_FILE
  41. static char THIS_FILE[] = __FILE__;
  42. #endif
  43. static bool CountArgsInFormat (LPCTSTR Format, UINT* nArgs);
  44. static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType);
  45. COleAutomationControl::COleAutomationControl ()
  46. {
  47. m_pDispatch = NULL;
  48. m_hResult = NOERROR;
  49. m_nErrArg = 0;
  50. VariantInit (&m_VariantResult);
  51. }
  52. COleAutomationControl::~COleAutomationControl ()
  53. {
  54. DeleteObject ();
  55. }
  56. void COleAutomationControl::DeleteObject ()
  57. {
  58. if (m_pDispatch)
  59. {
  60. m_pDispatch->Release ();
  61. m_pDispatch = NULL;
  62. }
  63. }
  64. // Creates an instance of the Automation object and
  65. // obtains it's IDispatch interface.
  66. //
  67. // Parameters:
  68. // ProgId         ProgID of Automation object
  69. //
  70. bool COleAutomationControl::CreateObject (char* ProgId)
  71. {
  72. CLSID ClsId; // CLSID of automation object
  73. LPUNKNOWN pUnknown = NULL; // IUnknown of automation object
  74. // Retrieve CLSID from the progID that the user specified
  75. LPOLESTR OleProgId = TO_OLE_STR (ProgId);
  76. m_hResult = CLSIDFromProgID (OleProgId, &ClsId);
  77. if (FAILED (m_hResult))
  78. goto error;
  79. // Create an instance of the automation object and ask for the
  80. // IDispatch interface
  81. m_hResult = CoCreateInstance (ClsId, NULL, CLSCTX_SERVER,
  82.        IID_IUnknown, (void**) &pUnknown);
  83. if (FAILED (m_hResult))
  84. goto error;
  85. m_hResult = pUnknown->QueryInterface (IID_IDispatch, (void**) &m_pDispatch);
  86. if (FAILED (m_hResult))
  87. goto error;
  88. pUnknown->Release ();
  89. return true;
  90. error:
  91. if (pUnknown)
  92. pUnknown->Release ();
  93. if (m_pDispatch)
  94. m_pDispatch->Release ();
  95. return false;
  96. }
  97. // Return the dispatch id of a named service
  98. // This id can be used in subsequent calls to GetProperty (), SetProperty () and
  99. // Method (). This is the prefered method when performance is important.
  100. //
  101. DISPID COleAutomationControl::GetDispatchId (char* Name)
  102. {
  103. DISPID DispatchId;
  104. ASSERT (m_pDispatch);
  105. // Get DISPID of property/method
  106. LPOLESTR OleName = TO_OLE_STR (Name);
  107. m_hResult = m_pDispatch->GetIDsOfNames (IID_NULL, &OleName, 1,
  108. LOCALE_USER_DEFAULT, &DispatchId);
  109. if (FAILED (m_hResult))
  110. return NULL;
  111. return DispatchId;
  112. }
  113. //  The following functions use these parameters:
  114. //
  115. // Parameters:
  116. //
  117. //  Name      Name of property or method.
  118. //
  119. //  Format    Format string that describes the variable list of parameters that
  120. //            follows. The format string can contain the follwoing characters.
  121. //            & = mark the following format character as VT_BYREF
  122. //            B = VT_BOOL
  123. //            i = VT_I2
  124. //            I = VT_I4
  125. //            r = VT_R2
  126. //            R = VT_R4
  127. //            c = VT_CY
  128. //            s = VT_BSTR (string pointer can be passed,
  129. //                BSTR will be allocated by this function).
  130. //            e = VT_ERROR
  131. //            d = VT_DATE
  132. //            v = VT_VARIANT. Use this to pass data types that are not described
  133. // in the format string. (For example SafeArrays).
  134. //            D = VT_DISPATCH
  135. //            U = VT_UNKNOWN
  136. //
  137. //  ...       Arguments of the property or method.
  138. //            Arguments are described by Format.
  139. //
  140. bool COleAutomationControl::GetProperty (char* Name)
  141. {
  142. return Invoke (DISPATCH_PROPERTYGET, Name, NULL, NULL);
  143. }
  144. bool COleAutomationControl::GetProperty (DISPID DispatchId)
  145. {
  146. return Invoke (DISPATCH_PROPERTYGET, DispatchId, NULL, NULL);
  147. }
  148. bool COleAutomationControl::PutProperty (char* Name, LPCTSTR Format, ...)
  149. {
  150. va_list ArgList;
  151. va_start (ArgList, Format);
  152. bool bRet = Invoke (DISPATCH_PROPERTYPUT, Name, Format, ArgList);
  153. va_end (ArgList);
  154. return bRet;
  155. }
  156. bool COleAutomationControl::PutProperty (DISPID DispatchId, LPCTSTR Format, ...)
  157. {
  158. va_list ArgList;
  159. va_start (ArgList, Format);
  160. bool bRet = Invoke (DISPATCH_PROPERTYPUT, DispatchId, Format, ArgList);
  161. va_end (ArgList);
  162. return bRet;
  163. }
  164. bool COleAutomationControl::Method (char* Name, LPCTSTR Format, ...)
  165. {
  166. va_list ArgList;
  167. va_start (ArgList, Format);
  168. bool bRet = Invoke (DISPATCH_METHOD, Name, Format, ArgList);
  169. va_end (ArgList);
  170. return bRet;
  171. }
  172. bool COleAutomationControl::Method (DISPID DispatchId, LPCTSTR Format, ...)
  173. {
  174. va_list ArgList;
  175. va_start (ArgList, Format);
  176. bool bRet = Invoke (DISPATCH_METHOD, DispatchId, Format, ArgList);
  177. va_end (ArgList);
  178. return bRet;
  179. }
  180. bool COleAutomationControl::Invoke (WORD Flags, char* Name,
  181.     LPCTSTR Format, va_list ArgList)
  182. {
  183. DISPID DispatchId = GetDispatchId (Name);
  184. if (! DispatchId)
  185. return false;
  186. return Invoke (Flags, DispatchId, Format, ArgList);
  187. }
  188. bool COleAutomationControl::Invoke (WORD Flags, DISPID DispatchId,
  189.     LPCTSTR Format, va_list ArgList)
  190. {
  191. UINT ArgCount = 0;
  192. VARIANTARG* ArgVector = NULL;
  193. ASSERT (m_pDispatch);
  194. DISPPARAMS DispatchParams;
  195. memset (&DispatchParams, 0, sizeof (DispatchParams));
  196. // Determine number of arguments
  197. if (Format)
  198. CountArgsInFormat (Format, &ArgCount);
  199. // Property puts have a named argument that represents the value that
  200. // the property is being assigned.
  201. DISPID DispIdNamed = DISPID_PROPERTYPUT;
  202. if (Flags & DISPATCH_PROPERTYPUT)
  203. {
  204. if (ArgCount == 0)
  205. {
  206. m_hResult = ResultFromScode (E_INVALIDARG);
  207. return false;
  208. }
  209. DispatchParams.cNamedArgs = 1;
  210. DispatchParams.rgdispidNamedArgs = &DispIdNamed;
  211. }
  212. if (ArgCount)
  213. {
  214. // Allocate memory for all VARIANTARG parameters
  215. ArgVector = (VARIANTARG*) CoTaskMemAlloc (
  216. ArgCount * sizeof (VARIANTARG));
  217. if (! ArgVector)
  218. {
  219. m_hResult = ResultFromScode (E_OUTOFMEMORY);
  220. return false;
  221. }
  222. memset (ArgVector, 0, sizeof (VARIANTARG) * ArgCount);
  223. // Get ready to walk vararg list
  224. LPCTSTR s = Format;
  225. VARIANTARG *p = ArgVector + ArgCount - 1;  // Params go in opposite order
  226. for (;;)
  227. {
  228. VariantInit (p);
  229. if (! (s = GetNextVarType (s, &p->vt)))
  230. break;
  231. if (p < ArgVector)
  232. {
  233. m_hResult = ResultFromScode (E_INVALIDARG);
  234. goto Cleanup;
  235. }
  236. switch (p->vt)
  237. {
  238.     case VT_I2:
  239. V_I2 (p) = va_arg (ArgList, short);
  240. break;
  241.     case VT_I4:
  242. V_I4 (p) = va_arg (ArgList, long);
  243. break;
  244.     case VT_R4:
  245. V_R4 (p) = va_arg (ArgList, float);
  246. break;
  247.     case VT_DATE:
  248.     case VT_R8:
  249. V_R8 (p) = va_arg (ArgList, double);
  250. break;
  251.     case VT_CY:
  252. V_CY (p) = va_arg (ArgList, CY);
  253. break;
  254.     case VT_BSTR:
  255. V_BSTR (p) = SysAllocString (va_arg (ArgList,
  256. OLECHAR*));
  257. if (! p->bstrVal)
  258. {
  259. m_hResult = ResultFromScode (E_OUTOFMEMORY);
  260. p->vt = VT_EMPTY;
  261. goto Cleanup;
  262. }
  263. break;
  264.     case VT_DISPATCH:
  265. V_DISPATCH (p) = va_arg (ArgList, LPDISPATCH);
  266. break;
  267.     case VT_ERROR:
  268. V_ERROR (p) = va_arg (ArgList, SCODE);
  269. break;
  270.     case VT_BOOL:
  271. V_BOOL (p) = va_arg (ArgList, BOOL) ? -1 : 0;
  272. break;
  273.     case VT_VARIANT:
  274. *p = va_arg (ArgList, VARIANTARG);
  275. break;
  276.     case VT_UNKNOWN:
  277. V_UNKNOWN (p) = va_arg (ArgList, LPUNKNOWN);
  278. break;
  279.     case VT_I2 | VT_BYREF:
  280. V_I2REF (p) = va_arg (ArgList, short*);
  281. break;
  282.     case VT_I4 | VT_BYREF:
  283. V_I4REF (p) = va_arg (ArgList, long*);
  284. break;
  285.     case VT_R4 | VT_BYREF:
  286. V_R4REF (p) = va_arg (ArgList, float*);
  287. break;
  288.     case VT_R8 | VT_BYREF:
  289. V_R8REF (p) = va_arg (ArgList, double*);
  290. break;
  291.     case VT_DATE | VT_BYREF:
  292. V_DATEREF (p) = va_arg (ArgList, DATE*);
  293. break;
  294.     case VT_CY | VT_BYREF:
  295. V_CYREF (p) = va_arg (ArgList, CY*);
  296. break;
  297.     case VT_BSTR | VT_BYREF:
  298. V_BSTRREF (p) = va_arg (ArgList, BSTR*);
  299. break;
  300.     case VT_DISPATCH | VT_BYREF:
  301. V_DISPATCHREF (p) = va_arg (ArgList, LPDISPATCH*);
  302. break;
  303.     case VT_ERROR | VT_BYREF:
  304. V_ERRORREF (p) = va_arg (ArgList, SCODE*);
  305. break;
  306.     case VT_BOOL | VT_BYREF:
  307. {
  308. BOOL* pBool = va_arg (ArgList, BOOL*);
  309. *pBool = 0;
  310. V_BOOLREF (p) = (VARIANT_BOOL*) pBool;
  311. }
  312. break;
  313.     case VT_VARIANT | VT_BYREF:
  314. V_VARIANTREF (p) = va_arg (ArgList, VARIANTARG*);
  315. break;
  316.     case VT_UNKNOWN | VT_BYREF:
  317. V_UNKNOWNREF (p) = va_arg (ArgList, LPUNKNOWN*);
  318. break;
  319.     default:
  320. {
  321. m_hResult = ResultFromScode (E_INVALIDARG);
  322. goto Cleanup;
  323. }
  324. break;
  325. }
  326. --p; // Get ready to fill next argument
  327. }
  328. }
  329. DispatchParams.cArgs = ArgCount;
  330. DispatchParams.rgvarg = ArgVector;
  331. // Initialize return variant, in case caller forgot. Caller can pass
  332. // NULL if return value is not expected.
  333. VariantInit (&m_VariantResult);
  334. // Make the call
  335. m_hResult = m_pDispatch->Invoke (DispatchId, IID_NULL, LOCALE_USER_DEFAULT,
  336.  Flags, &DispatchParams, &m_VariantResult,
  337.  &m_ExceptionInfo, &m_nErrArg);
  338.     Cleanup:
  339. // Cleanup any arguments that need cleanup
  340. if (ArgCount)
  341. {
  342. VARIANTARG* p = ArgVector;
  343. while (ArgCount--)
  344. {
  345. switch (p->vt)
  346. {
  347.     case VT_BSTR:
  348. VariantClear (p);
  349. break;
  350. }
  351. ++p;
  352. }
  353. CoTaskMemFree (ArgVector);
  354. }
  355. return FAILED (m_hResult) ? false : true;
  356. }
  357. #define CASE_SCODE(sc)  
  358. case sc: 
  359. lstrcpy((char*)ErrName, (char*)#sc); 
  360. break;
  361. void COleAutomationControl::ErrDiag ()
  362. {
  363. char ErrName[200];
  364. SCODE sc = GetScode (m_hResult);
  365. switch (sc)
  366. {
  367.     // SCODE's defined in SCODE.H
  368.     CASE_SCODE (S_OK)
  369.     CASE_SCODE (S_FALSE)
  370.     CASE_SCODE (E_UNEXPECTED)
  371.     CASE_SCODE (E_OUTOFMEMORY)
  372.     CASE_SCODE (E_INVALIDARG)
  373.     CASE_SCODE (E_NOINTERFACE)
  374.     CASE_SCODE (E_POINTER)
  375.     CASE_SCODE (E_HANDLE)
  376.     CASE_SCODE (E_ABORT)
  377.     CASE_SCODE (E_FAIL)
  378.     CASE_SCODE (E_ACCESSDENIED)
  379.     // SCODE's defined in OLE2.H
  380.     CASE_SCODE (OLE_E_OLEVERB)
  381.     CASE_SCODE (OLE_E_ADVF)
  382.     CASE_SCODE (OLE_E_ENUM_NOMORE)
  383.     CASE_SCODE (OLE_E_ADVISENOTSUPPORTED)
  384.     CASE_SCODE (OLE_E_NOCONNECTION)
  385.     CASE_SCODE (OLE_E_NOTRUNNING)
  386.     CASE_SCODE (OLE_E_NOCACHE)
  387.     CASE_SCODE (OLE_E_BLANK)
  388.     CASE_SCODE (OLE_E_CLASSDIFF)
  389.     CASE_SCODE (OLE_E_CANT_GETMONIKER)
  390.     CASE_SCODE (OLE_E_CANT_BINDTOSOURCE)
  391.     CASE_SCODE (OLE_E_STATIC)
  392.     CASE_SCODE (OLE_E_PROMPTSAVECANCELLED)
  393.     CASE_SCODE (OLE_E_INVALIDRECT)
  394.     CASE_SCODE (OLE_E_WRONGCOMPOBJ)
  395.     CASE_SCODE (OLE_E_INVALIDHWND)
  396.     CASE_SCODE (OLE_E_NOT_INPLACEACTIVE)
  397.     CASE_SCODE (OLE_E_CANTCONVERT)
  398.     CASE_SCODE (OLE_E_NOSTORAGE)
  399.     CASE_SCODE (DV_E_FORMATETC)
  400.     CASE_SCODE (DV_E_DVTARGETDEVICE)
  401.     CASE_SCODE (DV_E_STGMEDIUM)
  402.     CASE_SCODE (DV_E_STATDATA)
  403.     CASE_SCODE (DV_E_LINDEX)
  404.     CASE_SCODE (DV_E_TYMED)
  405.     CASE_SCODE (DV_E_CLIPFORMAT)
  406.     CASE_SCODE (DV_E_DVASPECT)
  407.     CASE_SCODE (DV_E_DVTARGETDEVICE_SIZE)
  408.     CASE_SCODE (DV_E_NOIVIEWOBJECT)
  409.     CASE_SCODE (OLE_S_USEREG)
  410.     CASE_SCODE (OLE_S_STATIC)
  411.     CASE_SCODE (OLE_S_MAC_CLIPFORMAT)
  412.     CASE_SCODE (CONVERT10_E_OLESTREAM_GET)
  413.     CASE_SCODE (CONVERT10_E_OLESTREAM_PUT)
  414.     CASE_SCODE (CONVERT10_E_OLESTREAM_FMT)
  415.     CASE_SCODE (CONVERT10_E_OLESTREAM_BITMAP_TO_DIB)
  416.     CASE_SCODE (CONVERT10_E_STG_FMT)
  417.     CASE_SCODE (CONVERT10_E_STG_NO_STD_STREAM)
  418.     CASE_SCODE (CONVERT10_E_STG_DIB_TO_BITMAP)
  419.     CASE_SCODE (CONVERT10_S_NO_PRESENTATION)
  420.     CASE_SCODE (CLIPBRD_E_CANT_OPEN)
  421.     CASE_SCODE (CLIPBRD_E_CANT_EMPTY)
  422.     CASE_SCODE (CLIPBRD_E_CANT_SET)
  423.     CASE_SCODE (CLIPBRD_E_BAD_DATA)
  424.     CASE_SCODE (CLIPBRD_E_CANT_CLOSE)
  425.     CASE_SCODE (DRAGDROP_E_NOTREGISTERED)
  426.     CASE_SCODE (DRAGDROP_E_ALREADYREGISTERED)
  427.     CASE_SCODE (DRAGDROP_E_INVALIDHWND)
  428.     CASE_SCODE (DRAGDROP_S_DROP)
  429.     CASE_SCODE (DRAGDROP_S_CANCEL)
  430.     CASE_SCODE (DRAGDROP_S_USEDEFAULTCURSORS)
  431.     CASE_SCODE (OLEOBJ_E_NOVERBS)
  432.     CASE_SCODE (OLEOBJ_E_INVALIDVERB)
  433.     CASE_SCODE (OLEOBJ_S_INVALIDVERB)
  434.     CASE_SCODE (OLEOBJ_S_CANNOT_DOVERB_NOW)
  435.     CASE_SCODE (OLEOBJ_S_INVALIDHWND)
  436.     CASE_SCODE (INPLACE_E_NOTUNDOABLE)
  437.     CASE_SCODE (INPLACE_E_NOTOOLSPACE)
  438.     CASE_SCODE (INPLACE_S_TRUNCATED)
  439.     // SCODE's defined in COMPOBJ.H
  440.     CASE_SCODE (CO_E_NOTINITIALIZED)
  441.     CASE_SCODE (CO_E_ALREADYINITIALIZED)
  442.     CASE_SCODE (CO_E_CANTDETERMINECLASS)
  443.     CASE_SCODE (CO_E_CLASSSTRING)
  444.     CASE_SCODE (CO_E_IIDSTRING)
  445.     CASE_SCODE (CO_E_APPNOTFOUND)
  446.     CASE_SCODE (CO_E_APPSINGLEUSE)
  447.     CASE_SCODE (CO_E_ERRORINAPP)
  448.     CASE_SCODE (CO_E_DLLNOTFOUND)
  449.     CASE_SCODE (CO_E_ERRORINDLL)
  450.     CASE_SCODE (CO_E_WRONGOSFORAPP)
  451.     CASE_SCODE (CO_E_OBJNOTREG)
  452.     CASE_SCODE (CO_E_OBJISREG)
  453.     CASE_SCODE (CO_E_OBJNOTCONNECTED)
  454.     CASE_SCODE (CO_E_APPDIDNTREG)
  455.     CASE_SCODE (CLASS_E_NOAGGREGATION)
  456.     CASE_SCODE (CLASS_E_CLASSNOTAVAILABLE)
  457.     CASE_SCODE (REGDB_E_READREGDB)
  458.     CASE_SCODE (REGDB_E_WRITEREGDB)
  459.     CASE_SCODE (REGDB_E_KEYMISSING)
  460.     CASE_SCODE (REGDB_E_INVALIDVALUE)
  461.     CASE_SCODE (REGDB_E_CLASSNOTREG)
  462.     CASE_SCODE (REGDB_E_IIDNOTREG)
  463.     CASE_SCODE (RPC_E_CALL_REJECTED)
  464.     CASE_SCODE (RPC_E_CALL_CANCELED)
  465.     CASE_SCODE (RPC_E_CANTPOST_INSENDCALL)
  466.     CASE_SCODE (RPC_E_CANTCALLOUT_INASYNCCALL)
  467.     CASE_SCODE (RPC_E_CANTCALLOUT_INEXTERNALCALL)
  468.     CASE_SCODE (RPC_E_CONNECTION_TERMINATED)
  469.     CASE_SCODE (RPC_E_SERVER_DIED)
  470.     CASE_SCODE (RPC_E_CLIENT_DIED)
  471.     CASE_SCODE (RPC_E_INVALID_DATAPACKET)
  472.     CASE_SCODE (RPC_E_CANTTRANSMIT_CALL)
  473.     CASE_SCODE (RPC_E_CLIENT_CANTMARSHAL_DATA)
  474.     CASE_SCODE (RPC_E_CLIENT_CANTUNMARSHAL_DATA)
  475.     CASE_SCODE (RPC_E_SERVER_CANTMARSHAL_DATA)
  476.     CASE_SCODE (RPC_E_SERVER_CANTUNMARSHAL_DATA)
  477.     CASE_SCODE (RPC_E_INVALID_DATA)
  478.     CASE_SCODE (RPC_E_INVALID_PARAMETER)
  479.     CASE_SCODE (RPC_E_CANTCALLOUT_AGAIN)
  480.     CASE_SCODE (RPC_E_UNEXPECTED)
  481.     // SCODE's defined in DVOBJ.H
  482.     CASE_SCODE (DATA_S_SAMEFORMATETC)
  483.     CASE_SCODE (VIEW_E_DRAW)
  484.     CASE_SCODE (VIEW_S_ALREADY_FROZEN)
  485.     CASE_SCODE (CACHE_E_NOCACHE_UPDATED)
  486.     CASE_SCODE (CACHE_S_FORMATETC_NOTSUPPORTED)
  487.     CASE_SCODE (CACHE_S_SAMECACHE)
  488.     CASE_SCODE (CACHE_S_SOMECACHES_NOTUPDATED)
  489.     // SCODE's defined in STORAGE.H
  490.     CASE_SCODE (STG_E_INVALIDFUNCTION)
  491.     CASE_SCODE (STG_E_FILENOTFOUND)
  492.     CASE_SCODE (STG_E_PATHNOTFOUND)
  493.     CASE_SCODE (STG_E_TOOMANYOPENFILES)
  494.     CASE_SCODE (STG_E_ACCESSDENIED)
  495.     CASE_SCODE (STG_E_INVALIDHANDLE)
  496.     CASE_SCODE (STG_E_INSUFFICIENTMEMORY)
  497.     CASE_SCODE (STG_E_INVALIDPOINTER)
  498.     CASE_SCODE (STG_E_NOMOREFILES)
  499.     CASE_SCODE (STG_E_DISKISWRITEPROTECTED)
  500.     CASE_SCODE (STG_E_SEEKERROR)
  501.     CASE_SCODE (STG_E_WRITEFAULT)
  502.     CASE_SCODE (STG_E_READFAULT)
  503.     CASE_SCODE (STG_E_SHAREVIOLATION)
  504.     CASE_SCODE (STG_E_LOCKVIOLATION)
  505.     CASE_SCODE (STG_E_FILEALREADYEXISTS)
  506.     CASE_SCODE (STG_E_INVALIDPARAMETER)
  507.     CASE_SCODE (STG_E_MEDIUMFULL)
  508.     CASE_SCODE (STG_E_ABNORMALAPIEXIT)
  509.     CASE_SCODE (STG_E_INVALIDHEADER)
  510.     CASE_SCODE (STG_E_INVALIDNAME)
  511.     CASE_SCODE (STG_E_UNKNOWN)
  512.     CASE_SCODE (STG_E_UNIMPLEMENTEDFUNCTION)
  513.     CASE_SCODE (STG_E_INVALIDFLAG)
  514.     CASE_SCODE (STG_E_INUSE)
  515.     CASE_SCODE (STG_E_NOTCURRENT)
  516.     CASE_SCODE (STG_E_REVERTED)
  517.     CASE_SCODE (STG_E_CANTSAVE)
  518.     CASE_SCODE (STG_E_OLDFORMAT)
  519.     CASE_SCODE (STG_E_OLDDLL)
  520.     CASE_SCODE (STG_E_SHAREREQUIRED)
  521.     CASE_SCODE (STG_E_NOTFILEBASEDSTORAGE)
  522.     CASE_SCODE (STG_E_EXTANTMARSHALLINGS)
  523.     CASE_SCODE (STG_S_CONVERTED)
  524.     // SCODE's defined in STORAGE.H
  525.     CASE_SCODE (MK_E_CONNECTMANUALLY)
  526.     CASE_SCODE (MK_E_EXCEEDEDDEADLINE)
  527.     CASE_SCODE (MK_E_NEEDGENERIC)
  528.     CASE_SCODE (MK_E_UNAVAILABLE)
  529.     CASE_SCODE (MK_E_SYNTAX)
  530.     CASE_SCODE (MK_E_NOOBJECT)
  531.     CASE_SCODE (MK_E_INVALIDEXTENSION)
  532.     CASE_SCODE (MK_E_INTERMEDIATEINTERFACENOTSUPPORTED)
  533.     CASE_SCODE (MK_E_NOTBINDABLE)
  534.     CASE_SCODE (MK_E_NOTBOUND)
  535.     CASE_SCODE (MK_E_CANTOPENFILE)
  536.     CASE_SCODE (MK_E_MUSTBOTHERUSER)
  537.     CASE_SCODE (MK_E_NOINVERSE)
  538.     CASE_SCODE (MK_E_NOSTORAGE)
  539.     CASE_SCODE (MK_E_NOPREFIX)
  540.     CASE_SCODE (MK_S_REDUCED_TO_SELF)
  541.     CASE_SCODE (MK_S_ME)
  542.     CASE_SCODE (MK_S_HIM)
  543.     CASE_SCODE (MK_S_US)
  544.     CASE_SCODE (MK_S_MONIKERALREADYREGISTERED)
  545.     // SCODE's defined in DISPATCH.H
  546.     CASE_SCODE (DISP_E_UNKNOWNINTERFACE)
  547.     CASE_SCODE (DISP_E_MEMBERNOTFOUND)
  548.     CASE_SCODE (DISP_E_PARAMNOTFOUND)
  549.     CASE_SCODE (DISP_E_TYPEMISMATCH)
  550.     CASE_SCODE (DISP_E_UNKNOWNNAME)
  551.     CASE_SCODE (DISP_E_NONAMEDARGS)
  552.     CASE_SCODE (DISP_E_BADVARTYPE)
  553.     CASE_SCODE (DISP_E_EXCEPTION)
  554.     CASE_SCODE (DISP_E_OVERFLOW)
  555.     CASE_SCODE (DISP_E_BADINDEX)
  556.     CASE_SCODE (DISP_E_UNKNOWNLCID)
  557.     CASE_SCODE (DISP_E_ARRAYISLOCKED)
  558.     CASE_SCODE (DISP_E_BADPARAMCOUNT)
  559.     CASE_SCODE (DISP_E_PARAMNOTOPTIONAL)
  560.     CASE_SCODE (DISP_E_BADCALLEE)
  561.     CASE_SCODE (DISP_E_NOTACOLLECTION)
  562.     CASE_SCODE (TYPE_E_BUFFERTOOSMALL)
  563.     CASE_SCODE (TYPE_E_INVDATAREAD)
  564.     CASE_SCODE (TYPE_E_UNSUPFORMAT)
  565.     CASE_SCODE (TYPE_E_REGISTRYACCESS)
  566.     CASE_SCODE (TYPE_E_LIBNOTREGISTERED)
  567.     CASE_SCODE (TYPE_E_UNDEFINEDTYPE)
  568.     CASE_SCODE (TYPE_E_QUALIFIEDNAMEDISALLOWED)
  569.     CASE_SCODE (TYPE_E_INVALIDSTATE)
  570.     CASE_SCODE (TYPE_E_WRONGTYPEKIND)
  571.     CASE_SCODE (TYPE_E_ELEMENTNOTFOUND)
  572.     CASE_SCODE (TYPE_E_AMBIGUOUSNAME)
  573.     CASE_SCODE (TYPE_E_NAMECONFLICT)
  574.     CASE_SCODE (TYPE_E_UNKNOWNLCID)
  575.     CASE_SCODE (TYPE_E_DLLFUNCTIONNOTFOUND)
  576.     CASE_SCODE (TYPE_E_BADMODULEKIND)
  577.     CASE_SCODE (TYPE_E_SIZETOOBIG)
  578.     CASE_SCODE (TYPE_E_DUPLICATEID)
  579.     CASE_SCODE (TYPE_E_TYPEMISMATCH)
  580.     CASE_SCODE (TYPE_E_OUTOFBOUNDS)
  581.     CASE_SCODE (TYPE_E_IOERROR)
  582.     CASE_SCODE (TYPE_E_CANTCREATETMPFILE)
  583.     CASE_SCODE (TYPE_E_CANTLOADLIBRARY)
  584.     CASE_SCODE (TYPE_E_INCONSISTENTPROPFUNCS)
  585.     CASE_SCODE (TYPE_E_CIRCULARTYPE)
  586.     default:
  587. lstrcpy (ErrName, "UNKNOWN SCODE");
  588. }
  589. char Buf[256];
  590. sprintf (Buf, "An OLE error occured:rnCode = %srnResult = %lx.",
  591.  (char*) ErrName, m_hResult);
  592. MessageBox (NULL, Buf, "OLE Error", MB_OK);
  593. }
  594. static bool CountArgsInFormat (LPCTSTR Format, UINT* pArgCount)
  595. {
  596. *pArgCount = 0;
  597. if (! Format)
  598. return true;
  599. while (*Format)
  600. {
  601. if (*Format == '&')
  602. Format++;
  603. switch (*Format)
  604. {
  605.     case 'b':
  606.     case 'i':
  607.     case 'I':
  608.     case 'r':
  609.     case 'R':
  610.     case 'c':
  611.     case 's':
  612.     case 'e':
  613.     case 'd':
  614.     case 'v':
  615.     case 'D':
  616.     case 'U':
  617. ++*pArgCount;
  618. Format++;
  619. break;
  620.     case '':
  621.     default:
  622. return false;
  623. }
  624. }
  625. return true;
  626. }
  627. static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType)
  628. {
  629. *pVarType = 0;
  630. if (*Format == '&')
  631. {
  632. *pVarType = VT_BYREF;
  633. Format++;
  634. if (!*Format)
  635. return NULL;
  636. }
  637. switch (*Format)
  638. {
  639.     case 'b':
  640. *pVarType |= VT_BOOL;
  641. break;
  642.     case 'i':
  643. *pVarType |= VT_I2;
  644. break;
  645.     case 'I':
  646. *pVarType |= VT_I4;
  647. break;
  648.     case 'r':
  649. *pVarType |= VT_R4;
  650. break;
  651.     case 'R':
  652. *pVarType |= VT_R8;
  653. break;
  654.     case 'c':
  655. *pVarType |= VT_CY;
  656. break;
  657.     case 's':
  658. *pVarType |= VT_BSTR;
  659. break;
  660.     case 'e':
  661. *pVarType |= VT_ERROR;
  662. break;
  663.     case 'd':
  664. *pVarType |= VT_DATE;
  665. break;
  666.     case 'v':
  667. *pVarType |= VT_VARIANT;
  668. break;
  669.     case 'U':
  670. *pVarType |= VT_UNKNOWN;
  671. break;
  672.     case 'D':
  673. *pVarType |= VT_DISPATCH;
  674. break;
  675.     case '':
  676. return NULL; // End of Format string
  677.     default:
  678. return NULL;
  679. }
  680. return ++Format;
  681. }
  682. #ifndef UNICODE
  683. char* ConvertToAnsi (OLECHAR* sUnicode)
  684. {
  685. static char BufAscii[MAX_OLE_STR];
  686. return ConvertToAnsiBuf (sUnicode, BufAscii);
  687. char* ConvertToAnsiBuf (OLECHAR* sUnicode, char* BufAscii)
  688. {
  689. WideCharToMultiByte (CP_ACP, 0, sUnicode, -1, BufAscii, MAX_OLE_STR, NULL, NULL);
  690. return BufAscii;
  691. OLECHAR* ConvertToUnicode (char* sAscii)
  692. {
  693. static OLECHAR BufUnicode[MAX_OLE_STR]; 
  694. return ConvertToUnicodeBuf (sAscii, BufUnicode);
  695. }
  696. OLECHAR* ConvertToUnicodeBuf (char* sAscii, OLECHAR* BufUnicode)
  697. {
  698. MultiByteToWideChar (CP_ACP, 0, sAscii, -1, BufUnicode, MAX_OLE_STR);
  699. return BufUnicode;
  700. }
  701. #endif