|
|
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.