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