Annotation of mstools/ole20/samples/ole2ui/olestd.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.