|
|
1.1 ! root 1: /************************************************************************* ! 2: ** ! 3: ** OLE 2 Standard Utilities ! 4: ** ! 5: ** olestd.c ! 6: ** ! 7: ** This file contains utilities that are useful for most standard ! 8: ** OLE 2.0 compound document type applications. ! 9: ** ! 10: ** (c) Copyright Microsoft Corp. 1992 All Rights Reserved ! 11: ** ! 12: *************************************************************************/ ! 13: ! 14: #define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H) ! 15: ! 16: #define STRICT 1 ! 17: #include "ole2ui.h" ! 18: #include <stdlib.h> ! 19: #include <ctype.h> ! 20: #include <shellapi.h> ! 21: #include "regdb.h" ! 22: #include "geticon.h" ! 23: #include "common.h" ! 24: ! 25: OLEDBGDATA ! 26: ! 27: static char szAssertMemAlloc[] = "CoGetMalloc failed"; ! 28: ! 29: ! 30: /* OleStdSetupAdvises ! 31: ** ------------------ ! 32: ** Setup the standard View and Ole advises required by a standard, ! 33: ** compound document-oriented container. Such a container relies on ! 34: ** Ole to manage the presentation of the Ole object. The container ! 35: ** call IViewObject::Draw to render (display) the object. ! 36: ** ! 37: ** This helper routine performs the following tasks: ! 38: ** setup View advise ! 39: ** setup Ole advise ! 40: ** Call IOleObject::SetHostNames ! 41: ** Call OleSetContainedObject ! 42: */ ! 43: STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect, ! 44: LPSTR lpszContainerApp, LPSTR lpszContainerObj, ! 45: LPADVISESINK lpAdviseSink) ! 46: { ! 47: LPVIEWOBJECT lpViewObject; ! 48: HRESULT hrErr; ! 49: DWORD dwTemp; ! 50: BOOL fStatus = TRUE; ! 51: ! 52: hrErr = lpOleObject->lpVtbl->QueryInterface( ! 53: lpOleObject, ! 54: &IID_IViewObject, ! 55: (LPVOID FAR*)&lpViewObject ! 56: ); ! 57: ! 58: /* Setup View advise */ ! 59: if (hrErr == NOERROR) { ! 60: ! 61: OLEDBG_BEGIN2("IViewObject::SetAdvise called\r\n") ! 62: lpViewObject->lpVtbl->SetAdvise( ! 63: lpViewObject, ! 64: dwDrawAspect, ! 65: 0, ! 66: lpAdviseSink ! 67: ); ! 68: OLEDBG_END2 ! 69: ! 70: OleStdRelease((LPUNKNOWN)lpViewObject); ! 71: } else { ! 72: fStatus = FALSE; ! 73: } ! 74: ! 75: /* Setup OLE advise. ! 76: ** OLE2NOTE: normally containers do NOT need to setup an OLE ! 77: ** advise. this advise connection is only useful for the OLE's ! 78: ** DefHandler and the OleLink object implementation. some ! 79: ** special container's might need to setup this advise for ! 80: ** programatic reasons. ! 81: ** ! 82: ** NOTE: this advise will be torn down automatically by the ! 83: ** server when we release the object, therefore we do not need ! 84: ** to store the connection id. ! 85: */ ! 86: OLEDBG_BEGIN2("IOleObject::Advise called\r\n") ! 87: hrErr = lpOleObject->lpVtbl->Advise( ! 88: lpOleObject, ! 89: lpAdviseSink, ! 90: (DWORD FAR*)&dwTemp ! 91: ); ! 92: OLEDBG_END2 ! 93: if (hrErr != NOERROR) fStatus = FALSE; ! 94: ! 95: /* Setup the host names for the OLE object. */ ! 96: OLEDBG_BEGIN2("IOleObject::SetHostNames called\r\n") ! 97: hrErr = lpOleObject->lpVtbl->SetHostNames( ! 98: lpOleObject, ! 99: lpszContainerApp, ! 100: lpszContainerObj ! 101: ); ! 102: OLEDBG_END2 ! 103: if (hrErr != NOERROR) fStatus = FALSE; ! 104: ! 105: /* Inform the loadded object's handler/inproc-server that it is in ! 106: ** its embedding container's process. ! 107: */ ! 108: OLEDBG_BEGIN2("OleSetContainedObject(TRUE) called\r\n") ! 109: OleSetContainedObject((LPUNKNOWN)lpOleObject, TRUE); ! 110: OLEDBG_END2 ! 111: ! 112: return fStatus; ! 113: } ! 114: ! 115: ! 116: /* OleStdSwitchDisplayAspect ! 117: ** ------------------------- ! 118: ** Switch the currently cached display aspect between DVASPECT_ICON ! 119: ** and DVASPECT_CONTENT. ! 120: ** ! 121: ** NOTE: when setting up icon aspect, any currently cached content ! 122: ** cache is discarded and any advise connections for content aspect ! 123: ** are broken. ! 124: ** ! 125: ** RETURNS: ! 126: ** S_OK -- new display aspect setup successfully ! 127: ** E_INVALIDARG -- IOleCache interface is NOT supported (this is ! 128: ** required). ! 129: ** <other SCODE> -- any SCODE that can be returned by ! 130: ** IOleCache::Cache method. ! 131: ** NOTE: if an error occurs then the current display aspect and ! 132: ** cache contents unchanged. ! 133: */ ! 134: STDAPI OleStdSwitchDisplayAspect( ! 135: LPOLEOBJECT lpOleObj, ! 136: LPDWORD lpdwCurAspect, ! 137: DWORD dwNewAspect, ! 138: HGLOBAL hMetaPict, ! 139: BOOL fDeleteOldAspect, ! 140: BOOL fSetupViewAdvise, ! 141: LPADVISESINK lpAdviseSink, ! 142: BOOL FAR* lpfMustUpdate ! 143: ) ! 144: { ! 145: LPOLECACHE lpOleCache = NULL; ! 146: LPVIEWOBJECT lpViewObj = NULL; ! 147: LPENUMSTATDATA lpEnumStatData = NULL; ! 148: STATDATA StatData; ! 149: FORMATETC FmtEtc; ! 150: STGMEDIUM Medium; ! 151: DWORD dwAdvf; ! 152: DWORD dwNewConnection; ! 153: DWORD dwOldAspect = *lpdwCurAspect; ! 154: HRESULT hrErr; ! 155: ! 156: *lpfMustUpdate = FALSE; ! 157: ! 158: lpOleCache = (LPOLECACHE)OleStdQueryInterface( ! 159: (LPUNKNOWN)lpOleObj,&IID_IOleCache); ! 160: ! 161: // if IOleCache* is NOT available, do nothing ! 162: if (! lpOleCache) ! 163: return ResultFromScode(E_INVALIDARG); ! 164: ! 165: // Setup new cache with the new aspect ! 166: FmtEtc.cfFormat = CF_METAFILEPICT; ! 167: FmtEtc.ptd = NULL; ! 168: FmtEtc.dwAspect = dwNewAspect; ! 169: FmtEtc.lindex = -1; ! 170: FmtEtc.tymed = TYMED_MFPICT; ! 171: ! 172: /* OLE2NOTE: if we are setting up Icon aspect with a custom icon ! 173: ** then we do not want DataAdvise notifications to ever change ! 174: ** the contents of the data cache. thus we set up a NODATA ! 175: ** advise connection. otherwise we set up a standard DataAdvise ! 176: ** connection. ! 177: */ ! 178: if (dwNewAspect == DVASPECT_ICON && hMetaPict) ! 179: dwAdvf = ADVF_NODATA; ! 180: else ! 181: dwAdvf = ADVF_PRIMEFIRST; ! 182: ! 183: OLEDBG_BEGIN2("IOleCache::Cache called\r\n") ! 184: hrErr = lpOleCache->lpVtbl->Cache( ! 185: lpOleCache, ! 186: (LPFORMATETC)&FmtEtc, ! 187: dwAdvf, ! 188: (LPDWORD)&dwNewConnection ! 189: ); ! 190: OLEDBG_END2 ! 191: ! 192: if (! SUCCEEDED(hrErr)) { ! 193: OleDbgOutHResult("IOleCache::Cache returned", hrErr); ! 194: OleStdRelease((LPUNKNOWN)lpOleCache); ! 195: return hrErr; ! 196: } ! 197: ! 198: *lpdwCurAspect = dwNewAspect; ! 199: ! 200: /* OLE2NOTE: if we are setting up Icon aspect with a custom icon, ! 201: ** then stuff the icon into the cache. otherwise force the cache ! 202: ** to be updated. this will run the object if necessary. ! 203: */ ! 204: if (dwNewAspect == DVASPECT_ICON && hMetaPict) { ! 205: ! 206: Medium.tymed = TYMED_MFPICT; ! 207: Medium.u.hGlobal = hMetaPict; ! 208: Medium.pUnkForRelease = NULL; ! 209: ! 210: OLEDBG_BEGIN2("IOleCache::SetData called\r\n") ! 211: hrErr = lpOleCache->lpVtbl->SetData( ! 212: lpOleCache, ! 213: (LPFORMATETC)&FmtEtc, ! 214: (LPSTGMEDIUM)&Medium, ! 215: FALSE /* fRelease */ ! 216: ); ! 217: OLEDBG_END2 ! 218: } else { ! 219: *lpfMustUpdate = TRUE; ! 220: } ! 221: ! 222: if (fSetupViewAdvise && lpAdviseSink) { ! 223: /* OLE2NOTE: re-establish the ViewAdvise connection */ ! 224: lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface( ! 225: (LPUNKNOWN)lpOleObj,&IID_IViewObject); ! 226: ! 227: if (lpViewObj) { ! 228: ! 229: OLEDBG_BEGIN2("IViewObject::SetAdvise called\r\n") ! 230: lpViewObj->lpVtbl->SetAdvise( ! 231: lpViewObj, ! 232: dwNewAspect, ! 233: 0, ! 234: lpAdviseSink ! 235: ); ! 236: OLEDBG_END2 ! 237: ! 238: OleStdRelease((LPUNKNOWN)lpViewObj); ! 239: } ! 240: } ! 241: ! 242: /* OLE2NOTE: remove any existing caches that are set up for the old ! 243: ** display aspect. It WOULD be possible to retain the caches set ! 244: ** up for the old aspect, but this would increase the storage ! 245: ** space required for the object and possibly require additional ! 246: ** overhead to maintain the unused cachaes. For these reasons the ! 247: ** strategy to delete the previous caches is prefered. if it is a ! 248: ** requirement to quickly switch between Icon and Content ! 249: ** display, then it would be better to keep both aspect caches. ! 250: */ ! 251: ! 252: if (fDeleteOldAspect) { ! 253: OLEDBG_BEGIN2("IOleCache::EnumCache called\r\n") ! 254: hrErr = lpOleCache->lpVtbl->EnumCache( ! 255: lpOleCache, ! 256: (LPENUMSTATDATA FAR*)&lpEnumStatData ! 257: ); ! 258: OLEDBG_END2 ! 259: ! 260: while(hrErr == NOERROR) { ! 261: hrErr = lpEnumStatData->lpVtbl->Next( ! 262: lpEnumStatData, ! 263: 1, ! 264: (LPSTATDATA)&StatData, ! 265: NULL ! 266: ); ! 267: if (hrErr != NOERROR) ! 268: break; // DONE! no more caches. ! 269: ! 270: if (StatData.formatetc.dwAspect == dwOldAspect) { ! 271: ! 272: // Remove previous cache with old aspect ! 273: OLEDBG_BEGIN2("IOleCache::Uncache called\r\n") ! 274: lpOleCache->lpVtbl->Uncache(lpOleCache,StatData.dwConnection); ! 275: OLEDBG_END2 ! 276: } ! 277: } ! 278: ! 279: if (lpEnumStatData) { ! 280: OleStdVerifyRelease( ! 281: (LPUNKNOWN)lpEnumStatData, ! 282: "OleStdSwitchDisplayAspect: Cache enumerator NOT released" ! 283: ); ! 284: } ! 285: } ! 286: ! 287: if (lpOleCache) ! 288: OleStdRelease((LPUNKNOWN)lpOleCache); ! 289: ! 290: return NOERROR; ! 291: } ! 292: ! 293: ! 294: /* OleStdSetIconInCache ! 295: ** -------------------- ! 296: ** SetData a new icon into the existing DVASPECT_ICON cache. ! 297: ** ! 298: ** RETURNS: ! 299: ** HRESULT returned from IOleCache::SetData ! 300: */ ! 301: STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict) ! 302: { ! 303: LPOLECACHE lpOleCache = NULL; ! 304: FORMATETC FmtEtc; ! 305: STGMEDIUM Medium; ! 306: HRESULT hrErr; ! 307: ! 308: if (! hMetaPict) ! 309: return FALSE; // invalid icon ! 310: ! 311: lpOleCache = (LPOLECACHE)OleStdQueryInterface( ! 312: (LPUNKNOWN)lpOleObj,&IID_IOleCache); ! 313: if (! lpOleCache) ! 314: return FALSE; // if IOleCache* is NOT available, do nothing ! 315: ! 316: FmtEtc.cfFormat = CF_METAFILEPICT; ! 317: FmtEtc.ptd = NULL; ! 318: FmtEtc.dwAspect = DVASPECT_ICON; ! 319: FmtEtc.lindex = -1; ! 320: FmtEtc.tymed = TYMED_MFPICT; ! 321: ! 322: // stuff the icon into the cache. ! 323: Medium.tymed = TYMED_MFPICT; ! 324: Medium.u.hGlobal = hMetaPict; ! 325: Medium.pUnkForRelease = NULL; ! 326: ! 327: OLEDBG_BEGIN2("IOleCache::SetData called\r\n") ! 328: hrErr = lpOleCache->lpVtbl->SetData( ! 329: lpOleCache, ! 330: (LPFORMATETC)&FmtEtc, ! 331: (LPSTGMEDIUM)&Medium, ! 332: FALSE /* fRelease */ ! 333: ); ! 334: OLEDBG_END2 ! 335: ! 336: OleStdRelease((LPUNKNOWN)lpOleCache); ! 337: ! 338: return hrErr; ! 339: } ! 340: ! 341: ! 342: ! 343: /* OleStdDoConvert ! 344: ** --------------- ! 345: ** Do the container-side responsibilities for converting an object. ! 346: ** This function would be used in conjunction with the OleUIConvert ! 347: ** dialog. If the user selects to convert an object then the ! 348: ** container must do the following: ! 349: ** 1. unload the object. ! 350: ** 2. write the NEW CLSID and NEW user type name ! 351: ** string into the storage of the object, ! 352: ** BUT write the OLD format tag. ! 353: ** 3. force an update of the object to force the actual ! 354: ** conversion of the data bits. ! 355: ** ! 356: ** This function takes care of step 2. ! 357: */ ! 358: STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew) ! 359: { ! 360: HRESULT error; ! 361: CLSID clsidOld; ! 362: CLIPFORMAT cfOld; ! 363: LPSTR lpszOld = NULL; ! 364: char szNew[OLEUI_CCHKEYMAX]; ! 365: ! 366: if ((error = ReadClassStg(lpStg, &clsidOld)) != NOERROR) { ! 367: clsidOld = CLSID_NULL; ! 368: goto errRtn; ! 369: } ! 370: ! 371: // read old fmt/old user type; sets out params to NULL on error ! 372: error = ReadFmtUserTypeStg(lpStg, &cfOld, &lpszOld); ! 373: OleDbgAssert(error == NOERROR || (cfOld == 0 && lpszOld == NULL)); ! 374: ! 375: // get new user type name; if error, set to NULL string ! 376: if (OleStdGetUserTypeOfClass( ! 377: (LPCLSID)rClsidNew, szNew,sizeof(szNew),NULL /* hKey */) == 0) ! 378: szNew[0] = '\0'; ! 379: ! 380: // write class stg ! 381: if ((error = WriteClassStg(lpStg, rClsidNew)) != NOERROR) ! 382: goto errRtn; ! 383: ! 384: // write old fmt/new user type; ! 385: if ((error = WriteFmtUserTypeStg(lpStg, cfOld, szNew)) != NOERROR) ! 386: goto errRewriteInfo; ! 387: ! 388: // set convert bit ! 389: if ((error = SetConvertStg(lpStg, TRUE)) != NOERROR) ! 390: goto errRewriteInfo; ! 391: ! 392: // Commit the changes to make them permanent in the storage ! 393: OleStdCommitStorage(lpStg); ! 394: goto okRtn; ! 395: ! 396: errRewriteInfo: ! 397: (void)WriteClassStg(lpStg, &clsidOld); ! 398: (void)WriteFmtUserTypeStg(lpStg, cfOld, lpszOld); ! 399: ! 400: errRtn: ! 401: ! 402: okRtn: ! 403: OleStdFreeString(lpszOld, NULL); ! 404: return error; ! 405: } ! 406: ! 407: ! 408: /* OleStdGetTreatAsFmtUserType ! 409: ** --------------------------- ! 410: ** Determine if the application should perform a TreatAs (ActivateAs ! 411: ** object or emulation) operation for the object that is stored in ! 412: ** the storage. ! 413: ** ! 414: ** if the CLSID written in the storage is not the same as the ! 415: ** application's own CLSID (clsidApp), then a TreatAs operation ! 416: ** should take place. if so determine the format the data should be ! 417: ** written and the user type name of the object the app should ! 418: ** emulate (ie. pretend to be). if this information is not written ! 419: ** in the storage then it is looked up in the REGDB. if it can not ! 420: ** be found in the REGDB, then the TreatAs operation can NOT be ! 421: ** executed. ! 422: ** ! 423: ** RETURNS: TRUE -- if TreatAs should be performed. ! 424: ** valid lpclsid, lplpszType, lpcfFmt to TreatAs are returned ! 425: ** (NOTE: lplpszType must be freed by caller) ! 426: ** FALSE -- NO TreatAs. lpszType will be NULL. ! 427: ** lpclsid = CLSID_NULL; lplpszType = lpcfFmt = NULL; ! 428: */ ! 429: STDAPI_(BOOL) OleStdGetTreatAsFmtUserType( ! 430: REFCLSID rclsidApp, ! 431: LPSTORAGE lpStg, ! 432: CLSID FAR* lpclsid, ! 433: CLIPFORMAT FAR* lpcfFmt, ! 434: LPSTR FAR* lplpszType ! 435: ) ! 436: { ! 437: HRESULT hrErr; ! 438: HKEY hKey; ! 439: LONG lRet; ! 440: UINT lSize; ! 441: char szBuf[OLEUI_CCHKEYMAX]; ! 442: ! 443: *lpclsid = CLSID_NULL; ! 444: *lpcfFmt = 0; ! 445: *lplpszType = NULL; ! 446: ! 447: hrErr = ReadClassStg(lpStg, lpclsid); ! 448: if (hrErr == NOERROR && ! 449: ! IsEqualCLSID(lpclsid, &CLSID_NULL) && ! 450: ! IsEqualCLSID(lpclsid, rclsidApp)) { ! 451: ! 452: hrErr = ReadFmtUserTypeStg(lpStg,(CLIPFORMAT FAR*)lpcfFmt,lplpszType); ! 453: if (hrErr == NOERROR && lplpszType && *lpcfFmt != 0) ! 454: return TRUE; // Do TreatAs. info was in lpStg. ! 455: ! 456: /* read info from REGDB ! 457: ** *lpcfFmt = value of field: CLSID\{...}\DataFormats\DefaultFile ! 458: ** *lplpszType = value of field: CLSID\{...} ! 459: */ ! 460: //Open up the root key. ! 461: lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey); ! 462: if (lRet != (LONG)ERROR_SUCCESS) ! 463: return FALSE; ! 464: *lpcfFmt = OleStdGetDefaultFileFormatOfClass(lpclsid, hKey); ! 465: if (*lpcfFmt == 0) ! 466: return FALSE; ! 467: lSize = OleStdGetUserTypeOfClass(lpclsid,szBuf,sizeof(szBuf),hKey); ! 468: if (lSize == 0) ! 469: return FALSE; ! 470: *lplpszType = OleStdCopyString(szBuf, NULL); ! 471: } else { ! 472: return FALSE; // NO TreatAs ! 473: } ! 474: } ! 475: ! 476: ! 477: ! 478: /* OleStdDoConvert ! 479: ** --------------- ! 480: ** Do the container-side responsibilities for "ActivateAs" (aka. ! 481: ** TreatAs) for an object. ! 482: ** This function would be used in conjunction with the OleUIConvert ! 483: ** dialog. If the user selects to ActivateAs an object then the ! 484: ** container must do the following: ! 485: ** 1. unload ALL objects of the OLD class that app knows about ! 486: ** 2. add the TreatAs tag in the registration database ! 487: ** by calling CoTreatAsClass(). ! 488: ** 3. lazily it can reload the objects; when the objects ! 489: ** are reloaded the TreatAs will take effect. ! 490: ** ! 491: ** This function takes care of step 2. ! 492: */ ! 493: STDAPI OleStdDoTreatAsClass(LPSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew) ! 494: { ! 495: HRESULT hrErr; ! 496: LPSTR lpszCLSID = NULL; ! 497: LONG lRet; ! 498: HKEY hKey; ! 499: ! 500: OLEDBG_BEGIN2("CoTreatAsClass called\r\n") ! 501: hrErr = CoTreatAsClass(rclsid, rclsidNew); ! 502: OLEDBG_END2 ! 503: ! 504: if ((hrErr != NOERROR) && lpszUserType) { ! 505: lRet = RegOpenKey(HKEY_CLASSES_ROOT, (LPCSTR)"CLSID", ! 506: (HKEY FAR *)&hKey); ! 507: StringFromCLSID(rclsid, (LPSTR FAR*)&lpszCLSID); ! 508: RegSetValue(hKey, lpszCLSID, REG_SZ, lpszUserType, ! 509: lstrlen(lpszUserType)); ! 510: ! 511: if (lpszCLSID) ! 512: OleStdFreeString(lpszCLSID, NULL); ! 513: ! 514: hrErr = CoTreatAsClass(rclsid, rclsidNew); ! 515: RegCloseKey(hKey); ! 516: } ! 517: ! 518: return hrErr; ! 519: } ! 520: ! 521: ! 522: ! 523: /* OleStdIsOleLink ! 524: ** --------------- ! 525: ** Returns TRUE if the OleObject is infact an OLE link object. this ! 526: ** checks if IOleLink interface is supported. if so, the object is a ! 527: ** link, otherwise not. ! 528: */ ! 529: STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk) ! 530: { ! 531: LPOLELINK lpOleLink; ! 532: ! 533: lpOleLink = (LPOLELINK)OleStdQueryInterface(lpUnk, &IID_IOleLink); ! 534: ! 535: if (lpOleLink) { ! 536: OleStdRelease((LPUNKNOWN)lpOleLink); ! 537: return TRUE; ! 538: } else ! 539: return FALSE; ! 540: } ! 541: ! 542: ! 543: /* OleStdQueryInterface ! 544: ** -------------------- ! 545: ** Returns the desired interface pointer if exposed by the given object. ! 546: ** Returns NULL if the interface is not available. ! 547: ** eg.: ! 548: ** lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject); ! 549: */ ! 550: STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid) ! 551: { ! 552: LPUNKNOWN lpInterface; ! 553: HRESULT hrErr; ! 554: ! 555: hrErr = lpUnk->lpVtbl->QueryInterface( ! 556: lpUnk, ! 557: riid, ! 558: (LPVOID FAR*)&lpInterface ! 559: ); ! 560: ! 561: if (hrErr == NOERROR) ! 562: return lpInterface; ! 563: else ! 564: return NULL; ! 565: } ! 566: ! 567: ! 568: /* OleStdGetData ! 569: ** ------------- ! 570: ** Retrieve data from an IDataObject in a specified format on a ! 571: ** global memory block. This function ALWAYS returns a private copy ! 572: ** of the data to the caller. if necessary a copy is made of the ! 573: ** data (ie. if lpMedium->pUnkForRelease != NULL). The caller assumes ! 574: ** ownership of the data block in all cases and must free the data ! 575: ** when done with it. The caller may directly free the data handle ! 576: ** returned (taking care whether it is a simple HGLOBAL or a HANDLE ! 577: ** to a MetafilePict) or the caller may call ! 578: ** ReleaseStgMedium(lpMedium). this OLE helper function will do the ! 579: ** right thing. ! 580: ** ! 581: ** PARAMETERS: ! 582: ** LPDATAOBJECT lpDataObj -- object on which GetData should be ! 583: ** called. ! 584: ** CLIPFORMAT cfFormat -- desired clipboard format (eg. CF_TEXT) ! 585: ** DVTARGETDEVICE FAR* lpTargetDevice -- target device for which ! 586: ** the data should be composed. This may ! 587: ** be NULL. NULL can be used whenever the ! 588: ** data format is insensitive to target ! 589: ** device or when the caller does not care ! 590: ** what device is used. ! 591: ** LPSTGMEDIUM lpMedium -- ptr to STGMEDIUM struct. the ! 592: ** resultant medium from the ! 593: ** IDataObject::GetData call is ! 594: ** returned. ! 595: ** ! 596: ** RETURNS: ! 597: ** HGLOBAL -- global memory handle of retrieved data block. ! 598: ** NULL -- if error. ! 599: */ ! 600: STDAPI_(HGLOBAL) OleStdGetData( ! 601: LPDATAOBJECT lpDataObj, ! 602: CLIPFORMAT cfFormat, ! 603: DVTARGETDEVICE FAR* lpTargetDevice, ! 604: DWORD dwAspect, ! 605: LPSTGMEDIUM lpMedium ! 606: ) ! 607: { ! 608: HRESULT hrErr; ! 609: FORMATETC formatetc; ! 610: HGLOBAL hGlobal = NULL; ! 611: HGLOBAL hCopy; ! 612: LPVOID lp; ! 613: ! 614: formatetc.cfFormat = cfFormat; ! 615: formatetc.ptd = lpTargetDevice; ! 616: formatetc.dwAspect = dwAspect; ! 617: formatetc.lindex = -1; ! 618: ! 619: switch (cfFormat) { ! 620: case CF_METAFILEPICT: ! 621: formatetc.tymed = TYMED_MFPICT; ! 622: break; ! 623: ! 624: case CF_BITMAP: ! 625: formatetc.tymed = TYMED_GDI; ! 626: break; ! 627: ! 628: default: ! 629: formatetc.tymed = TYMED_HGLOBAL; ! 630: break; ! 631: } ! 632: ! 633: OLEDBG_BEGIN2("IDataObject::GetData called\r\n") ! 634: hrErr = lpDataObj->lpVtbl->GetData( ! 635: lpDataObj, ! 636: (LPFORMATETC)&formatetc, ! 637: lpMedium ! 638: ); ! 639: OLEDBG_END2 ! 640: ! 641: if (hrErr != NOERROR) ! 642: return NULL; ! 643: ! 644: if ((hGlobal = lpMedium->u.hGlobal) == NULL) ! 645: return NULL; ! 646: ! 647: // Check if hGlobal really points to valid memory ! 648: if ((lp = GlobalLock(hGlobal)) != NULL) { ! 649: if (IsBadReadPtr(lp, 1)) { ! 650: GlobalUnlock(hGlobal); ! 651: return NULL; // ERROR: memory is NOT valid ! 652: } ! 653: GlobalUnlock(hGlobal); ! 654: } ! 655: ! 656: if (hGlobal != NULL && lpMedium->pUnkForRelease != NULL) { ! 657: /* OLE2NOTE: the callee wants to retain ownership of the data. ! 658: ** this is indicated by passing a non-NULL pUnkForRelease. ! 659: ** thus, we will make a copy of the data and release the ! 660: ** callee's copy. ! 661: */ ! 662: ! 663: hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE); ! 664: ReleaseStgMedium(lpMedium); // release callee's copy of data ! 665: ! 666: hGlobal = hCopy; ! 667: lpMedium->u.hGlobal = hCopy; ! 668: lpMedium->pUnkForRelease = NULL; ! 669: } ! 670: return hGlobal; ! 671: } ! 672: ! 673: ! 674: /* OleStdMalloc ! 675: ** ------------ ! 676: ** allocate memory using the currently active IMalloc* allocator ! 677: */ ! 678: STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize) ! 679: { ! 680: LPVOID pout; ! 681: LPMALLOC pmalloc; ! 682: ! 683: if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) { ! 684: OleDbgAssertSz(0, szAssertMemAlloc); ! 685: return NULL; ! 686: } ! 687: ! 688: pout = (LPVOID)pmalloc->lpVtbl->Alloc(pmalloc, ulSize); ! 689: ! 690: if (pmalloc != NULL) { ! 691: ULONG refs = pmalloc->lpVtbl->Release(pmalloc); ! 692: } ! 693: ! 694: return pout; ! 695: } ! 696: ! 697: ! 698: /* OleStdRealloc ! 699: ** ------------- ! 700: ** re-allocate memory using the currently active IMalloc* allocator ! 701: */ ! 702: STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize) ! 703: { ! 704: LPVOID pout; ! 705: LPMALLOC pmalloc; ! 706: ! 707: if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) { ! 708: OleDbgAssertSz(0, szAssertMemAlloc); ! 709: return NULL; ! 710: } ! 711: ! 712: pout = (LPVOID)pmalloc->lpVtbl->Realloc(pmalloc, pmem, ulSize); ! 713: ! 714: if (pmalloc != NULL) { ! 715: ULONG refs = pmalloc->lpVtbl->Release(pmalloc); ! 716: } ! 717: ! 718: return pout; ! 719: } ! 720: ! 721: ! 722: /* OleStdFree ! 723: ** ---------- ! 724: ** free memory using the currently active IMalloc* allocator ! 725: */ ! 726: STDAPI_(void) OleStdFree(LPVOID pmem) ! 727: { ! 728: LPMALLOC pmalloc; ! 729: ! 730: if (pmem == NULL) ! 731: return; ! 732: ! 733: if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) { ! 734: OleDbgAssertSz(0, szAssertMemAlloc); ! 735: return; ! 736: } ! 737: ! 738: pmalloc->lpVtbl->Free(pmalloc, pmem); ! 739: ! 740: if (pmalloc != NULL) { ! 741: ULONG refs = pmalloc->lpVtbl->Release(pmalloc); ! 742: } ! 743: ! 744: } ! 745: ! 746: ! 747: /* OleStdGetSize ! 748: ** ------------- ! 749: ** Get the size of a memory block that was allocated using the ! 750: ** currently active IMalloc* allocator. ! 751: */ ! 752: STDAPI_(ULONG) OleStdGetSize(LPVOID pmem) ! 753: { ! 754: ULONG ulSize; ! 755: LPMALLOC pmalloc; ! 756: ! 757: if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != S_OK) { ! 758: OleDbgAssertSz(0, szAssertMemAlloc); ! 759: return (ULONG)-1; ! 760: } ! 761: ! 762: ulSize = pmalloc->lpVtbl->GetSize(pmalloc, pmem); ! 763: ! 764: if (pmalloc != NULL) { ! 765: ULONG refs = pmalloc->lpVtbl->Release(pmalloc); ! 766: } ! 767: ! 768: return ulSize; ! 769: } ! 770: ! 771: ! 772: /* OleStdFreeString ! 773: ** ---------------- ! 774: ** Free a string that was allocated with the currently active ! 775: ** IMalloc* allocator. ! 776: ** ! 777: ** if the caller has the current IMalloc* handy, then it can be ! 778: ** passed as a argument, otherwise this function will retrieve the ! 779: ** active allocator and use it. ! 780: */ ! 781: STDAPI_(void) OleStdFreeString(LPSTR lpsz, LPMALLOC lpMalloc) ! 782: { ! 783: BOOL fMustRelease = FALSE; ! 784: ! 785: if (! lpMalloc) { ! 786: if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR) ! 787: return; ! 788: fMustRelease = TRUE; ! 789: } ! 790: ! 791: lpMalloc->lpVtbl->Free(lpMalloc, lpsz); ! 792: ! 793: if (fMustRelease) ! 794: OleStdRelease((LPUNKNOWN)lpMalloc); ! 795: } ! 796: ! 797: ! 798: /* OleStdCopyString ! 799: ** ---------------- ! 800: ** Copy a string into memory allocated with the currently active ! 801: ** IMalloc* allocator. ! 802: ** ! 803: ** if the caller has the current IMalloc* handy, then it can be ! 804: ** passed as a argument, otherwise this function will retrieve the ! 805: ** active allocator and use it. ! 806: */ ! 807: STDAPI_(LPSTR) OleStdCopyString(LPSTR lpszSrc, LPMALLOC lpMalloc) ! 808: { ! 809: LPSTR lpszDest = NULL; ! 810: BOOL fMustRelease = FALSE; ! 811: UINT lSize = lstrlen(lpszSrc); ! 812: ! 813: if (! lpMalloc) { ! 814: if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR) ! 815: return NULL; ! 816: fMustRelease = TRUE; ! 817: } ! 818: ! 819: lpszDest = lpMalloc->lpVtbl->Alloc(lpMalloc, lSize+1); ! 820: ! 821: if (lpszDest) ! 822: lstrcpy(lpszDest, lpszSrc); ! 823: ! 824: if (fMustRelease) ! 825: OleStdRelease((LPUNKNOWN)lpMalloc); ! 826: return lpszDest; ! 827: } ! 828: ! 829: ! 830: /* ! 831: * OleStdCreateStorageOnHGlobal() ! 832: * ! 833: * Purpose: ! 834: * Create a memory based IStorage*. ! 835: * ! 836: * OLE2NOTE: if fDeleteOnRelease==TRUE, then the ILockBytes is created ! 837: * such that it will delete them memory on its last release. ! 838: * the IStorage on created on top of the ILockBytes in NOT ! 839: * created with STGM_DELETEONRELEASE. when the IStorage receives ! 840: * its last release, it will release the ILockBytes which will ! 841: * in turn free the memory. it is in fact an error to specify ! 842: * STGM_DELETEONRELEASE in this situation. ! 843: * ! 844: * Parameters: ! 845: * hGlobal -- handle to MEM_SHARE allocated memory. may be NULL and ! 846: * memory will be automatically allocated. ! 847: * fDeleteOnRelease -- controls if the memory is freed on the last release. ! 848: * grfMode -- flags passed to StgCreateDocfileOnILockBytes ! 849: * ! 850: * NOTE: if hGlobal is NULL, then a new IStorage is created and ! 851: * STGM_CREATE flag is passed to StgCreateDocfileOnILockBytes. ! 852: * if hGlobal is non-NULL, then it is assumed that the hGlobal already ! 853: * has an IStorage inside it and STGM_CONVERT flag is passed ! 854: * to StgCreateDocfileOnILockBytes. ! 855: * ! 856: * Return Value: ! 857: * SCODE - S_OK if successful ! 858: */ ! 859: STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal( ! 860: HANDLE hGlobal, ! 861: BOOL fDeleteOnRelease, ! 862: DWORD grfMode ! 863: ) ! 864: { ! 865: DWORD grfCreateMode=grfMode | (hGlobal==NULL ? STGM_CREATE:STGM_CONVERT); ! 866: HRESULT hrErr; ! 867: LPLOCKBYTES lpLockBytes = NULL; ! 868: DWORD reserved = 0; ! 869: LPSTORAGE lpStg = NULL; ! 870: ! 871: hrErr = CreateILockBytesOnHGlobal( ! 872: hGlobal, ! 873: fDeleteOnRelease, ! 874: (LPLOCKBYTES FAR*)&lpLockBytes ! 875: ); ! 876: if (hrErr != NOERROR) ! 877: return NULL; ! 878: ! 879: hrErr = StgCreateDocfileOnILockBytes( ! 880: lpLockBytes, ! 881: grfCreateMode, ! 882: reserved, ! 883: (LPSTORAGE FAR*)&lpStg ! 884: ); ! 885: if (hrErr != NOERROR) { ! 886: OleStdRelease((LPUNKNOWN)lpLockBytes); ! 887: return NULL; ! 888: } ! 889: return lpStg; ! 890: } ! 891: ! 892: ! 893: ! 894: /* ! 895: * OleStdCreateTempStorage() ! 896: * ! 897: * Purpose: ! 898: * Create a temporay IStorage* that will DeleteOnRelease. ! 899: * this can be either memory based or file based. ! 900: * ! 901: * Parameters: ! 902: * fUseMemory -- controls if memory-based or file-based stg is created ! 903: * grfMode -- storage mode flags ! 904: * ! 905: * Return Value: ! 906: * LPSTORAGE - if successful, NULL otherwise ! 907: */ ! 908: STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode) ! 909: { ! 910: LPSTORAGE lpstg; ! 911: HRESULT hrErr; ! 912: DWORD reserved = 0; ! 913: ! 914: if (fUseMemory) { ! 915: lpstg = OleStdCreateStorageOnHGlobal( ! 916: NULL, /* auto allocate */ ! 917: TRUE, /* delete on release */ ! 918: grfMode ! 919: ); ! 920: } else { ! 921: /* allocate a temp docfile that will delete on last release */ ! 922: hrErr = StgCreateDocfile( ! 923: NULL, ! 924: grfMode | STGM_DELETEONRELEASE | STGM_CREATE, ! 925: reserved, ! 926: &lpstg ! 927: ); ! 928: if (hrErr != NOERROR) ! 929: return NULL; ! 930: } ! 931: return lpstg; ! 932: } ! 933: ! 934: ! 935: /* OleStdGetOleObjectData ! 936: ** ---------------------- ! 937: ** Render CF_EMBEDSOURCE/CF_EMBEDDEDOBJECT data on an TYMED_ISTORAGE ! 938: ** medium by asking the object to save into the storage. ! 939: ** the object must support IPersistStorage. ! 940: ** ! 941: ** if lpMedium->tymed == TYMED_NULL, then a delete-on-release ! 942: ** storage is allocated (either file-based or memory-base depending ! 943: ** the value of fUseMemory). this is useful to support an ! 944: ** IDataObject::GetData call where the callee must allocate the ! 945: ** medium. ! 946: ** ! 947: ** if lpMedium->tymed == TYMED_ISTORAGE, then the data is writen ! 948: ** into the passed in IStorage. this is useful to support an ! 949: ** IDataObject::GetDataHere call where the caller has allocated his ! 950: ** own IStorage. ! 951: */ ! 952: STDAPI OleStdGetOleObjectData( ! 953: LPPERSISTSTORAGE lpPStg, ! 954: LPFORMATETC lpformatetc, ! 955: LPSTGMEDIUM lpMedium, ! 956: BOOL fUseMemory ! 957: ) ! 958: { ! 959: LPSTORAGE lpstg = NULL; ! 960: DWORD reserved = 0; ! 961: SCODE sc = S_OK; ! 962: HRESULT hrErr; ! 963: ! 964: lpMedium->pUnkForRelease = NULL; ! 965: ! 966: if (lpMedium->tymed == TYMED_NULL) { ! 967: ! 968: if (lpformatetc->tymed & TYMED_ISTORAGE) { ! 969: ! 970: /* allocate a temp docfile that will delete on last release */ ! 971: lpstg = OleStdCreateTempStorage( ! 972: TRUE /*fUseMemory*/, ! 973: STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE ! 974: ); ! 975: if (!lpstg) ! 976: return ResultFromScode(E_OUTOFMEMORY); ! 977: ! 978: lpMedium->u.pstg = lpstg; ! 979: lpMedium->tymed = TYMED_ISTORAGE; ! 980: lpMedium->pUnkForRelease = NULL; ! 981: } else { ! 982: return ResultFromScode(DATA_E_FORMATETC); ! 983: } ! 984: } else if (lpMedium->tymed == TYMED_ISTORAGE) { ! 985: lpMedium->tymed = TYMED_ISTORAGE; ! 986: } else { ! 987: return ResultFromScode(DATA_E_FORMATETC); ! 988: } ! 989: ! 990: // OLE2NOTE: even if OleSave returns an error you should still call ! 991: // SaveCompleted. ! 992: ! 993: OLEDBG_BEGIN2("OleSave called\r\n") ! 994: hrErr = OleSave(lpPStg, lpMedium->u.pstg, FALSE /* fSameAsLoad */); ! 995: OLEDBG_END2 ! 996: ! 997: if (hrErr != NOERROR) { ! 998: OleDbgOutHResult("WARNING: OleSave returned", hrErr); ! 999: sc = GetScode(hrErr); ! 1000: } ! 1001: OLEDBG_BEGIN2("IPersistStorage::SaveCompleted called\r\n") ! 1002: hrErr = lpPStg->lpVtbl->SaveCompleted(lpPStg, NULL); ! 1003: OLEDBG_END2 ! 1004: ! 1005: if (hrErr != NOERROR) { ! 1006: OleDbgOutHResult("WARNING: SaveCompleted returned",hrErr); ! 1007: if (sc == S_OK) ! 1008: sc = GetScode(hrErr); ! 1009: } ! 1010: ! 1011: return ResultFromScode(sc); ! 1012: } ! 1013: ! 1014: ! 1015: STDAPI OleStdGetLinkSourceData( ! 1016: LPMONIKER lpmk, ! 1017: LPCLSID lpClsID, ! 1018: LPFORMATETC lpformatetc, ! 1019: LPSTGMEDIUM lpMedium ! 1020: ) ! 1021: { ! 1022: LPSTREAM lpstm = NULL; ! 1023: DWORD reserved = 0; ! 1024: HRESULT hrErr; ! 1025: ! 1026: if (lpMedium->tymed == TYMED_NULL) { ! 1027: if (lpformatetc->tymed & TYMED_ISTREAM) { ! 1028: hrErr = CreateStreamOnHGlobal( ! 1029: NULL, /* auto allocate */ ! 1030: TRUE, /* delete on release */ ! 1031: (LPSTREAM FAR*)&lpstm ! 1032: ); ! 1033: if (hrErr != NOERROR) { ! 1034: lpMedium->pUnkForRelease = NULL; ! 1035: return ResultFromScode(E_OUTOFMEMORY); ! 1036: } ! 1037: lpMedium->u.pstm = lpstm; ! 1038: lpMedium->tymed = TYMED_ISTREAM; ! 1039: lpMedium->pUnkForRelease = NULL; ! 1040: } else { ! 1041: lpMedium->pUnkForRelease = NULL; ! 1042: return ResultFromScode(DATA_E_FORMATETC); ! 1043: } ! 1044: } else { ! 1045: if (lpMedium->tymed == TYMED_ISTREAM) { ! 1046: lpMedium->tymed = TYMED_ISTREAM; ! 1047: lpMedium->u.pstm = lpMedium->u.pstm; ! 1048: lpMedium->pUnkForRelease = NULL; ! 1049: } else { ! 1050: lpMedium->pUnkForRelease = NULL; ! 1051: return ResultFromScode(DATA_E_FORMATETC); ! 1052: } ! 1053: } ! 1054: ! 1055: hrErr = OleSaveToStream((LPPERSISTSTREAM)lpmk, lpMedium->u.pstm); ! 1056: if (hrErr != NOERROR) return hrErr; ! 1057: return WriteClassStm(lpMedium->u.pstm, lpClsID); ! 1058: } ! 1059: ! 1060: /* ! 1061: * OleStdGetObjectDescriptorData ! 1062: * ! 1063: * Purpose: ! 1064: * Fills and returns a OBJECTDESCRIPTOR structure. ! 1065: * See OBJECTDESCRIPTOR for more information. ! 1066: * ! 1067: * Parameters: ! 1068: * clsid CLSID CLSID of object being transferred ! 1069: * dwAspect DWORD Display Aspect of object ! 1070: * sizel SIZEL Size of object in HIMETRIC ! 1071: * pointl POINTL Offset from upper-left corner of object where mouse went ! 1072: * down for drag. Meaningful only when drag-drop is used. ! 1073: * dwStatus DWORD OLEMISC flags ! 1074: * lpszFullUserTypeName LPSTR Full User Type Name ! 1075: * lpszSrcOfCopy LPSTR Source of Copy ! 1076: * ! 1077: * Return Value: ! 1078: * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. ! 1079: */ ! 1080: STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData( ! 1081: CLSID clsid, ! 1082: DWORD dwAspect, ! 1083: SIZEL sizel, ! 1084: POINTL pointl, ! 1085: DWORD dwStatus, ! 1086: LPSTR lpszFullUserTypeName, ! 1087: LPSTR lpszSrcOfCopy ! 1088: ) ! 1089: { ! 1090: HGLOBAL hMem = NULL; ! 1091: IBindCtx FAR *pbc = NULL; ! 1092: LPOBJECTDESCRIPTOR lpOD; ! 1093: DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen; ! 1094: ! 1095: // Get the length of Full User Type Name; Add 1 for the null terminator ! 1096: dwFullUserTypeNameLen = lpszFullUserTypeName ? lstrlen(lpszFullUserTypeName)+1 : 0; ! 1097: ! 1098: // Get the Source of Copy string and it's length; Add 1 for the null terminator ! 1099: if (lpszSrcOfCopy) ! 1100: dwSrcOfCopyLen = lstrlen(lpszSrcOfCopy)+1; ! 1101: else { ! 1102: // No src moniker so use user type name as source string. ! 1103: lpszSrcOfCopy = lpszFullUserTypeName; ! 1104: dwSrcOfCopyLen = dwFullUserTypeNameLen; ! 1105: } ! 1106: ! 1107: // Allocate space for OBJECTDESCRIPTOR and the additional string data ! 1108: dwObjectDescSize = sizeof(OBJECTDESCRIPTOR); ! 1109: hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, ! 1110: dwObjectDescSize + dwFullUserTypeNameLen + dwSrcOfCopyLen); ! 1111: if (NULL == hMem) ! 1112: goto error; ! 1113: ! 1114: lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem); ! 1115: ! 1116: // Set the FullUserTypeName offset and copy the string ! 1117: if (lpszFullUserTypeName) ! 1118: { ! 1119: lpOD->dwFullUserTypeName = dwObjectDescSize; ! 1120: lstrcpy((LPSTR)lpOD+lpOD->dwFullUserTypeName , lpszFullUserTypeName); ! 1121: } ! 1122: else lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present ! 1123: ! 1124: // Set the SrcOfCopy offset and copy the string ! 1125: if (lpszSrcOfCopy) ! 1126: { ! 1127: lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen; ! 1128: lstrcpy((LPSTR)lpOD+lpOD->dwSrcOfCopy , lpszSrcOfCopy); ! 1129: } ! 1130: else lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present ! 1131: ! 1132: // Initialize the rest of the OBJECTDESCRIPTOR ! 1133: lpOD->cbSize = dwObjectDescSize + dwFullUserTypeNameLen + dwSrcOfCopyLen; ! 1134: lpOD->clsid = clsid; ! 1135: lpOD->dwDrawAspect = dwAspect; ! 1136: lpOD->sizel = sizel; ! 1137: lpOD->pointl = pointl; ! 1138: lpOD->dwStatus = dwStatus; ! 1139: ! 1140: GlobalUnlock(hMem); ! 1141: return hMem; ! 1142: ! 1143: error: ! 1144: if (hMem) ! 1145: { ! 1146: GlobalUnlock(hMem); ! 1147: GlobalFree(hMem); ! 1148: } ! 1149: return NULL; ! 1150: } ! 1151: ! 1152: /* ! 1153: * OleStdGetObjectDescriptorDataFromOleObject ! 1154: * ! 1155: * Purpose: ! 1156: * Fills and returns a OBJECTDESCRIPTOR structure. Information for the structure is ! 1157: * obtained from an OLEOBJECT. ! 1158: * See OBJECTDESCRIPTOR for more information. ! 1159: * ! 1160: * Parameters: ! 1161: * lpOleObj LPOLEOBJECT OleObject from which ONJECTDESCRIPTOR info ! 1162: * is obtained. ! 1163: * lpszSrcOfCopy LPSTR string to identify source of copy. ! 1164: * May be NULL in which case IOleObject::GetMoniker is called ! 1165: * to get the moniker of the object. if the object is loaded ! 1166: * as part of a data transfer document, then usually ! 1167: * lpOleClientSite==NULL is passed to OleLoad when loading ! 1168: * the object. in this case the IOleObject:GetMoniker call ! 1169: * will always fail (it tries to call back to the object's ! 1170: * client site). in this situation a non-NULL lpszSrcOfCopy ! 1171: * parameter should be passed. ! 1172: * dwAspect DWORD Display Aspect of object ! 1173: * pointl POINTL Offset from upper-left corner of object where mouse went ! 1174: * down for drag. Meaningful only when drag-drop is used. ! 1175: * ! 1176: * Return Value: ! 1177: * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. ! 1178: */ ! 1179: ! 1180: STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject( ! 1181: LPOLEOBJECT lpOleObj, ! 1182: LPSTR lpszSrcOfCopy, ! 1183: DWORD dwAspect, ! 1184: POINTL pointl ! 1185: ) ! 1186: { ! 1187: CLSID clsid; ! 1188: LPSTR lpszFullUserTypeName = NULL; ! 1189: LPMONIKER lpSrcMonikerOfCopy = NULL; ! 1190: HGLOBAL hObjDesc; ! 1191: IBindCtx FAR *pbc = NULL; ! 1192: HRESULT hrErr; ! 1193: SIZEL sizel; ! 1194: BOOL fFreeSrcOfCopy = FALSE; ! 1195: LPOLELINK lpOleLink = ! 1196: (LPOLELINK)OleStdQueryInterface((LPUNKNOWN)lpOleObj,&IID_IOleLink); ! 1197: BOOL fIsLink = (lpOleLink ? TRUE : FALSE); ! 1198: char szLinkedTypeFmt[80]; ! 1199: LPSTR lpszBuf = NULL; ! 1200: DWORD dwStatus = 0; ! 1201: ! 1202: // Get CLSID ! 1203: OLEDBG_BEGIN2("IOleObject::GetUserClassID called\r\n") ! 1204: hrErr = lpOleObj->lpVtbl->GetUserClassID(lpOleObj, &clsid); ! 1205: OLEDBG_END2 ! 1206: if (hrErr != NOERROR) ! 1207: clsid = CLSID_NULL; ! 1208: ! 1209: // Get FullUserTypeName ! 1210: OLEDBG_BEGIN2("IOleObject::GetUserType called\r\n") ! 1211: hrErr = lpOleObj->lpVtbl->GetUserType( ! 1212: lpOleObj, ! 1213: USERCLASSTYPE_FULL, ! 1214: (LPSTR FAR*)&lpszFullUserTypeName ! 1215: ); ! 1216: OLEDBG_END2 ! 1217: ! 1218: // REVIEW: added IDS_OLE2UILINKEDTYPE to strings.rc ! 1219: /* if object is a link, then expand usertypename to be "Linked %s" */ ! 1220: if (fIsLink && lpszFullUserTypeName) { ! 1221: lpszBuf = OleStdMalloc( ! 1222: lstrlen(lpszFullUserTypeName)+lstrlen(szLinkedTypeFmt)+1); ! 1223: if (lpszBuf) { ! 1224: #if defined( LATER ) ! 1225: if (0 == LoadString(ghInst, IDS_OLE2UILINKEDTYPE, ! 1226: (LPSTR)szLinkedTypeFmt, sizeof(szLinkedTypeFmt))) ! 1227: #endif ! 1228: lstrcpy(szLinkedTypeFmt, (LPSTR)"Linked %s"); ! 1229: ! 1230: wsprintf(lpszBuf, szLinkedTypeFmt, lpszFullUserTypeName); ! 1231: OleStdFreeString(lpszFullUserTypeName, NULL); ! 1232: lpszFullUserTypeName = lpszBuf; ! 1233: } ! 1234: } ! 1235: ! 1236: /* Get Source Of Copy ! 1237: ** if the object is an embedding, then get the object's moniker ! 1238: ** if the object is a link, then get the link source moniker ! 1239: */ ! 1240: if (fIsLink) { ! 1241: ! 1242: OLEDBG_BEGIN2("IOleLink::GetSourceDisplayName called\r\n") ! 1243: hrErr = lpOleLink->lpVtbl->GetSourceDisplayName( ! 1244: lpOleLink, &lpszSrcOfCopy ); ! 1245: OLEDBG_END2 ! 1246: fFreeSrcOfCopy = TRUE; ! 1247: ! 1248: } else { ! 1249: ! 1250: if (lpszSrcOfCopy == NULL) { ! 1251: OLEDBG_BEGIN2("IOleObject::GetMoniker called\r\n") ! 1252: hrErr = lpOleObj->lpVtbl->GetMoniker( ! 1253: lpOleObj, ! 1254: OLEGETMONIKER_TEMPFORUSER, ! 1255: OLEWHICHMK_OBJFULL, ! 1256: (LPMONIKER FAR*)&lpSrcMonikerOfCopy ! 1257: ); ! 1258: OLEDBG_END2 ! 1259: if (hrErr == NOERROR) ! 1260: { ! 1261: CreateBindCtx(0, (LPBC FAR*)&pbc); ! 1262: lpSrcMonikerOfCopy->lpVtbl->GetDisplayName( ! 1263: lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy); ! 1264: pbc->lpVtbl->Release(pbc); ! 1265: fFreeSrcOfCopy = TRUE; ! 1266: } ! 1267: } ! 1268: } ! 1269: ! 1270: // Get SIZEL ! 1271: OLEDBG_BEGIN2("IOleObject::GetExtent called\r\n") ! 1272: hrErr = lpOleObj->lpVtbl->GetExtent( ! 1273: lpOleObj, ! 1274: dwAspect, ! 1275: &sizel ! 1276: ); ! 1277: OLEDBG_END2 ! 1278: if (hrErr != NOERROR) ! 1279: sizel.cx = sizel.cy = 0; ! 1280: ! 1281: // Get DWSTATUS ! 1282: OLEDBG_BEGIN2("IOleObject::GetMiscStatus called\r\n") ! 1283: hrErr = lpOleObj->lpVtbl->GetMiscStatus( ! 1284: lpOleObj, ! 1285: dwAspect, ! 1286: &dwStatus ! 1287: ); ! 1288: OLEDBG_END2 ! 1289: if (hrErr != NOERROR) ! 1290: dwStatus = 0; ! 1291: ! 1292: // Get OBJECTDESCRIPTOR ! 1293: hObjDesc = OleStdGetObjectDescriptorData( ! 1294: clsid, ! 1295: dwAspect, ! 1296: sizel, ! 1297: pointl, ! 1298: dwStatus, ! 1299: lpszFullUserTypeName, ! 1300: lpszSrcOfCopy ! 1301: ); ! 1302: if (! hObjDesc) ! 1303: goto error; ! 1304: ! 1305: // Clean up ! 1306: if (lpszFullUserTypeName) ! 1307: OleStdFreeString(lpszFullUserTypeName, NULL); ! 1308: if (fFreeSrcOfCopy && lpszSrcOfCopy) ! 1309: OleStdFreeString(lpszSrcOfCopy, NULL); ! 1310: if (lpSrcMonikerOfCopy) ! 1311: OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy); ! 1312: if (lpOleLink) ! 1313: OleStdRelease((LPUNKNOWN)lpOleLink); ! 1314: ! 1315: return hObjDesc; ! 1316: ! 1317: error: ! 1318: if (lpszFullUserTypeName) ! 1319: OleStdFreeString(lpszFullUserTypeName, NULL); ! 1320: if (fFreeSrcOfCopy && lpszSrcOfCopy) ! 1321: OleStdFreeString(lpszSrcOfCopy, NULL); ! 1322: if (lpSrcMonikerOfCopy) ! 1323: OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy); ! 1324: if (lpOleLink) ! 1325: OleStdRelease((LPUNKNOWN)lpOleLink); ! 1326: ! 1327: return NULL; ! 1328: } ! 1329: ! 1330: /* ! 1331: * OleStdFillObjectDescriptorFromData ! 1332: * ! 1333: * Purpose: ! 1334: * Fills and returns a OBJECTDESCRIPTOR structure. The source object will offer CF_OBJECTDESCRIPTOR ! 1335: * if it is an OLE2 object, CF_OWNERLINK if it is an OLE1 object, or CF_FILENAME if it has been ! 1336: * copied to the clipboard by FileManager. ! 1337: * ! 1338: * Parameters: ! 1339: * lpDataObject LPDATAOBJECT Source object ! 1340: * lpmedium LPSTGMEDIUM Storage medium ! 1341: * lpcfFmt CLIPFORMAT FAR * Format offered by lpDataObject (OUT parameter) ! 1342: * ! 1343: * Return Value: ! 1344: * HBGLOBAL Handle to OBJECTDESCRIPTOR structure. ! 1345: */ ! 1346: ! 1347: STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData( ! 1348: LPDATAOBJECT lpDataObject, ! 1349: LPSTGMEDIUM lpmedium, ! 1350: CLIPFORMAT FAR* lpcfFmt ! 1351: ) ! 1352: { ! 1353: CLSID clsid; ! 1354: SIZEL sizel; ! 1355: POINTL pointl; ! 1356: LPSTR lpsz, szFullUserTypeName, szSrcOfCopy, szClassName, szDocName, szItemName; ! 1357: int nClassName, nDocName, nItemName, nFullUserTypeName; ! 1358: LPSTR szBuf = NULL; ! 1359: HGLOBAL hMem = NULL; ! 1360: HKEY hKey = NULL; ! 1361: LPMALLOC pIMalloc = NULL; ! 1362: DWORD dw = OLEUI_CCHKEYMAX; ! 1363: HGLOBAL hObjDesc; ! 1364: HRESULT hrErr; ! 1365: ! 1366: ! 1367: // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard. ! 1368: // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR ! 1369: if (hMem = OleStdGetData( ! 1370: lpDataObject, ! 1371: cfObjectDescriptor, ! 1372: NULL, ! 1373: DVASPECT_CONTENT, ! 1374: lpmedium)) ! 1375: { ! 1376: *lpcfFmt = cfObjectDescriptor; ! 1377: return hMem; // Don't drop to clean up at the end of this function ! 1378: } ! 1379: // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an OLE2 object, ! 1380: // check if this is an OLE 1 object. OLE 1 objects will offer CF_OWNERLINK ! 1381: else if (hMem = OleStdGetData( ! 1382: lpDataObject, ! 1383: cfOwnerLink, ! 1384: NULL, ! 1385: DVASPECT_CONTENT, ! 1386: lpmedium)) ! 1387: { ! 1388: *lpcfFmt = cfOwnerLink; ! 1389: // CF_OWNERLINK contains null-terminated strings for class name, document name ! 1390: // and item name with two null terminating characters at the end ! 1391: szClassName = (LPSTR)GlobalLock(hMem); ! 1392: nClassName = lstrlen(szClassName); ! 1393: szDocName = szClassName + nClassName + 1; ! 1394: nDocName = lstrlen(szDocName); ! 1395: szItemName = szDocName + nDocName + 1; ! 1396: nItemName = lstrlen(szItemName); ! 1397: ! 1398: hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); ! 1399: if (hrErr != NOERROR) ! 1400: goto error; ! 1401: ! 1402: // Find FullUserTypeName from Registration database using class name ! 1403: if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey) != ERROR_SUCCESS) ! 1404: goto error; ! 1405: ! 1406: // Allocate space for szFullUserTypeName & szSrcOfCopy. Maximum length of FullUserTypeName ! 1407: // is OLEUI_CCHKEYMAX. SrcOfCopy is constructed by concatenating FullUserTypeName, Document ! 1408: // Name and ItemName separated by spaces. ! 1409: szBuf = (LPSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, ! 1410: (DWORD)2*OLEUI_CCHKEYMAX+nDocName+nItemName+4); ! 1411: if (NULL == szBuf) ! 1412: goto error; ! 1413: szFullUserTypeName = szBuf; ! 1414: szSrcOfCopy = szFullUserTypeName+OLEUI_CCHKEYMAX+1; ! 1415: ! 1416: // Get FullUserTypeName ! 1417: if (RegQueryValue(hKey, NULL, szFullUserTypeName, &dw) != ERROR_SUCCESS) ! 1418: goto error; ! 1419: ! 1420: // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName ! 1421: lpsz = szSrcOfCopy; ! 1422: lstrcpy(lpsz, szFullUserTypeName); ! 1423: nFullUserTypeName = lstrlen(szFullUserTypeName); ! 1424: lpsz[nFullUserTypeName]=' '; ! 1425: lpsz += nFullUserTypeName+1; ! 1426: lstrcpy(lpsz, szDocName); ! 1427: lpsz[nDocName] = ' '; ! 1428: lpsz += nDocName+1; ! 1429: lstrcpy(lpsz, szItemName); ! 1430: ! 1431: sizel.cx = sizel.cy = 0; ! 1432: pointl.x = pointl.y = 0; ! 1433: ! 1434: CLSIDFromProgID(szClassName, &clsid); ! 1435: ! 1436: hObjDesc = OleStdGetObjectDescriptorData( ! 1437: clsid, ! 1438: DVASPECT_CONTENT, ! 1439: sizel, ! 1440: pointl, ! 1441: 0, ! 1442: szFullUserTypeName, ! 1443: szSrcOfCopy ! 1444: ); ! 1445: if (!hObjDesc) ! 1446: goto error; ! 1447: } ! 1448: // Check if object is CF_FILENAME ! 1449: else if (hMem = OleStdGetData( ! 1450: lpDataObject, ! 1451: cfFileName, ! 1452: NULL, ! 1453: DVASPECT_CONTENT, ! 1454: lpmedium)) ! 1455: { ! 1456: *lpcfFmt = cfFileName; ! 1457: lpsz = (LPSTR)GlobalLock(hMem); ! 1458: hrErr = GetClassFile(lpsz, &clsid); ! 1459: ! 1460: /* OLE2NOTE: if the file does not have an OLE class ! 1461: ** associated, then use the OLE 1 Packager as the class of ! 1462: ** the object to be created. this is the behavior of ! 1463: ** OleCreateFromData API ! 1464: */ ! 1465: if (hrErr != NOERROR) ! 1466: CLSIDFromProgID("Package", &clsid); ! 1467: sizel.cx = sizel.cy = 0; ! 1468: pointl.x = pointl.y = 0; ! 1469: ! 1470: hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc); ! 1471: if (hrErr != NOERROR) ! 1472: goto error; ! 1473: szBuf = (LPSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)OLEUI_CCHKEYMAX); ! 1474: if (NULL == szBuf) ! 1475: goto error; ! 1476: ! 1477: OleStdGetUserTypeOfClass(&clsid, szBuf, OLEUI_CCHKEYMAX, NULL); ! 1478: ! 1479: hObjDesc = OleStdGetObjectDescriptorData( ! 1480: clsid, ! 1481: DVASPECT_CONTENT, ! 1482: sizel, ! 1483: pointl, ! 1484: 0, ! 1485: szBuf, ! 1486: lpsz ! 1487: ); ! 1488: if (!hObjDesc) ! 1489: goto error; ! 1490: } ! 1491: else goto error; ! 1492: ! 1493: // Clean up ! 1494: if (szBuf) ! 1495: pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf); ! 1496: if (pIMalloc) ! 1497: OleStdRelease((LPUNKNOWN)pIMalloc); ! 1498: if (hMem) ! 1499: { ! 1500: GlobalUnlock(hMem); ! 1501: GlobalFree(hMem); ! 1502: } ! 1503: if (hKey) ! 1504: RegCloseKey(hKey); ! 1505: return hObjDesc; ! 1506: ! 1507: error: ! 1508: if (szBuf) ! 1509: pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf); ! 1510: if (pIMalloc) ! 1511: OleStdRelease((LPUNKNOWN)pIMalloc); ! 1512: if (hMem) ! 1513: { ! 1514: GlobalUnlock(hMem); ! 1515: GlobalFree(hMem); ! 1516: } ! 1517: if (hKey) ! 1518: RegCloseKey(hKey); ! 1519: return NULL; ! 1520: } ! 1521: ! 1522: ! 1523: STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc) ! 1524: { ! 1525: if (lpformatetc->tymed & TYMED_ISTORAGE) { ! 1526: return NOERROR; ! 1527: } else { ! 1528: return ResultFromScode(DATA_E_FORMATETC); ! 1529: } ! 1530: } ! 1531: ! 1532: ! 1533: STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc) ! 1534: { ! 1535: if (lpformatetc->tymed & TYMED_ISTREAM) ! 1536: return NOERROR; ! 1537: else ! 1538: return ResultFromScode(DATA_E_FORMATETC); ! 1539: } ! 1540: ! 1541: ! 1542: STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc) ! 1543: { ! 1544: if (lpformatetc->tymed & TYMED_HGLOBAL) { ! 1545: return NOERROR; ! 1546: } else { ! 1547: return ResultFromScode(DATA_E_FORMATETC); ! 1548: } ! 1549: } ! 1550: ! 1551: ! 1552: STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed) ! 1553: { ! 1554: if (lpformatetc->tymed & tymed) { ! 1555: return NOERROR; ! 1556: } else { ! 1557: return ResultFromScode(DATA_E_FORMATETC); ! 1558: } ! 1559: } ! 1560: ! 1561: ! 1562: ! 1563: /* ! 1564: * OleStdCopyMetafilePict() ! 1565: * ! 1566: * Purpose: ! 1567: * Make an independent copy of a MetafilePict ! 1568: * Parameters: ! 1569: * ! 1570: * Return Value: ! 1571: * TRUE if successful, else FALSE. ! 1572: */ ! 1573: STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout) ! 1574: { ! 1575: HANDLE hpictout; ! 1576: LPMETAFILEPICT ppictin, ppictout; ! 1577: ! 1578: if (hpictin == NULL || phpictout == NULL) { ! 1579: OleDbgAssert(hpictin == NULL || phpictout == NULL); ! 1580: return FALSE; ! 1581: } ! 1582: ! 1583: *phpictout = NULL; ! 1584: ! 1585: if ((ppictin = (LPMETAFILEPICT)GlobalLock(hpictin)) == NULL) { ! 1586: return FALSE; ! 1587: } ! 1588: ! 1589: hpictout = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT)); ! 1590: ! 1591: if (hpictout && (ppictout = (LPMETAFILEPICT)GlobalLock(hpictout))){ ! 1592: ppictout->hMF = CopyMetaFile(ppictin->hMF, NULL); ! 1593: ppictout->xExt = ppictin->xExt; ! 1594: ppictout->yExt = ppictin->yExt; ! 1595: ppictout->mm = ppictin->mm; ! 1596: GlobalUnlock(hpictout); ! 1597: } ! 1598: ! 1599: *phpictout = hpictout; ! 1600: ! 1601: return TRUE; ! 1602: ! 1603: } ! 1604: ! 1605: ! 1606: /* ! 1607: * OleStdGetMetafilePictFromOleObject() ! 1608: * ! 1609: * Purpose: ! 1610: * Generate a MetafilePict by drawing the OLE object. ! 1611: * Parameters: ! 1612: * ! 1613: * Return Value: ! 1614: * HANDLE -- handle of allocated METAFILEPICT ! 1615: */ ! 1616: STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject( ! 1617: LPOLEOBJECT lpOleObj, ! 1618: DWORD dwDrawAspect ! 1619: ) ! 1620: { ! 1621: LPVIEWOBJECT lpViewObj = NULL; ! 1622: HDC hDC; ! 1623: HMETAFILE hmf; ! 1624: HANDLE hMetaPict; ! 1625: LPMETAFILEPICT lpPict; ! 1626: RECT rcHim; ! 1627: RECTL rclHim; ! 1628: SIZEL sizelHim; ! 1629: HRESULT hrErr; ! 1630: SIZE size; ! 1631: POINT point; ! 1632: ! 1633: lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface( ! 1634: (LPUNKNOWN)lpOleObj, &IID_IViewObject); ! 1635: if (! lpViewObj) ! 1636: return NULL; ! 1637: ! 1638: OLEDBG_BEGIN2("IOleObject::GetExtent called\r\n") ! 1639: lpOleObj->lpVtbl->GetExtent( ! 1640: lpOleObj, ! 1641: dwDrawAspect, ! 1642: (LPSIZEL)&sizelHim ! 1643: ); ! 1644: OLEDBG_END2 ! 1645: ! 1646: hDC = CreateMetaFile(NULL); ! 1647: ! 1648: rclHim.left = 0; ! 1649: rclHim.top = 0; ! 1650: rclHim.right = sizelHim.cx; ! 1651: rclHim.bottom = sizelHim.cy; ! 1652: ! 1653: rcHim.left = (int)rclHim.left; ! 1654: rcHim.top = (int)rclHim.top; ! 1655: rcHim.right = (int)rclHim.right; ! 1656: rcHim.bottom = (int)rclHim.bottom; ! 1657: ! 1658: SetWindowOrgEx(hDC, rcHim.left, rcHim.top, &point); ! 1659: SetWindowExtEx(hDC, rcHim.right-rcHim.left, rcHim.bottom-rcHim.top,&size); ! 1660: ! 1661: OLEDBG_BEGIN2("IViewObject::Draw called\r\n") ! 1662: hrErr = lpViewObj->lpVtbl->Draw( ! 1663: lpViewObj, ! 1664: dwDrawAspect, ! 1665: -1, ! 1666: NULL, ! 1667: NULL, ! 1668: NULL, ! 1669: hDC, ! 1670: (LPRECTL)&rclHim, ! 1671: (LPRECTL)&rclHim, ! 1672: NULL, ! 1673: 0 ! 1674: ); ! 1675: OLEDBG_END2 ! 1676: ! 1677: OleStdRelease((LPUNKNOWN)lpViewObj); ! 1678: if (hrErr != NOERROR) { ! 1679: OleDbgOutHResult("IViewObject::Draw returned", hrErr); ! 1680: } ! 1681: ! 1682: hmf = CloseMetaFile(hDC); ! 1683: ! 1684: hMetaPict = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT)); ! 1685: ! 1686: if (hMetaPict && (lpPict = (LPMETAFILEPICT)GlobalLock(hMetaPict))){ ! 1687: lpPict->hMF = hmf; ! 1688: lpPict->xExt = (int)sizelHim.cx ; ! 1689: lpPict->yExt = (int)sizelHim.cy ; ! 1690: lpPict->mm = MM_ANISOTROPIC; ! 1691: GlobalUnlock(hMetaPict); ! 1692: } ! 1693: ! 1694: return hMetaPict; ! 1695: } ! 1696: ! 1697: ! 1698: /* Call Release on the object that is expected to go away. ! 1699: ** if the refcnt of the object did no go to 0 then give a debug message. ! 1700: */ ! 1701: STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPSTR lpszMsg) ! 1702: { ! 1703: ULONG cRef; ! 1704: ! 1705: cRef = lpUnk->lpVtbl->Release(lpUnk); ! 1706: ! 1707: #if defined( _DEBUG ) ! 1708: if (cRef != 0) { ! 1709: char szBuf[80]; ! 1710: if (lpszMsg) ! 1711: MessageBox(NULL, lpszMsg, NULL, MB_ICONEXCLAMATION | MB_OK); ! 1712: wsprintf( ! 1713: (LPSTR)szBuf, ! 1714: "refcnt (%ld) != 0 after object (0x%lx) release\n", ! 1715: cRef, ! 1716: lpUnk ! 1717: ); ! 1718: if (lpszMsg) ! 1719: OleDbgOut1(lpszMsg); ! 1720: OleDbgOut1((LPSTR)szBuf); ! 1721: OleDbgAssertSz(cRef == 0, (LPSTR)szBuf); ! 1722: } else { ! 1723: char szBuf[80]; ! 1724: wsprintf( ! 1725: (LPSTR)szBuf, ! 1726: "refcnt = 0 after object (0x%lx) release\n", lpUnk ! 1727: ); ! 1728: OleDbgOut4((LPSTR)szBuf); ! 1729: } ! 1730: #endif ! 1731: return cRef; ! 1732: } ! 1733: ! 1734: ! 1735: /* Call Release on the object that is NOT necessarily expected to go away. ! 1736: */ ! 1737: STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk) ! 1738: { ! 1739: ULONG cRef; ! 1740: ! 1741: cRef = lpUnk->lpVtbl->Release(lpUnk); ! 1742: ! 1743: #if defined( _DEBUG ) ! 1744: { ! 1745: char szBuf[80]; ! 1746: wsprintf( ! 1747: (LPSTR)szBuf, ! 1748: "refcnt = %ld after object (0x%lx) release\n", ! 1749: cRef, ! 1750: lpUnk ! 1751: ); ! 1752: OleDbgOut4((LPSTR)szBuf); ! 1753: } ! 1754: #endif ! 1755: return cRef; ! 1756: } ! 1757: ! 1758: ! 1759: /* OleStdInitVtbl ! 1760: ** -------------- ! 1761: ** ! 1762: ** Initialize an interface Vtbl to ensure that there are no NULL ! 1763: ** function pointers in the Vtbl. All entries in the Vtbl are ! 1764: ** set to a valid funtion pointer (OleStdNullMethod) that issues ! 1765: ** debug assert message (message box) and returns E_NOTIMPL if called. ! 1766: ** ! 1767: ** NOTE: this funtion does not initialize the Vtbl with usefull ! 1768: ** function pointers, only valid function pointers to avoid the ! 1769: ** horrible run-time crash when a call is made through the Vtbl with ! 1770: ** a NULL function pointer. this API is only necessary when ! 1771: ** initializing the Vtbl's in C. C++ guarantees that all interface ! 1772: ** functions (in C++ terms -- pure virtual functions) are implemented. ! 1773: */ ! 1774: ! 1775: STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl) ! 1776: { ! 1777: LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl; ! 1778: UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*); ! 1779: UINT i; ! 1780: ! 1781: for (i = 0; i < nMethods; i++) { ! 1782: lpFuncPtrArr[i] = OleStdNullMethod; ! 1783: } ! 1784: } ! 1785: ! 1786: ! 1787: /* OleStdCheckVtbl ! 1788: ** --------------- ! 1789: ** ! 1790: ** Check if all entries in the Vtbl are properly initialized with ! 1791: ** valid function pointers. If any entries are either NULL or ! 1792: ** OleStdNullMethod, then this function returns FALSE. If compiled ! 1793: ** for _DEBUG this function reports which function pointers are ! 1794: ** invalid. ! 1795: ** ! 1796: ** RETURNS: TRUE if all entries in Vtbl are valid ! 1797: ** FALSE otherwise. ! 1798: */ ! 1799: ! 1800: STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPSTR lpszIface) ! 1801: { ! 1802: LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl; ! 1803: UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*); ! 1804: UINT i; ! 1805: BOOL fStatus = TRUE; ! 1806: int nChar = 0; ! 1807: ! 1808: for (i = 0; i < nMethods; i++) { ! 1809: if (lpFuncPtrArr[i] == NULL || lpFuncPtrArr[i] == OleStdNullMethod) { ! 1810: #if defined( _DEBUG ) ! 1811: char szBuf[256]; ! 1812: wsprintf(szBuf, "%s::method# %d NOT valid!", lpszIface, i); ! 1813: OleDbgOut1((LPSTR)szBuf); ! 1814: #endif ! 1815: fStatus = FALSE; ! 1816: } ! 1817: } ! 1818: return fStatus; ! 1819: } ! 1820: ! 1821: ! 1822: /* OleStdNullMethod ! 1823: ** ---------------- ! 1824: ** Dummy method used by OleStdInitVtbl to initialize an interface ! 1825: ** Vtbl to ensure that there are no NULL function pointers in the ! 1826: ** Vtbl. All entries in the Vtbl are set to this function. this ! 1827: ** function issues a debug assert message (message box) and returns ! 1828: ** E_NOTIMPL if called. If all is done properly, this function will ! 1829: ** NEVER be called! ! 1830: */ ! 1831: STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis) ! 1832: { ! 1833: MessageBox( ! 1834: NULL, ! 1835: "ERROR: INTERFACE METHOD NOT IMPLEMENTED!\r\n", ! 1836: NULL, ! 1837: MB_SYSTEMMODAL | MB_ICONHAND | MB_OK ! 1838: ); ! 1839: ! 1840: return ResultFromScode(E_NOTIMPL); ! 1841: } ! 1842: ! 1843: ! 1844: ! 1845: static BOOL GetFileTimes(LPSTR lpszFileName, FILETIME FAR* pfiletime) ! 1846: { ! 1847: #ifdef WIN32 ! 1848: WIN32_FIND_DATA fd; ! 1849: HANDLE hFind; ! 1850: hFind = FindFirstFile(lpszFileName,&fd); ! 1851: if (hFind == NULL || hFind == INVALID_HANDLE_VALUE) { ! 1852: return FALSE; ! 1853: } ! 1854: FindClose(hFind); ! 1855: *pfiletime = fd.ftLastWriteTime; ! 1856: return TRUE; ! 1857: #else ! 1858: static char sz[256]; ! 1859: static struct _find_t fileinfo; ! 1860: ! 1861: lstrcpyn((LPSTR)sz, lpszFileName, sizeof(sz)-1); ! 1862: sz[sizeof(sz)-1]= '\0'; ! 1863: AnsiToOem(sz, sz); ! 1864: return (_dos_findfirst(sz,_A_NORMAL|_A_HIDDEN|_A_SUBDIR|_A_SYSTEM, ! 1865: (struct _find_t *)&fileinfo) == 0 && ! 1866: CoDosDateTimeToFileTime(fileinfo.wr_date,fileinfo.wr_time,pfiletime)); ! 1867: #endif ! 1868: } ! 1869: ! 1870: ! 1871: ! 1872: /* OleStdRegisterAsRunning ! 1873: ** ----------------------- ! 1874: ** Register a moniker in the RunningObjectTable. ! 1875: ** if there is an existing registration (*lpdwRegister!=NULL), then ! 1876: ** first revoke that registration. ! 1877: ** ! 1878: ** new dwRegister key is returned via *lpdwRegister parameter. ! 1879: */ ! 1880: STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister) ! 1881: { ! 1882: LPRUNNINGOBJECTTABLE lpROT; ! 1883: HRESULT hrErr; ! 1884: DWORD dwOldRegister = *lpdwRegister; ! 1885: ! 1886: OLEDBG_BEGIN2("OleStdRegisterAsRunning\r\n") ! 1887: ! 1888: OLEDBG_BEGIN2("GetRunningObjectTable called\r\n") ! 1889: hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); ! 1890: OLEDBG_END2 ! 1891: ! 1892: if (hrErr == NOERROR) { ! 1893: ! 1894: /* register as running if a valid moniker is passed ! 1895: ** ! 1896: ** OLE2NOTE: we deliberately register the new moniker BEFORE ! 1897: ** revoking the old moniker just in case the object ! 1898: ** currently has no external locks. if the object has no ! 1899: ** locks then revoking it from the running object table will ! 1900: ** cause the object's StubManager to initiate shutdown of ! 1901: ** the object. ! 1902: */ ! 1903: if (lpmkFull) { ! 1904: ! 1905: OLEDBG_BEGIN2("IRunningObjectTable::Register called\r\n") ! 1906: lpROT->lpVtbl->Register(lpROT, 0, lpUnk,lpmkFull,lpdwRegister); ! 1907: OLEDBG_END2 ! 1908: ! 1909: #if _DEBUG ! 1910: { ! 1911: char szBuf[512]; ! 1912: LPSTR lpszDisplay; ! 1913: LPBC lpbc; ! 1914: ! 1915: CreateBindCtx(0, (LPBC FAR*)&lpbc); ! 1916: lpmkFull->lpVtbl->GetDisplayName( ! 1917: lpmkFull, ! 1918: lpbc, ! 1919: NULL, ! 1920: (LPSTR FAR*)&lpszDisplay ! 1921: ); ! 1922: OleStdRelease((LPUNKNOWN)lpbc); ! 1923: wsprintf( ! 1924: szBuf, ! 1925: "Moniker '%s' REGISTERED as [0x%lx] in ROT\r\n", ! 1926: lpszDisplay, ! 1927: *lpdwRegister ! 1928: ); ! 1929: OleDbgOut2(szBuf); ! 1930: OleStdFreeString(lpszDisplay, NULL); ! 1931: } ! 1932: #endif // _DEBUG ! 1933: ! 1934: } ! 1935: ! 1936: // if already registered, revoke ! 1937: if (dwOldRegister != 0) { ! 1938: ! 1939: #if _DEBUG ! 1940: { ! 1941: char szBuf[512]; ! 1942: ! 1943: wsprintf( ! 1944: szBuf, ! 1945: "Moniker [0x%lx] REVOKED from ROT\r\n", ! 1946: dwOldRegister ! 1947: ); ! 1948: OleDbgOut2(szBuf); ! 1949: } ! 1950: #endif // _DEBUG ! 1951: ! 1952: OLEDBG_BEGIN2("IRunningObjectTable::Revoke called\r\n") ! 1953: lpROT->lpVtbl->Revoke(lpROT, dwOldRegister); ! 1954: OLEDBG_END2 ! 1955: ! 1956: *lpdwRegister = 0; ! 1957: } ! 1958: ! 1959: OleStdRelease((LPUNKNOWN)lpROT); ! 1960: } else { ! 1961: OleDbgAssertSz( ! 1962: lpROT != NULL, ! 1963: "OleStdRegisterAsRunning: GetRunningObjectTable FAILED\r\n" ! 1964: ); ! 1965: } ! 1966: ! 1967: OLEDBG_END2 ! 1968: } ! 1969: ! 1970: ! 1971: ! 1972: /* OleStdRevokeAsRunning ! 1973: ** --------------------- ! 1974: ** Revoke a moniker from the RunningObjectTable if there is an ! 1975: ** existing registration (*lpdwRegister!=NULL). ! 1976: ** ! 1977: ** *lpdwRegister parameter will be set to NULL. ! 1978: */ ! 1979: STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister) ! 1980: { ! 1981: LPRUNNINGOBJECTTABLE lpROT; ! 1982: HRESULT hrErr; ! 1983: ! 1984: OLEDBG_BEGIN2("OleStdRevokeAsRunning\r\n") ! 1985: ! 1986: // if still registered, then revoke ! 1987: if (*lpdwRegister != 0) { ! 1988: ! 1989: OLEDBG_BEGIN2("GetRunningObjectTable called\r\n") ! 1990: hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); ! 1991: OLEDBG_END2 ! 1992: ! 1993: if (hrErr == NOERROR) { ! 1994: ! 1995: #if _DEBUG ! 1996: { ! 1997: char szBuf[512]; ! 1998: ! 1999: wsprintf( ! 2000: szBuf, ! 2001: "Moniker [0x%lx] REVOKED from ROT\r\n", ! 2002: *lpdwRegister ! 2003: ); ! 2004: OleDbgOut2(szBuf); ! 2005: } ! 2006: #endif // _DEBUG ! 2007: ! 2008: OLEDBG_BEGIN2("IRunningObjectTable::Revoke called\r\n") ! 2009: lpROT->lpVtbl->Revoke(lpROT, *lpdwRegister); ! 2010: OLEDBG_END2 ! 2011: ! 2012: *lpdwRegister = 0; ! 2013: ! 2014: OleStdRelease((LPUNKNOWN)lpROT); ! 2015: } else { ! 2016: OleDbgAssertSz( ! 2017: lpROT != NULL, ! 2018: "OleStdRevokeAsRunning: GetRunningObjectTable FAILED\r\n" ! 2019: ); ! 2020: } ! 2021: } ! 2022: OLEDBG_END2 ! 2023: } ! 2024: ! 2025: ! 2026: /* OleStdNoteFileChangeTime ! 2027: ** ------------------------ ! 2028: ** Note the time a File-Based object has been saved in the ! 2029: ** RunningObjectTable. These change times are used as the basis for ! 2030: ** IOleObject::IsUpToDate. ! 2031: ** It is important to set the time of the file-based object ! 2032: ** following a save operation to exactly the time of the saved file. ! 2033: ** this helps IOleObject::IsUpToDate to give the correct answer ! 2034: ** after a file has been saved. ! 2035: */ ! 2036: STDAPI_(void) OleStdNoteFileChangeTime(LPSTR lpszFileName, DWORD dwRegister) ! 2037: { ! 2038: if (dwRegister != 0) { ! 2039: ! 2040: LPRUNNINGOBJECTTABLE lprot; ! 2041: FILETIME filetime; ! 2042: ! 2043: if (GetFileTimes(lpszFileName, &filetime) && ! 2044: GetRunningObjectTable(0,&lprot) == NOERROR) ! 2045: { ! 2046: lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime ); ! 2047: lprot->lpVtbl->Release(lprot); ! 2048: ! 2049: OleDbgOut2("IRunningObjectTable::NoteChangeTime called\r\n"); ! 2050: } ! 2051: } ! 2052: } ! 2053: ! 2054: ! 2055: /* OleStdNoteObjectChangeTime ! 2056: ** -------------------------- ! 2057: ** Set the last change time of an object that is registered in the ! 2058: ** RunningObjectTable. These change times are used as the basis for ! 2059: ** IOleObject::IsUpToDate. ! 2060: ** ! 2061: ** every time the object sends out a OnDataChange notification, it ! 2062: ** should update the Time of last change in the ROT. ! 2063: ** ! 2064: ** NOTE: this function set the change time to the current time. ! 2065: */ ! 2066: STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister) ! 2067: { ! 2068: if (dwRegister != 0) { ! 2069: ! 2070: LPRUNNINGOBJECTTABLE lprot; ! 2071: FILETIME filetime; ! 2072: ! 2073: if (GetRunningObjectTable(0,&lprot) == NOERROR) ! 2074: { ! 2075: CoFileTimeNow( &filetime ); ! 2076: lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime ); ! 2077: lprot->lpVtbl->Release(lprot); ! 2078: ! 2079: OleDbgOut2("IRunningObjectTable::NoteChangeTime called\r\n"); ! 2080: } ! 2081: } ! 2082: } ! 2083: ! 2084: ! 2085: ! 2086: STDAPI_(void) OleStdCreateTempFileMoniker(LPSTR lpszPrefixString, UINT FAR* lpuUnique, LPSTR lpszName, LPMONIKER FAR* lplpmk) ! 2087: { ! 2088: LPRUNNINGOBJECTTABLE lpROT = NULL; ! 2089: UINT i = (lpuUnique != NULL ? *lpuUnique : 1); ! 2090: HRESULT hrErr; ! 2091: ! 2092: wsprintf(lpszName, "%s%d", lpszPrefixString, i++); ! 2093: CreateFileMoniker(lpszName, lplpmk); ! 2094: ! 2095: OLEDBG_BEGIN2("GetRunningObjectTable called\r\n") ! 2096: hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT); ! 2097: OLEDBG_END2 ! 2098: ! 2099: if (hrErr == NOERROR) { ! 2100: ! 2101: while (1) { ! 2102: if (! *lplpmk) ! 2103: break; // failed to create FileMoniker ! 2104: ! 2105: OLEDBG_BEGIN2("IRunningObjectTable::IsRunning called\r\n") ! 2106: hrErr = lpROT->lpVtbl->IsRunning(lpROT,*lplpmk); ! 2107: OLEDBG_END2 ! 2108: ! 2109: if (hrErr != NOERROR) ! 2110: break; // the Moniker is NOT running; found unused one! ! 2111: ! 2112: OleStdVerifyRelease( ! 2113: (LPUNKNOWN)*lplpmk, ! 2114: "OleStdCreateTempFileMoniker: Moniker NOT released" ! 2115: ); ! 2116: ! 2117: wsprintf(lpszName, "%s%d", lpszPrefixString, i++); ! 2118: CreateFileMoniker(lpszName, lplpmk); ! 2119: } ! 2120: ! 2121: OleStdRelease((LPUNKNOWN)lpROT); ! 2122: } ! 2123: ! 2124: if (lpuUnique != NULL) ! 2125: *lpuUnique = i; ! 2126: } ! 2127: ! 2128: ! 2129: /* OleStdGetFirstMoniker ! 2130: ** --------------------- ! 2131: ** return the first piece of a moniker. ! 2132: ** ! 2133: ** NOTE: if the given moniker is not a generic composite moniker, ! 2134: ** then an AddRef'ed pointer to the given moniker is returned. ! 2135: */ ! 2136: STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk) ! 2137: { ! 2138: LPMONIKER lpmkFirst = NULL; ! 2139: LPENUMMONIKER lpenumMoniker; ! 2140: DWORD dwMksys; ! 2141: HRESULT hrErr; ! 2142: ! 2143: if (! lpmk) ! 2144: return NULL; ! 2145: ! 2146: if (lpmk->lpVtbl->IsSystemMoniker(lpmk, (LPDWORD)&dwMksys) == NOERROR ! 2147: && dwMksys == MKSYS_GENERICCOMPOSITE) { ! 2148: ! 2149: /* OLE2NOTE: the moniker is a GenericCompositeMoniker. ! 2150: ** enumerate the moniker to pull off the first piece. ! 2151: */ ! 2152: ! 2153: hrErr = lpmk->lpVtbl->Enum( ! 2154: lpmk, ! 2155: TRUE /* fForward */, ! 2156: (LPENUMMONIKER FAR*)&lpenumMoniker ! 2157: ); ! 2158: if (hrErr != NOERROR) ! 2159: return NULL; // ERROR: give up! ! 2160: ! 2161: hrErr = lpenumMoniker->lpVtbl->Next( ! 2162: lpenumMoniker, ! 2163: 1, ! 2164: (LPMONIKER FAR*)&lpmkFirst, ! 2165: NULL ! 2166: ); ! 2167: lpenumMoniker->lpVtbl->Release(lpenumMoniker); ! 2168: return lpmkFirst; ! 2169: ! 2170: } else { ! 2171: /* OLE2NOTE: the moniker is NOT a GenericCompositeMoniker. ! 2172: ** return an AddRef'ed pointer to the input moniker. ! 2173: */ ! 2174: lpmk->lpVtbl->AddRef(lpmk); ! 2175: return lpmk; ! 2176: } ! 2177: } ! 2178: ! 2179: ! 2180: /* OleStdGetLenFilePrefixOfMoniker ! 2181: ** ------------------------------- ! 2182: ** if the first piece of the Moniker is a FileMoniker, then return ! 2183: ** the length of the filename string. ! 2184: ** ! 2185: ** lpmk pointer to moniker ! 2186: ** ! 2187: ** Returns ! 2188: ** 0 if moniker does NOT start with a FileMoniker ! 2189: ** uLen string length of filename prefix of the display name ! 2190: ** retrieved from the given (lpmk) moniker. ! 2191: */ ! 2192: STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk) ! 2193: { ! 2194: LPMONIKER lpmkFirst = NULL; ! 2195: DWORD dwMksys; ! 2196: LPSTR lpsz = NULL; ! 2197: LPBC lpbc = NULL; ! 2198: ULONG uLen = 0; ! 2199: HRESULT hrErr; ! 2200: ! 2201: if (! lpmk) ! 2202: return 0; ! 2203: ! 2204: lpmkFirst = OleStdGetFirstMoniker(lpmk); ! 2205: if (lpmkFirst) { ! 2206: if ( (lpmkFirst->lpVtbl->IsSystemMoniker( ! 2207: lpmkFirst, (LPDWORD)&dwMksys) == NOERROR) ! 2208: && dwMksys == MKSYS_FILEMONIKER) { ! 2209: ! 2210: hrErr = CreateBindCtx(0, (LPBC FAR*)&lpbc); ! 2211: if (hrErr == NOERROR) { ! 2212: hrErr = lpmkFirst->lpVtbl->GetDisplayName( ! 2213: lpmkFirst, ! 2214: lpbc, ! 2215: NULL, /* pmkToLeft */ ! 2216: (LPSTR FAR*)&lpsz ! 2217: ); ! 2218: if (hrErr == NOERROR && lpsz != NULL) { ! 2219: uLen = lstrlen(lpsz); ! 2220: OleStdFreeString(lpsz, NULL); ! 2221: } ! 2222: OleStdRelease((LPUNKNOWN)lpbc); ! 2223: } ! 2224: } ! 2225: lpmkFirst->lpVtbl->Release(lpmkFirst); ! 2226: } ! 2227: return uLen; ! 2228: } ! 2229: ! 2230: ! 2231: /* ! 2232: * OleStdMarkPasteEntryList ! 2233: * ! 2234: * Purpose: ! 2235: * Mark each entry in the PasteEntryList if its format is available from ! 2236: * the source IDataObject*. the dwScratchSpace field of each PasteEntry ! 2237: * is set to TRUE if available, else FALSE. ! 2238: * ! 2239: * Parameters: ! 2240: * LPOLEUIPASTEENTRY array of PasteEntry structures ! 2241: * int count of elements in PasteEntry array ! 2242: * LPDATAOBJECT source IDataObject* pointer ! 2243: * ! 2244: * Return Value: ! 2245: * none ! 2246: */ ! 2247: STDAPI_(void) OleStdMarkPasteEntryList( ! 2248: LPDATAOBJECT lpSrcDataObj, ! 2249: LPOLEUIPASTEENTRY lpPriorityList, ! 2250: int cEntries ! 2251: ) ! 2252: { ! 2253: LPENUMFORMATETC lpEnumFmtEtc = NULL; ! 2254: FORMATETC fmtetc; ! 2255: int i; ! 2256: HRESULT hrErr; ! 2257: ! 2258: // Clear all marks ! 2259: for (i = 0; i < cEntries; i++) { ! 2260: lpPriorityList[i].dwScratchSpace = FALSE; ! 2261: ! 2262: if (! lpPriorityList[i].fmtetc.cfFormat) { ! 2263: // caller wants this item always considered available ! 2264: // (by specifying a NULL format) ! 2265: lpPriorityList[i].dwScratchSpace = TRUE; ! 2266: } else if (lpPriorityList[i].fmtetc.cfFormat == cfEmbeddedObject ! 2267: || lpPriorityList[i].fmtetc.cfFormat == cfEmbedSource ! 2268: || lpPriorityList[i].fmtetc.cfFormat == cfFileName) { ! 2269: ! 2270: // if there is an OLE object format, then handle it ! 2271: // specially by calling OleQueryCreateFromData. the caller ! 2272: // need only specify one object type format. ! 2273: OLEDBG_BEGIN2("OleQueryCreateFromData called\r\n") ! 2274: hrErr = OleQueryCreateFromData(lpSrcDataObj); ! 2275: OLEDBG_END2 ! 2276: if(NOERROR == hrErr) { ! 2277: lpPriorityList[i].dwScratchSpace = TRUE; ! 2278: } ! 2279: } else if (lpPriorityList[i].fmtetc.cfFormat == cfLinkSource) { ! 2280: ! 2281: // if there is OLE 2.0 LinkSource format, then handle it ! 2282: // specially by calling OleQueryLinkFromData. ! 2283: OLEDBG_BEGIN2("OleQueryLinkFromData called\r\n") ! 2284: hrErr = OleQueryLinkFromData(lpSrcDataObj); ! 2285: OLEDBG_END2 ! 2286: if(NOERROR == hrErr) { ! 2287: lpPriorityList[i].dwScratchSpace = TRUE; ! 2288: } ! 2289: } ! 2290: } ! 2291: ! 2292: OLEDBG_BEGIN2("IDataObject::EnumFormatEtc called\r\n") ! 2293: hrErr = lpSrcDataObj->lpVtbl->EnumFormatEtc( ! 2294: lpSrcDataObj, ! 2295: DATADIR_GET, ! 2296: (LPENUMFORMATETC FAR*)&lpEnumFmtEtc ! 2297: ); ! 2298: OLEDBG_END2 ! 2299: ! 2300: if (hrErr != NOERROR) ! 2301: return; // unable to get format enumerator ! 2302: ! 2303: // Enumerate the formats offered by the source ! 2304: // Loop over all formats offered by the source ! 2305: while (lpEnumFmtEtc->lpVtbl->Next( ! 2306: lpEnumFmtEtc, 1, (LPFORMATETC)&fmtetc, NULL) == S_OK) ! 2307: { ! 2308: for (i = 0; i < cEntries; i++) ! 2309: { ! 2310: if (! lpPriorityList[i].dwScratchSpace && ! 2311: IsEqualFORMATETC(fmtetc, lpPriorityList[i].fmtetc)) ! 2312: { ! 2313: lpPriorityList[i].dwScratchSpace = TRUE; ! 2314: } ! 2315: } ! 2316: } ! 2317: ! 2318: // Clean up ! 2319: if (lpEnumFmtEtc) ! 2320: OleStdRelease((LPUNKNOWN)lpEnumFmtEtc); ! 2321: } ! 2322: ! 2323: ! 2324: /* OleStdGetPriorityClipboardFormat ! 2325: ** -------------------------------- ! 2326: ** ! 2327: ** Retrieve the first clipboard format in a list for which data ! 2328: ** exists in the source IDataObject*. ! 2329: ** ! 2330: ** Returns -1 if no acceptable match is found. ! 2331: ** index of first acceptable match in the priority list. ! 2332: ** ! 2333: */ ! 2334: STDAPI_(int) OleStdGetPriorityClipboardFormat(LPDATAOBJECT lpSrcDataObj, LPOLEUIPASTEENTRY lpPriorityList, int cEntries) ! 2335: { ! 2336: int i; ! 2337: int nFmtEtc = -1; ! 2338: ! 2339: // Mark all entries that the Source provides ! 2340: OleStdMarkPasteEntryList(lpSrcDataObj, lpPriorityList, cEntries); ! 2341: ! 2342: // Loop over the target's priority list of formats ! 2343: for (i = 0; i < cEntries; i++) ! 2344: { ! 2345: if (lpPriorityList[i].dwFlags != OLEUIPASTE_PASTEONLY && ! 2346: !(lpPriorityList[i].dwFlags & OLEUIPASTE_PASTE)) ! 2347: continue; ! 2348: ! 2349: // get first marked entry ! 2350: if (lpPriorityList[i].dwScratchSpace) { ! 2351: nFmtEtc = i; ! 2352: break; // Found priority format; DONE ! 2353: } ! 2354: } ! 2355: ! 2356: return nFmtEtc; ! 2357: } ! 2358: ! 2359: ! 2360: /* OleStdIsDuplicateFormat ! 2361: ** ----------------------- ! 2362: ** Returns TRUE if the lpFmtEtc->cfFormat is found in the array of ! 2363: ** FormatEtc structures. ! 2364: */ ! 2365: STDAPI_(BOOL) OleStdIsDuplicateFormat( ! 2366: LPFORMATETC lpFmtEtc, ! 2367: LPFORMATETC arrFmtEtc, ! 2368: int nFmtEtc ! 2369: ) ! 2370: { ! 2371: int i; ! 2372: ! 2373: for (i = 0; i < nFmtEtc; i++) { ! 2374: if (lpFmtEtc->cfFormat == arrFmtEtc[i].cfFormat) ! 2375: return TRUE; ! 2376: } ! 2377: ! 2378: return FALSE; ! 2379: } ! 2380: ! 2381: ! 2382: /* OleStdGetDropEffect ! 2383: ** ------------------- ! 2384: ** ! 2385: ** Convert a keyboard state into a DROPEFFECT. ! 2386: ** ! 2387: ** returns the DROPEFFECT value derived from the key state. ! 2388: ** the following is the standard interpretation: ! 2389: ** no modifier -- Default Drop (NULL is returned) ! 2390: ** CTRL -- DROPEFFECT_COPY ! 2391: ** SHIFT -- DROPEFFECT_MOVE ! 2392: ** CTRL-SHIFT -- DROPEFFECT_LINK ! 2393: ** ! 2394: ** Default Drop: this depends on the type of the target application. ! 2395: ** this is re-interpretable by each target application. a typical ! 2396: ** interpretation is if the drag is local to the same document ! 2397: ** (which is source of the drag) then a MOVE operation is ! 2398: ** performed. if the drag is not local, then a COPY operation is ! 2399: ** performed. ! 2400: */ ! 2401: STDAPI_(DWORD) OleStdGetDropEffect( DWORD grfKeyState ) ! 2402: { ! 2403: ! 2404: if (grfKeyState & MK_CONTROL) { ! 2405: ! 2406: if (grfKeyState & MK_SHIFT) ! 2407: return DROPEFFECT_LINK; ! 2408: else ! 2409: return DROPEFFECT_COPY; ! 2410: ! 2411: } else if (grfKeyState & MK_SHIFT) ! 2412: return DROPEFFECT_MOVE; ! 2413: ! 2414: return 0; // no modifier -- do default operation ! 2415: } ! 2416: ! 2417: ! 2418: /* OleStdGetItemToken ! 2419: * ------------------ ! 2420: * ! 2421: * LPSTR lpszSrc - Pointer to a source string ! 2422: * LPSTR lpszDst - Pointer to destination buffer ! 2423: * ! 2424: * Will copy one token from the lpszSrc buffer to the lpszItem buffer. ! 2425: * It considers all alpha-numeric and white space characters as valid ! 2426: * characters for a token. the first non-valid character delimates the ! 2427: * token. ! 2428: * ! 2429: * returns the number of charaters eaten. ! 2430: */ ! 2431: STDAPI_(ULONG) OleStdGetItemToken(LPSTR lpszSrc, LPSTR lpszDst, int nMaxChars) ! 2432: { ! 2433: ULONG chEaten = 0L; ! 2434: ! 2435: // skip leading delimeter characters ! 2436: while (*lpszSrc && --nMaxChars > 0 ! 2437: && ((*lpszSrc=='/') || (*lpszSrc=='\\') || ! 2438: (*lpszSrc=='!') || (*lpszSrc==':'))) { ! 2439: *lpszSrc++; ! 2440: chEaten++; ! 2441: } ! 2442: ! 2443: // Extract token string (up to first delimeter char or EOS) ! 2444: while (*lpszSrc && --nMaxChars > 0 ! 2445: && !((*lpszSrc=='/') || (*lpszSrc=='\\') || ! 2446: (*lpszSrc=='!') || (*lpszSrc==':'))) { ! 2447: *lpszDst++ = *lpszSrc++; ! 2448: chEaten++; ! 2449: } ! 2450: *lpszDst = '\0'; ! 2451: return chEaten; ! 2452: } ! 2453: ! 2454: ! 2455: /************************************************************************* ! 2456: ** OleStdCreateRootStorage ! 2457: ** create a root level Storage given a filename that is compatible ! 2458: ** to be used by a top-level OLE container. if the filename ! 2459: ** specifies an existing file, then an error is returned. ! 2460: ** the root storage (Docfile) that is created by this function ! 2461: ** is suitable to be used to create child storages for embedings. ! 2462: ** (CreateChildStorage can be used to create child storages.) ! 2463: ** NOTE: the root-level storage is opened in transacted mode. ! 2464: *************************************************************************/ ! 2465: ! 2466: STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPSTR lpszStgName, DWORD grfMode) ! 2467: { ! 2468: HRESULT hr; ! 2469: DWORD grfCreateMode = STGM_READWRITE | STGM_TRANSACTED; ! 2470: DWORD reserved = 0; ! 2471: LPSTORAGE lpRootStg; ! 2472: char szMsg[64]; ! 2473: ! 2474: // if temp file is being created, enable delete-on-release ! 2475: if (! lpszStgName) ! 2476: grfCreateMode |= STGM_DELETEONRELEASE; ! 2477: ! 2478: hr = StgCreateDocfile( ! 2479: lpszStgName, ! 2480: grfMode | grfCreateMode, ! 2481: reserved, ! 2482: (LPSTORAGE FAR*)&lpRootStg ! 2483: ); ! 2484: ! 2485: if (hr == NOERROR) ! 2486: return lpRootStg; // existing file successfully opened ! 2487: ! 2488: OleDbgOutHResult("StgCreateDocfile returned", hr); ! 2489: ! 2490: if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPSTR)szMsg, 64)) ! 2491: return NULL; ! 2492: ! 2493: MessageBox(NULL, (LPSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK); ! 2494: return NULL; ! 2495: } ! 2496: ! 2497: ! 2498: /************************************************************************* ! 2499: ** OleStdOpenRootStorage ! 2500: ** open a root level Storage given a filename that is compatible ! 2501: ** to be used by a top-level OLE container. if the file does not ! 2502: ** exist then an error is returned. ! 2503: ** the root storage (Docfile) that is opened by this function ! 2504: ** is suitable to be used to create child storages for embedings. ! 2505: ** (CreateChildStorage can be used to create child storages.) ! 2506: ** NOTE: the root-level storage is opened in transacted mode. ! 2507: *************************************************************************/ ! 2508: ! 2509: STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPSTR lpszStgName, DWORD grfMode) ! 2510: { ! 2511: HRESULT hr; ! 2512: DWORD reserved = 0; ! 2513: LPSTORAGE lpRootStg; ! 2514: char szMsg[64]; ! 2515: ! 2516: if (lpszStgName) { ! 2517: ! 2518: hr = StgOpenStorage( ! 2519: lpszStgName, ! 2520: NULL, ! 2521: grfMode | STGM_TRANSACTED, ! 2522: NULL, ! 2523: reserved, ! 2524: (LPSTORAGE FAR*)&lpRootStg ! 2525: ); ! 2526: ! 2527: if (hr == NOERROR) ! 2528: return lpRootStg; // existing file successfully opened ! 2529: ! 2530: OleDbgOutHResult("StgOpenStorage returned", hr); ! 2531: } ! 2532: ! 2533: if (0 == LoadString(ghInst, IDS_OLESTDNOOPENFILE, szMsg, 64)) ! 2534: return NULL; ! 2535: ! 2536: MessageBox(NULL, (LPSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK); ! 2537: return NULL; ! 2538: } ! 2539: ! 2540: ! 2541: /************************************************************************* ! 2542: ** OpenOrCreateRootStorage ! 2543: ** open a root level Storage given a filename that is compatible ! 2544: ** to be used by a top-level OLE container. if the filename ! 2545: ** specifies an existing file, then it is open, otherwise a new file ! 2546: ** with the given name is created. ! 2547: ** the root storage (Docfile) that is created by this function ! 2548: ** is suitable to be used to create child storages for embedings. ! 2549: ** (CreateChildStorage can be used to create child storages.) ! 2550: ** NOTE: the root-level storage is opened in transacted mode. ! 2551: *************************************************************************/ ! 2552: ! 2553: STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPSTR lpszStgName, DWORD grfMode) ! 2554: { ! 2555: HRESULT hrErr; ! 2556: SCODE sc; ! 2557: DWORD reserved = 0; ! 2558: LPSTORAGE lpRootStg; ! 2559: char szMsg[64]; ! 2560: ! 2561: if (lpszStgName) { ! 2562: ! 2563: hrErr = StgOpenStorage( ! 2564: lpszStgName, ! 2565: NULL, ! 2566: grfMode | STGM_READWRITE | STGM_TRANSACTED, ! 2567: NULL, ! 2568: reserved, ! 2569: (LPSTORAGE FAR*)&lpRootStg ! 2570: ); ! 2571: ! 2572: if (hrErr == NOERROR) ! 2573: return lpRootStg; // existing file successfully opened ! 2574: ! 2575: OleDbgOutHResult("StgOpenStorage returned", hrErr); ! 2576: sc = GetScode(hrErr); ! 2577: ! 2578: if (sc!=STG_E_FILENOTFOUND && sc!=STG_E_FILEALREADYEXISTS) { ! 2579: return NULL; ! 2580: } ! 2581: } ! 2582: ! 2583: /* if file did not already exist, try to create a new one */ ! 2584: hrErr = StgCreateDocfile( ! 2585: lpszStgName, ! 2586: grfMode | STGM_READWRITE | STGM_TRANSACTED, ! 2587: reserved, ! 2588: (LPSTORAGE FAR*)&lpRootStg ! 2589: ); ! 2590: ! 2591: if (hrErr == NOERROR) ! 2592: return lpRootStg; // existing file successfully opened ! 2593: ! 2594: OleDbgOutHResult("StgCreateDocfile returned", hrErr); ! 2595: ! 2596: if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPSTR)szMsg, 64)) ! 2597: return NULL; ! 2598: ! 2599: MessageBox(NULL, (LPSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK); ! 2600: return NULL; ! 2601: } ! 2602: ! 2603: ! 2604: /* ! 2605: ** OleStdCreateChildStorage ! 2606: ** create a child Storage inside the given lpStg that is compatible ! 2607: ** to be used by an embedded OLE object. the return value from this ! 2608: ** function can be passed to OleCreateXXX functions. ! 2609: ** NOTE: the child storage is opened in transacted mode. ! 2610: */ ! 2611: STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPSTR lpszStgName) ! 2612: { ! 2613: if (lpStg != NULL) { ! 2614: LPSTORAGE lpChildStg; ! 2615: DWORD grfMode = (STGM_READWRITE | STGM_TRANSACTED | ! 2616: STGM_SHARE_EXCLUSIVE); ! 2617: DWORD reserved = 0; ! 2618: ! 2619: HRESULT hrErr = lpStg->lpVtbl->CreateStorage( ! 2620: lpStg, ! 2621: lpszStgName, ! 2622: grfMode, ! 2623: reserved, ! 2624: reserved, ! 2625: (LPSTORAGE FAR*)&lpChildStg ! 2626: ); ! 2627: ! 2628: if (hrErr == NOERROR) ! 2629: return lpChildStg; ! 2630: ! 2631: OleDbgOutHResult("lpStg->lpVtbl->CreateStorage returned", hrErr); ! 2632: } ! 2633: return NULL; ! 2634: } ! 2635: ! 2636: ! 2637: /* ! 2638: ** OleStdOpenChildStorage ! 2639: ** open a child Storage inside the given lpStg that is compatible ! 2640: ** to be used by an embedded OLE object. the return value from this ! 2641: ** function can be passed to OleLoad function. ! 2642: ** NOTE: the child storage is opened in transacted mode. ! 2643: */ ! 2644: STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPSTR lpszStgName, DWORD grfMode) ! 2645: { ! 2646: LPSTORAGE lpChildStg; ! 2647: LPSTORAGE lpstgPriority = NULL; ! 2648: DWORD reserved = 0; ! 2649: HRESULT hrErr; ! 2650: ! 2651: if (lpStg != NULL) { ! 2652: ! 2653: hrErr = lpStg->lpVtbl->OpenStorage( ! 2654: lpStg, ! 2655: lpszStgName, ! 2656: lpstgPriority, ! 2657: grfMode | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE, ! 2658: NULL, ! 2659: reserved, ! 2660: (LPSTORAGE FAR*)&lpChildStg ! 2661: ); ! 2662: ! 2663: if (hrErr == NOERROR) ! 2664: return lpChildStg; ! 2665: ! 2666: OleDbgOutHResult("lpStg->lpVtbl->OpenStorage returned", hrErr); ! 2667: } ! 2668: return NULL; ! 2669: } ! 2670: ! 2671: /* OleStdCommitStorage ! 2672: ** ------------------- ! 2673: ** Commit the changes to the given IStorage*. This routine can be ! 2674: ** called on either a root-level storage as used by an OLE-Container ! 2675: ** or by a child storage as used by an embedded object. ! 2676: ** ! 2677: ** This routine first attempts to perform this commit in a safe ! 2678: ** manner. if this fails it then attempts to do the commit in a less ! 2679: ** robust manner (STGC_OVERWRITE). ! 2680: */ ! 2681: STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg) ! 2682: { ! 2683: HRESULT hrErr; ! 2684: ! 2685: // make the changes permanent ! 2686: hrErr = lpStg->lpVtbl->Commit(lpStg, 0); ! 2687: ! 2688: if (GetScode(hrErr) == STG_E_MEDIUMFULL) { ! 2689: // try to commit changes in less robust manner. ! 2690: OleDbgOut("Warning: commiting with STGC_OVERWRITE specified\n"); ! 2691: hrErr = lpStg->lpVtbl->Commit(lpStg, STGC_OVERWRITE); ! 2692: } ! 2693: ! 2694: if (hrErr != NOERROR) ! 2695: { ! 2696: char szMsg[64]; ! 2697: ! 2698: if (0 == LoadString(ghInst, IDS_OLESTDDISKFULL, (LPSTR)szMsg, 64)) ! 2699: return FALSE; ! 2700: ! 2701: MessageBox(NULL, (LPSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK); ! 2702: return FALSE; ! 2703: } ! 2704: else { ! 2705: return TRUE; ! 2706: } ! 2707: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.