OLESTD.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:12k
源码类别:

Windows编程

开发平台:

Visual C++

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