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 43static char THIS_FILE[] = __FILE__; 44#endif 45 46 47static bool CountArgsInFormat (LPCTSTR Format, UINT* nArgs); 48static LPCTSTR GetNextVarType (LPCTSTR Format, VARTYPE* pVarType); 49 50 51COleAutomationControl::COleAutomationControl () 52{ 53 m_pDispatch = NULL; 54 m_hResult = NOERROR; 55 m_nErrArg = 0; 56 VariantInit (&m_VariantResult); 57} 58 59COleAutomationControl::~COleAutomationControl () 60{ 61 DeleteObject (); 62} 63 64void 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// 79bool 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 104error: 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 preferred method when performance is important. 115// 116DISPID 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 following 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 159bool COleAutomationControl::GetProperty (char* Name) 160{ 161 return Invoke (DISPATCH_PROPERTYGET, Name, NULL, NULL); 162} 163 164bool COleAutomationControl::GetProperty (DISPID DispatchId) 165{ 166 return Invoke (DISPATCH_PROPERTYGET, DispatchId, NULL, NULL); 167} 168 169bool 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 179bool 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 189bool 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 199bool 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 209bool 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 218bool 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 412void 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 663static 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 700static 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 757char* ConvertToAnsi (OLECHAR* sUnicode) 758{ 759 static char BufAscii[MAX_OLE_STR]; 760 return ConvertToAnsiBuf (sUnicode, BufAscii); 761} 762 763char* ConvertToAnsiBuf (OLECHAR* sUnicode, char* BufAscii) 764{ 765 WideCharToMultiByte (CP_ACP, 0, sUnicode, -1, BufAscii, MAX_OLE_STR, NULL, NULL); 766 return BufAscii; 767} 768 769OLECHAR* ConvertToUnicode (char* sAscii) 770{ 771 static OLECHAR BufUnicode[MAX_OLE_STR]; 772 return ConvertToUnicodeBuf (sAscii, BufUnicode); 773} 774 775OLECHAR* ConvertToUnicodeBuf (char* sAscii, OLECHAR* BufUnicode) 776{ 777 MultiByteToWideChar (CP_ACP, 0, sAscii, -1, BufUnicode, MAX_OLE_STR); 778 return BufUnicode; 779} 780#endif 781 782