home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / comctl / reitp / olestd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-01  |  12.2 KB  |  419 lines

  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-1997 All Rights Reserved
  11. **
  12. *************************************************************************/
  13.  
  14. #define NONAMELESSUNION     // use strict ANSI standard (for DVOBJ.H)
  15.  
  16. #define STRICT  1
  17. #include "olestd.h"
  18. #include <stdlib.h>
  19. #include <ctype.h>
  20. #include <shellapi.h>
  21. #include "common.h"
  22.  
  23. OLEDBGDATA
  24.  
  25. static char szAssertMemAlloc[] = "CoGetMalloc failed";
  26. static int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight);
  27.  
  28. //The instance handle shared amongst all dialogs.
  29. HINSTANCE     ghInst;
  30.  
  31.  
  32. /* OleStdSwitchDisplayAspect
  33. ** -------------------------
  34. **    Switch the currently cached display aspect between DVASPECT_ICON
  35. **    and DVASPECT_CONTENT.
  36. **
  37. **    NOTE: when setting up icon aspect, any currently cached content
  38. **    cache is discarded and any advise connections for content aspect
  39. **    are broken.
  40. **
  41. **    RETURNS:
  42. **      S_OK -- new display aspect setup successfully
  43. **      E_INVALIDARG -- IOleCache interface is NOT supported (this is
  44. **                  required).
  45. **      <other SCODE> -- any SCODE that can be returned by
  46. **                  IOleCache::Cache method.
  47. **      NOTE: if an error occurs then the current display aspect and
  48. **            cache contents unchanged.
  49. */
  50. STDAPI OleStdSwitchDisplayAspect(
  51.       LPOLEOBJECT             lpOleObj,
  52.       LPDWORD                 lpdwCurAspect,
  53.       DWORD                   dwNewAspect,
  54.       HGLOBAL                 hMetaPict,
  55.       BOOL                    fDeleteOldAspect,
  56.       BOOL                    fSetupViewAdvise,
  57.       LPADVISESINK            lpAdviseSink,
  58.       BOOL FAR*               lpfMustUpdate
  59. )
  60. {
  61.    LPOLECACHE      lpOleCache = NULL;
  62.    LPVIEWOBJECT    lpViewObj = NULL;
  63.    LPENUMSTATDATA  lpEnumStatData = NULL;
  64.    STATDATA        StatData;
  65.    FORMATETC       FmtEtc;
  66.    STGMEDIUM       Medium;
  67.    DWORD           dwAdvf;
  68.    DWORD           dwNewConnection;
  69.    DWORD           dwOldAspect = *lpdwCurAspect;
  70.    HRESULT         hrErr;
  71.  
  72.    if (lpfMustUpdate)
  73.       *lpfMustUpdate = FALSE;
  74.  
  75.    lpOleCache = (LPOLECACHE)OleStdQueryInterface(
  76.                               (LPUNKNOWN)lpOleObj,&IID_IOleCache);
  77.  
  78.    // if IOleCache* is NOT available, do nothing
  79.    if (! lpOleCache)
  80.       return E_INVALIDARG;
  81.  
  82.    // Setup new cache with the new aspect
  83.    FmtEtc.cfFormat = 0;     // whatever is needed to draw
  84.    FmtEtc.ptd      = NULL;
  85.    FmtEtc.dwAspect = dwNewAspect;
  86.    FmtEtc.lindex   = -1;
  87.    FmtEtc.tymed    = TYMED_NULL;
  88.  
  89.    /* NOTE: if we are setting up Icon aspect with a custom icon
  90.    **    then we do not want DataAdvise notifications to ever change
  91.    **    the contents of the data cache. thus we set up a NODATA
  92.    **    advise connection. otherwise we set up a standard DataAdvise
  93.    **    connection.
  94.    */
  95.    if (dwNewAspect == DVASPECT_ICON && hMetaPict)
  96.       dwAdvf = ADVF_NODATA;
  97.    else
  98.       dwAdvf = ADVF_PRIMEFIRST;
  99.  
  100.    OLEDBG_BEGIN2("IOleCache::Cache called\r\n")
  101.    hrErr = lpOleCache->lpVtbl->Cache(
  102.          lpOleCache,
  103.          (LPFORMATETC)&FmtEtc,
  104.          dwAdvf,
  105.          (LPDWORD)&dwNewConnection
  106.    );
  107.    OLEDBG_END2
  108.  
  109.    if (! SUCCEEDED(hrErr)) {
  110.       OleDbgOutHResult("IOleCache::Cache returned", hrErr);
  111.       OleStdRelease((LPUNKNOWN)lpOleCache);
  112.       return hrErr;
  113.    }
  114.  
  115.    *lpdwCurAspect = dwNewAspect;
  116.  
  117.    /* NOTE: if we are setting up Icon aspect with a custom icon,
  118.    **    then stuff the icon into the cache. otherwise the cache must
  119.    **    be forced to be updated. set the *lpfMustUpdate flag to tell
  120.    **    caller to force the object to Run so that the cache will be
  121.    **    updated.
  122.    */
  123.    if (dwNewAspect == DVASPECT_ICON && hMetaPict) {
  124.  
  125.       FmtEtc.cfFormat = CF_METAFILEPICT;
  126.       FmtEtc.ptd      = NULL;
  127.       FmtEtc.dwAspect = DVASPECT_ICON;
  128.       FmtEtc.lindex   = -1;
  129.       FmtEtc.tymed    = TYMED_MFPICT;
  130.  
  131.       Medium.tymed            = TYMED_MFPICT;
  132.       Medium.u.hGlobal        = hMetaPict;
  133.       Medium.pUnkForRelease   = NULL;
  134.  
  135.       OLEDBG_BEGIN2("IOleCache::SetData called\r\n")
  136.       hrErr = lpOleCache->lpVtbl->SetData(
  137.             lpOleCache,
  138.             (LPFORMATETC)&FmtEtc,
  139.             (LPSTGMEDIUM)&Medium,
  140.             FALSE   /* fRelease */
  141.       );
  142.       OLEDBG_END2
  143.    } else {
  144.       if (lpfMustUpdate)
  145.          *lpfMustUpdate = TRUE;
  146.    }
  147.  
  148.    if (fSetupViewAdvise && lpAdviseSink) {
  149.       /* NOTE: re-establish the ViewAdvise connection */
  150.       lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface(
  151.                               (LPUNKNOWN)lpOleObj,&IID_IViewObject);
  152.  
  153.       if (lpViewObj) {
  154.  
  155.          OLEDBG_BEGIN2("IViewObject::SetAdvise called\r\n")
  156.          lpViewObj->lpVtbl->SetAdvise(
  157.                lpViewObj,
  158.                dwNewAspect,
  159.                0,
  160.                lpAdviseSink
  161.          );
  162.          OLEDBG_END2
  163.  
  164.          OleStdRelease((LPUNKNOWN)lpViewObj);
  165.       }
  166.    }
  167.  
  168.    /* NOTE: remove any existing caches that are set up for the old
  169.    **    display aspect. It WOULD be possible to retain the caches set
  170.    **    up for the old aspect, but this would increase the storage
  171.    **    space required for the object and possibly require additional
  172.    **    overhead to maintain the unused cachaes. For these reasons the
  173.    **    strategy to delete the previous caches is prefered. if it is a
  174.    **    requirement to quickly switch between Icon and Content
  175.    **    display, then it would be better to keep both aspect caches.
  176.    */
  177.  
  178.    if (fDeleteOldAspect) {
  179.       OLEDBG_BEGIN2("IOleCache::EnumCache called\r\n")
  180.       hrErr = lpOleCache->lpVtbl->EnumCache(
  181.             lpOleCache,
  182.             (LPENUMSTATDATA FAR*)&lpEnumStatData
  183.       );
  184.       OLEDBG_END2
  185.  
  186.       while(hrErr == NOERROR) {
  187.          hrErr = lpEnumStatData->lpVtbl->Next(
  188.                lpEnumStatData,
  189.                1,
  190.                (LPSTATDATA)&StatData,
  191.                NULL
  192.          );
  193.          if (hrErr != NOERROR)
  194.             break;              // DONE! no more caches.
  195.  
  196.          if (StatData.formatetc.dwAspect == dwOldAspect) {
  197.  
  198.             // Remove previous cache with old aspect
  199.             OLEDBG_BEGIN2("IOleCache::Uncache called\r\n")
  200.             lpOleCache->lpVtbl->Uncache(lpOleCache,StatData.dwConnection);
  201.             OLEDBG_END2
  202.          }
  203.       }
  204.  
  205.       if (lpEnumStatData) {
  206.          OleStdVerifyRelease(
  207.                (LPUNKNOWN)lpEnumStatData,
  208.                OLESTR ("OleStdSwitchDisplayAspect: Cache enumerator NOT released"));
  209.       }
  210.    }
  211.  
  212.    if (lpOleCache)
  213.       OleStdRelease((LPUNKNOWN)lpOleCache);
  214.  
  215.    return NOERROR;
  216. }
  217.  
  218.  
  219. /* OleStdQueryInterface
  220. ** --------------------
  221. **    Returns the desired interface pointer if exposed by the given object.
  222. **    Returns NULL if the interface is not available.
  223. **    eg.:
  224. **      lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject);
  225. */
  226. STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid)
  227. {
  228.    LPUNKNOWN lpInterface;
  229.    HRESULT hrErr;
  230.  
  231.    hrErr = lpUnk->lpVtbl->QueryInterface(
  232.          lpUnk,
  233.          riid,
  234.          (LPVOID FAR*)&lpInterface
  235.    );
  236.  
  237.    if (hrErr == NOERROR)
  238.       return lpInterface;
  239.    else
  240.       return NULL;
  241. }
  242.  
  243.  
  244. /* OleStdFreeString
  245. ** ----------------
  246. **    Free a string that was allocated with the currently active
  247. **    IMalloc* allocator.
  248. **
  249. **    if the caller has the current IMalloc* handy, then it can be
  250. **    passed as a argument, otherwise this function will retrieve the
  251. **    active allocator and use it.
  252. */
  253. STDAPI_(void) OleStdFreeString(LPOLESTR lpsz, LPMALLOC lpMalloc)
  254. {
  255.    BOOL fMustRelease = FALSE;
  256.  
  257.    if (! lpMalloc) {
  258.       if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR)
  259.          return;
  260.       fMustRelease = TRUE;
  261.    }
  262.  
  263.    lpMalloc->lpVtbl->Free(lpMalloc, lpsz);
  264.  
  265.    if (fMustRelease)
  266.       lpMalloc->lpVtbl->Release(lpMalloc);
  267. }
  268.  
  269.  
  270. /* Call Release on the object that is expected to go away.
  271. **      if the refcnt of the object did no go to 0 then give a debug message.
  272. */
  273. STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPOLESTR lpszMsg)
  274. {
  275.    ULONG cRef;
  276.    char  lpszAnsiMsg[256];
  277.  
  278.    W2A (lpszMsg, lpszAnsiMsg, 256);
  279.    cRef = lpUnk->lpVtbl->Release(lpUnk);
  280.  
  281. #if defined( _DEBUG )
  282.    if (cRef != 0) {
  283.       char szBuf[80];
  284.       if (lpszMsg)
  285.          MessageBox(NULL, lpszAnsiMsg, NULL, MB_ICONEXCLAMATION | MB_OK);
  286.       wsprintf(
  287.             /*(LPSTR)*/szBuf,
  288.             "refcnt (%ld) != 0 after object (0x%lx) release\n",
  289.             cRef,
  290.             lpUnk
  291.       );
  292.       if (lpszMsg)
  293.          OleDbgOut1(lpszAnsiMsg);
  294.       OleDbgOut1(/*(LPSTR)*/szBuf);
  295.       OleDbgAssertSz(cRef == 0, /*(LPSTR)*/szBuf);
  296.    } else {
  297.       char szBuf[80];
  298.       wsprintf(
  299.             /*(LPSTR)*/szBuf,
  300.             "refcnt = 0 after object (0x%lx) release\n", lpUnk
  301.       );
  302.       OleDbgOut4(/*(LPSTR)*/szBuf);
  303.    }
  304. #endif
  305.    return cRef;
  306. }
  307.  
  308.  
  309. /* Call Release on the object that is NOT necessarily expected to go away.
  310. */
  311. STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk)
  312. {
  313.    ULONG cRef;
  314.  
  315.    cRef = lpUnk->lpVtbl->Release(lpUnk);
  316.  
  317. #if defined( _DEBUG )
  318.    {
  319.       char szBuf[80];
  320.       wsprintf(
  321.             /*(LPSTR)*/szBuf,
  322.             "refcnt = %ld after object (0x%lx) release\n",
  323.             cRef,
  324.             lpUnk
  325.       );
  326.       OleDbgOut4(/*(LPSTR)*/szBuf);
  327.    }
  328. #endif
  329.    return cRef;
  330. }
  331.  
  332.  
  333. /*************************************************************************
  334. ** OleStdCreateRootStorage
  335. **    create a root level Storage given a filename that is compatible
  336. **    to be used by a top-level OLE container. if the filename
  337. **    specifies an existing file, then an error is returned.
  338. **    the root storage (Docfile) that is created by this function
  339. **    is suitable to be used to create child storages for embedings.
  340. **    (CreateChildStorage can be used to create child storages.)
  341. **    NOTE: the root-level storage is opened in transacted mode.
  342. *************************************************************************/
  343.  
  344. STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPOLESTR lpszStgName, DWORD grfMode)
  345. {
  346.    HRESULT hr;
  347.    DWORD grfCreateMode = STGM_READWRITE | STGM_TRANSACTED;
  348.    DWORD reserved = 0;
  349.    LPSTORAGE lpRootStg;
  350.    char szMsg[64];
  351.  
  352.    // if temp file is being created, enable delete-on-release
  353.    if (! lpszStgName)
  354.       grfCreateMode |= STGM_DELETEONRELEASE;
  355.  
  356.    hr = StgCreateDocfile(
  357.          lpszStgName,
  358.          grfMode | grfCreateMode,
  359.          reserved,
  360.          (LPSTORAGE FAR*)&lpRootStg
  361.       );
  362.  
  363.    if (hr == NOERROR)
  364.       return lpRootStg;               // existing file successfully opened
  365.  
  366.    OleDbgOutHResult("StgCreateDocfile returned", hr);
  367.  
  368.    if (0 == LoadString(ghInst, (UINT)IDS_OLESTDNOCREATEFILE, /*(LPSTR)*/szMsg, 64))
  369.      return NULL;
  370.  
  371.    MessageBox(NULL, /*(LPSTR)*/szMsg, NULL,MB_ICONEXCLAMATION | MB_OK);
  372.    return NULL;
  373. }
  374.  
  375.  
  376. /*
  377. ** OleStdCreateChildStorage
  378. **    create a child Storage inside the given lpStg that is compatible
  379. **    to be used by an embedded OLE object. the return value from this
  380. **    function can be passed to OleCreateXXX functions.
  381. **    NOTE: the child storage is opened in transacted mode.
  382. */
  383. STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPOLESTR lpszStgName)
  384. {
  385.    if (lpStg != NULL) {
  386.       LPSTORAGE lpChildStg;
  387.       DWORD grfMode = (STGM_READWRITE | STGM_TRANSACTED |
  388.             STGM_SHARE_EXCLUSIVE);
  389.       DWORD reserved = 0;
  390.  
  391.       HRESULT hrErr = lpStg->lpVtbl->CreateStorage(
  392.             lpStg,
  393.             lpszStgName,
  394.             grfMode,
  395.             reserved,
  396.             reserved,
  397.             (LPSTORAGE FAR*)&lpChildStg
  398.          );
  399.  
  400.       if (hrErr == NOERROR)
  401.          return lpChildStg;
  402.  
  403.       OleDbgOutHResult("lpStg->lpVtbl->CreateStorage returned", hrErr);
  404.    }
  405.    return NULL;
  406. }
  407.  
  408. HRESULT HrGetClassFileA(LPCSTR szFilenameA, CLSID * pclsid)
  409. {
  410.     WCHAR lpszFilenameW[MAX_PATH];
  411.     HRESULT hr;
  412.  
  413.     A2W (szFilenameA, lpszFilenameW, MAX_PATH);
  414.  
  415.     hr = GetClassFile(lpszFilenameW, pclsid);
  416.  
  417.     return hr;
  418. }
  419.