home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / inole / helpers.cpp < prev    next >
C/C++ Source or Header  |  1996-05-02  |  23KB  |  921 lines

  1. /*
  2.  * HELPERS.CPP
  3.  *
  4.  * Utility functions for drawing various graphical effects
  5.  * as well as coordinate conversion functions.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "inoledll.h"
  16.  
  17.  
  18. /*
  19.  * INOLE_MetafilePictIconFree
  20.  *
  21.  * Purpose:
  22.  *  Deletes the metafile contained in a METAFILEPICT structure and
  23.  *  frees the memory for the structure itself.
  24.  *
  25.  * Parameters:
  26.  *  hMetaPict       HGLOBAL metafilepict structure created in
  27.  *                  OleMetafilePictFromIconAndLabel
  28.  *
  29.  * Return Value:
  30.  *  None
  31.  */
  32.  
  33. STDAPI_(void) INOLE_MetafilePictIconFree(HGLOBAL hMetaPict)
  34.    {
  35.    LPMETAFILEPICT      pMF;
  36.  
  37.    if (NULL==hMetaPict)
  38.       return;
  39.  
  40.    pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict);
  41.  
  42.    if (NULL!=pMF)
  43.       {
  44.       if (NULL!=pMF->hMF)
  45.          DeleteMetaFile(pMF->hMF);
  46.       }
  47.  
  48.    GlobalUnlock(hMetaPict);
  49.    GlobalFree(hMetaPict);
  50.    return;
  51.    }
  52.  
  53.  
  54.  
  55.  
  56.  
  57. /*
  58.  * INOLE_SwitchDisplayAspect
  59.  *
  60.  * Purpose:
  61.  *  Switch the currently cached display aspect between DVASPECT_ICON
  62.  *  and DVASPECT_CONTENT.  When setting up icon aspect, any currently
  63.  *  cached content cache is discarded and any advise connections for
  64.  *  content aspect are broken.
  65.  *
  66.  * Parameters:
  67.  *  pObj            IUnknown * to the object in question
  68.  *  pdwCurAspect    DWORD * containing the current aspect which
  69.  *                  will contain the new aspect on output.
  70.  *  dwNewAspect     DWORD with the aspect to switch to.
  71.  *  hMetaPict       HGLOBAL containing the CF_METAFILEPICT with
  72.  *                  the icon.
  73.  *  fDeleteOld      BOOL indicating if we're to delete the old
  74.  *                  aspect from the cache.
  75.  *  fViewAdvise     BOOL indicating if we're to establish an
  76.  *                  advise with the object for this new aspect.
  77.  *  pSink           IAdviseSink * to the notification sink.
  78.  *  pfMustUpdate    BOOL * in which to return whether or not
  79.  *                  an update from a running server is necessary.
  80.  *
  81.  * Return Value:
  82.  *  HRESULT         NOERROR or an error code in which case the cache
  83.  *                  remains unchanged.
  84.  */
  85.  
  86. STDAPI INOLE_SwitchDisplayAspect(IUnknown *pObj, LPDWORD pdwCurAspect
  87.     , DWORD dwNewAspect, HGLOBAL hMetaPict, BOOL fDeleteOld
  88.     , BOOL fViewAdvise, IAdviseSink *pSink, BOOL *pfMustUpdate)
  89.     {
  90.     IOleCache      *pCache=NULL;
  91.     FORMATETC       fe;
  92.     STGMEDIUM       stm;
  93.     DWORD           dwAdvf;
  94.     DWORD           dwNewConnection;
  95.     DWORD           dwOldAspect=*pdwCurAspect;
  96.     HRESULT         hr;
  97.  
  98.     if (pfMustUpdate)
  99.        *pfMustUpdate=FALSE;
  100.  
  101.     hr=pObj->QueryInterface(IID_IOleCache, (void **)&pCache);
  102.  
  103.     if (FAILED(hr))
  104.        return ResultFromScode(E_FAIL);
  105.  
  106.     //Establish new cache with the new aspect
  107.     SETFormatEtc(fe, 0, dwNewAspect, NULL, TYMED_NULL, -1);
  108.  
  109.     /*
  110.      * If we are using a custom icon for the display aspect then
  111.      * we won't want to establish notifications with the data
  112.      * source, that is, we don't want to change the icon.  Otherwise
  113.      * we link up the given advise sink.
  114.      */
  115.     if (DVASPECT_ICON==dwNewAspect && NULL!=hMetaPict)
  116.        dwAdvf=ADVF_NODATA;
  117.     else
  118.        dwAdvf=ADVF_PRIMEFIRST;
  119.  
  120.     hr=pCache->Cache(&fe, dwAdvf, &dwNewConnection);
  121.  
  122.     if (FAILED(hr))
  123.         {
  124.         pCache->Release();
  125.         return hr;
  126.         }
  127.  
  128.     *pdwCurAspect=dwNewAspect;
  129.  
  130.     /*
  131.      * Stuff the custom icon into the cache, or force an update
  132.      * from the server.
  133.      */
  134.     if (DVASPECT_ICON==dwNewAspect && NULL!=hMetaPict)
  135.         {
  136.         SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  137.             , TYMED_MFPICT, -1);
  138.  
  139.         stm.tymed=TYMED_MFPICT;
  140.         stm.hGlobal=hMetaPict;
  141.         stm.pUnkForRelease=NULL;
  142.  
  143.         hr=pCache->SetData(&fe, &stm, FALSE);
  144.         }
  145.     else
  146.         {
  147.         if (pfMustUpdate)
  148.            *pfMustUpdate=TRUE;
  149.         }
  150.  
  151.     if (fViewAdvise && pSink)
  152.         {
  153.         IViewObject    *pView=NULL;
  154.  
  155.         hr=pObj->QueryInterface(IID_IViewObject, (void **)&pView);
  156.  
  157.         if (SUCCEEDED(hr))
  158.             {
  159.             pView->SetAdvise(dwNewAspect, 0, pSink);
  160.             pView->Release();
  161.             }
  162.         }
  163.  
  164.     /*
  165.      * Remove existing caches for the old display aspect to cut
  166.      * down on needless storage overhead.  If you want to switch
  167.      * frequently between icon and content aspects, then it is
  168.      * best to actually keep both presentations in the cache.
  169.      */
  170.     if (fDeleteOld)
  171.         {
  172.         IEnumSTATDATA  *pEnum=NULL;
  173.         STATDATA        sd;
  174.  
  175.         hr=pCache->EnumCache(&pEnum);
  176.  
  177.         while(NOERROR==hr)
  178.             {
  179.             hr=pEnum->Next(1, &sd, NULL);
  180.  
  181.             if (NOERROR==hr)
  182.                 {
  183.                 //Remove old aspect caches
  184.                 if (sd.formatetc.dwAspect==dwOldAspect)
  185.                     pCache->Uncache(sd.dwConnection);
  186.                 }
  187.             }
  188.  
  189.         if (NULL!=pEnum)
  190.             pEnum->Release();
  191.         }
  192.  
  193.     pCache->Release();
  194.     return NOERROR;
  195.     }
  196.  
  197.  
  198.  
  199. /*
  200.  * INOLE_SetIconInCache
  201.  *
  202.  * Purpose:
  203.  *  Stores an iconic presentation metafile in the cache.
  204.  *
  205.  * Parameters:
  206.  *  pObj            IUnknown * of the object.
  207.  *  hMetaPict       HGLOBAL containing the presentation.
  208.  *
  209.  * Return Value:
  210.  *  HRESULT         From IOleCache::SetData.
  211.  */
  212.  
  213. STDAPI INOLE_SetIconInCache(IUnknown *pObj, HGLOBAL hMetaPict)
  214.     {
  215.     IOleCache      *pCache;
  216.     FORMATETC       fe;
  217.     STGMEDIUM       stm;
  218.     HRESULT         hr;
  219.  
  220.     if (NULL==hMetaPict)
  221.         return ResultFromScode(E_INVALIDARG);
  222.  
  223.     if (FAILED(pObj->QueryInterface(IID_IOleCache, (void **)&pCache)))
  224.         return ResultFromScode(E_NOINTERFACE);
  225.  
  226.     SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  227.         , TYMED_MFPICT, -1);
  228.  
  229.     stm.tymed=TYMED_MFPICT;
  230.     stm.hGlobal=hMetaPict;
  231.     stm.pUnkForRelease=NULL;
  232.  
  233.     hr=pCache->SetData(&fe, &stm, FALSE);
  234.     pCache->Release();
  235.  
  236.     return hr;
  237.     }
  238.  
  239.  
  240.  
  241.  
  242.  
  243. /*
  244.  * INOLE_GetUserTypeOfClass
  245.  *
  246.  * Purpose:
  247.  *  Returns the user type (human readable class name) of the
  248.  *  specified class as stored in the registry.
  249.  *
  250.  * Parameters:
  251.  *  clsID           CLSID in question
  252.  *  iName           UINT index to the name to retrieve, where
  253.  *                  zero is the name found as the value of
  254.  *                  of the CLSID, anything else tries
  255.  *                  AuxUserType\iName.
  256.  *  pszUserType     LPTSTR in which to return the type
  257.  *  cch             UINT length of pszUserType
  258.  *
  259.  * Return Value:
  260.  *  UINT            Number of characters in returned string.
  261.  *                  0 on error.
  262.  */
  263.  
  264. STDAPI_(UINT) INOLE_GetUserTypeOfClass(REFCLSID clsID, UINT iName
  265.     , LPTSTR pszUserType, UINT cch)
  266.     {
  267.     LPTSTR      pszCLSID;
  268.     LPTSTR      pszProgID;
  269.     TCHAR       szKey[300];
  270.     LONG        dw;
  271.     LONG        lRet;
  272.  
  273.     if (!pszUserType)
  274.         return 0;
  275.  
  276.     *pszUserType='\0';
  277.  
  278.     //Get a string containing the class name
  279.     StringFromCLSID(clsID, &pszCLSID);
  280.  
  281.     if (0==iName)
  282.         wsprintf(szKey, TEXT("CLSID\\%s"), pszCLSID);
  283.     else
  284.         {
  285.         wsprintf(szKey, TEXT("CLSID\\%s\\AuxUserType\\%u")
  286.             , pszCLSID, iName);
  287.         }
  288.  
  289.     CoTaskMemFree(pszCLSID);
  290.  
  291.     dw=cch;
  292.     lRet=RegQueryValue(HKEY_CLASSES_ROOT, szKey, pszUserType, &dw);
  293.  
  294.     if (ERROR_SUCCESS!=lRet)
  295.         {
  296.         lstrcpyn(pszUserType, TEXT("Unknown"), cch);
  297.  
  298.         if (CoIsOle1Class(clsID))
  299.             {
  300.             //Try to get ProgID value for OLE 1 class
  301.             ProgIDFromCLSID(clsID, &pszProgID);
  302.  
  303.             dw=cch;
  304.             lRet=RegQueryValue(HKEY_CLASSES_ROOT, pszProgID
  305.                 , pszUserType, &dw);
  306.  
  307.             CoTaskMemFree(pszProgID);
  308.  
  309.             if (ERROR_SUCCESS!=lRet)
  310.                 dw=0;
  311.             }
  312.         }
  313.  
  314.     return (UINT)dw;
  315.     }
  316.  
  317.  
  318.  
  319.  
  320.  
  321. /*
  322.  * INOLE_DoConvert
  323.  *
  324.  * Purpose:
  325.  *  Convert an embedded or linked object to another type, working
  326.  *  in conjunection with OleUIConvert.
  327.  *
  328.  * Parameters:
  329.  *  pIStorage       IStorage * to the object's data.
  330.  *  clsID           CLSID to which we convert the object.
  331.  *
  332.  * Return Value:
  333.  *  HRESULT         The usual.
  334.  */
  335.  
  336. STDAPI INOLE_DoConvert(IStorage *pIStorage, REFCLSID clsID)
  337.     {
  338.     HRESULT     hr;
  339.     CLSID       clsIDOrg;
  340.     CLIPFORMAT  cfOrg;
  341.     LPTSTR      pszOrg=NULL;
  342.     TCHAR       szNew[256];
  343.  
  344.     if (FAILED(ReadClassStg(pIStorage, &clsIDOrg)))
  345.         return ResultFromScode(E_FAIL);
  346.  
  347.     //Read original format/user type
  348.     hr=ReadFmtUserTypeStg(pIStorage, &cfOrg, &pszOrg);
  349.  
  350.     //Get new user type
  351.     if (0==INOLE_GetUserTypeOfClass(clsID, 0, szNew, 256))
  352.         lstrcpy(szNew, TEXT(""));
  353.  
  354.     //Write new class into the storage
  355.     if (SUCCEEDED(WriteClassStg(pIStorage, clsID)))
  356.         {
  357.         if (SUCCEEDED(WriteFmtUserTypeStg(pIStorage, cfOrg
  358.             , szNew)))
  359.             {
  360.             SetConvertStg(pIStorage, TRUE);
  361.             CoTaskMemFree((void *)pszOrg);
  362.             return NOERROR;
  363.             }
  364.  
  365.         //Failed to write new type, restore the old class
  366.         WriteClassStg(pIStorage, clsIDOrg);
  367.         }
  368.  
  369.     CoTaskMemFree((void *)pszOrg);
  370.     return ResultFromScode(E_FAIL);
  371.     }
  372.  
  373.  
  374.  
  375.  
  376. /*
  377.  * INOLE_CopyString
  378.  *
  379.  * Purpose:
  380.  *  Copies a string allocated with CoTaskMemAlloc.
  381.  *
  382.  * Parameters:
  383.  *  pszSrc          LPTSTR to the string to copy.
  384.  *
  385.  * Return Value:
  386.  *  LPTSTR          New string or a NULL.
  387.  */
  388.  
  389. STDAPI_(LPTSTR) INOLE_CopyString(LPTSTR pszSrc)
  390.     {
  391.     IMalloc    *pIMalloc;
  392.     LPTSTR      pszDst;
  393.     UINT        cch;
  394.  
  395.     cch=lstrlen(pszSrc);
  396.  
  397.     if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  398.         return NULL;
  399.  
  400.     pszDst=(LPTSTR)pIMalloc->Alloc((cch+1)*sizeof(TCHAR));
  401.  
  402.     if (NULL!=pszDst)
  403.        lstrcpy(pszDst, pszSrc);
  404.  
  405.     pIMalloc->Release();
  406.     return pszDst;
  407.     }
  408.  
  409.  
  410.  
  411.  
  412. /*
  413.  * INOLE_ObjectDescriptorFromOleObject
  414.  *
  415.  * Purpose:
  416.  *  Fills and returns an OBJECTDESCRIPTOR structure. Information
  417.  *  for the structure is obtained from an IOleObject instance.
  418.  *
  419.  * Parameters:
  420.  *  pObj            IOleObject * from which to retrieve information.
  421.  *  dwAspect        DWORD with the display aspect
  422.  *  ptl             POINTL from upper-left corner of object where
  423.  *                  mouse went down for use with Drag & Drop.
  424.  *  pszl            LPSIZEL (optional) if the object is being scaled in
  425.  *                  its container, then the container should pass the
  426.  *                  extents that it is using to display the object.
  427.  *
  428.  * Return Value:
  429.  *  HBGLOBAL         Handle to OBJECTDESCRIPTOR structure.
  430.  */
  431.  
  432. STDAPI_(HGLOBAL) INOLE_ObjectDescriptorFromOleObject
  433.     (IOleObject *pObj, DWORD dwAspect, POINTL ptl, LPSIZEL pszl)
  434.     {
  435.     CLSID           clsID;
  436.     LPTSTR          pszName=NULL;
  437.     LPTSTR          pszSrc=NULL;
  438.     BOOL            fLink=FALSE;
  439.     IOleLink       *pLink;
  440.     TCHAR           szName[512];
  441.     DWORD           dwMisc=0;
  442.     SIZEL           szl;
  443.     HGLOBAL         hMem;
  444.     HRESULT         hr;
  445.    #ifdef WIN32ANSI
  446.    //#ifndef UNICODE
  447.     LPWSTR            pszw;
  448.     char            szTemp[512];
  449.    #endif 
  450.  
  451.     if (SUCCEEDED(pObj->QueryInterface(IID_IOleLink
  452.         , (void **)&pLink)))
  453.         fLink=TRUE;
  454.  
  455.     if (FAILED(pObj->GetUserClassID(&clsID)))
  456.         clsID=CLSID_NULL;
  457.  
  458.     //Get user string, expand to "Linked %s" if this is link
  459.    #ifndef WIN32ANSI
  460.    //#ifdef UNICODE
  461.     pObj->GetUserType(USERCLASSTYPE_FULL, &pszName);
  462.    #else
  463.     pObj->GetUserType(USERCLASSTYPE_FULL, &pszw);
  464.     WideCharToMultiByte(CP_ACP, 0, pszw, -1, szTemp
  465.         , sizeof(szTemp), NULL, NULL);
  466.     pszName=szTemp;
  467.    #endif
  468.  
  469.     if (fLink && NULL!=pszName)
  470.         wsprintf(szName, TEXT("Linked %s"), pszName);
  471.     else
  472.         lstrcpy(szName, pszName);
  473.  
  474.    #ifndef WIN32ANSI
  475.    //#ifdef UNICODE
  476.     CoTaskMemFree(pszName);
  477.    #else
  478.     CoTaskMemFree(pszw);
  479.     pszw=NULL;
  480.    #endif
  481.  
  482.     /*
  483.      * Get the source name of this object using either the
  484.      * link display name (for link) or a moniker display
  485.      * name.
  486.      */
  487.  
  488.     if (fLink)
  489.         {
  490.        #ifndef WIN32ANSI
  491.        //#ifdef UNICODE
  492.         hr=pLink->GetSourceDisplayName(&pszSrc);
  493.        #else
  494.         hr=pLink->GetSourceDisplayName(&pszw);
  495.         WideCharToMultiByte(CP_ACP, 0, pszw, -1, szTemp
  496.             , sizeof(szTemp), NULL, NULL);
  497.         pszSrc=szTemp;
  498.        #endif
  499.         }
  500.     else
  501.         {
  502.         IMoniker   *pmk;
  503.  
  504.         hr=pObj->GetMoniker(OLEGETMONIKER_TEMPFORUSER
  505.             , OLEWHICHMK_OBJFULL, &pmk);
  506.  
  507.         if (SUCCEEDED(hr))
  508.             {
  509.             IBindCtx  *pbc;
  510.             CreateBindCtx(0, &pbc);
  511.  
  512.            #ifndef WIN32ANSI
  513.            //#ifdef UNICODE
  514.             pmk->GetDisplayName(pbc, NULL, &pszSrc);
  515.             #else
  516.             pmk->GetDisplayName(pbc, NULL, &pszw);
  517.             WideCharToMultiByte(CP_ACP, 0, pszw, -1, szTemp
  518.                 , sizeof(szTemp), NULL, NULL);
  519.             pszSrc=szTemp;
  520.            #endif
  521.  
  522.             pbc->Release();
  523.  
  524.             pmk->Release();
  525.             }
  526.         }
  527.  
  528.     if (fLink)
  529.         pLink->Release();
  530.  
  531.     //Get MiscStatus bits
  532.     hr=pObj->GetMiscStatus(dwAspect, &dwMisc);
  533.  
  534.     //Get OBJECTDESCRIPTOR
  535.     hMem=INOLE_AllocObjectDescriptor(clsID, dwAspect, szl, ptl
  536.         , dwMisc, szName, pszSrc);
  537.  
  538.    #ifndef WIN32ANSI
  539.    //#ifdef UNICODE
  540.     CoTaskMemFree(pszSrc);
  541.    #else
  542.     if (NULL!=pszw)
  543.         CoTaskMemFree(pszw);
  544.    #endif
  545.  
  546.     return hMem;
  547.     }
  548.  
  549.  
  550.  
  551.  
  552.  
  553. /*
  554.  * INOLE_AllocObjectDescriptor
  555.  *
  556.  * Purpose:
  557.  *  Allocated and fills an OBJECTDESCRIPTOR structure.
  558.  *
  559.  * Parameters:
  560.  *  clsID           CLSID to store.
  561.  *  dwAspect        DWORD with the display aspect
  562.  *  pszl            LPSIZEL (optional) if the object is being scaled in
  563.  *                  its container, then the container should pass the
  564.  *                  extents that it is using to display the object.
  565.  *  ptl             POINTL from upper-left corner of object where
  566.  *                  mouse went down for use with Drag & Drop.
  567.  *  dwMisc          DWORD containing MiscStatus flags
  568.  *  pszName         LPTSTR naming the object to copy
  569.  *  pszSrc          LPTSTR identifying the source of the object.
  570.  *
  571.  * Return Value:
  572.  *  HBGLOBAL         Handle to OBJECTDESCRIPTOR structure.
  573.  */
  574.  
  575. STDAPI_(HGLOBAL) INOLE_AllocObjectDescriptor(CLSID clsID
  576.     , DWORD dwAspect, SIZEL szl, POINTL ptl, DWORD dwMisc
  577.     , LPTSTR pszName, LPTSTR pszSrc)
  578.     {
  579.     HGLOBAL              hMem=NULL;
  580.     LPOBJECTDESCRIPTOR   pOD;
  581.     DWORD                cb, cbStruct;
  582.     DWORD                cchName, cchSrc;
  583.  
  584.     cchName=lstrlen(pszName)+1;
  585.  
  586.     if (NULL!=pszSrc)
  587.         cchSrc=lstrlen(pszSrc)+1;
  588.     else
  589.         {
  590.         cchSrc=cchName;
  591.         pszSrc=pszName;
  592.         }
  593.  
  594.     /*
  595.      * Note:  CFSTR_OBJECTDESCRIPTOR is an ANSI structure.
  596.      * That means strings in it must be ANSI.  OLE will do
  597.      * internal conversions back to Unicode as necessary,
  598.      * but we have to put ANSI strings in it ourselves.
  599.      */
  600.     cbStruct=sizeof(OBJECTDESCRIPTOR);
  601.     cb=cbStruct+(sizeof(WCHAR)*(cchName+cchSrc));   //HACK
  602.  
  603.     hMem=GlobalAlloc(GHND, cb);
  604.  
  605.     if (NULL==hMem)
  606.         return NULL;
  607.  
  608.     pOD=(LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  609.  
  610.     pOD->cbSize=cb;
  611.     pOD->clsid=clsID;
  612.     pOD->dwDrawAspect=dwAspect;
  613.     pOD->sizel=szl;
  614.     pOD->pointl=ptl;
  615.     pOD->dwStatus=dwMisc;
  616.  
  617.     if (pszName)
  618.         {
  619.         pOD->dwFullUserTypeName=cbStruct;
  620.        #ifdef WIN32ANSI
  621.         MultiByteToWideChar(CP_ACP, 0, pszName, -1
  622.             , (LPWSTR)((LPBYTE)pOD+pOD->dwFullUserTypeName), cchName);
  623.        #else
  624.         lstrcpy((LPTSTR)((LPBYTE)pOD+pOD->dwFullUserTypeName)
  625.             , pszName);
  626.        #endif
  627.         }
  628.     else
  629.         pOD->dwFullUserTypeName=0;  //No string
  630.  
  631.     if (pszSrc)
  632.         {
  633.         pOD->dwSrcOfCopy=cbStruct+(cchName*sizeof(WCHAR));
  634.  
  635.        #ifdef WIN32ANSI
  636.         MultiByteToWideChar(CP_ACP, 0, pszSrc, -1
  637.             , (LPWSTR)((LPBYTE)pOD+pOD->dwSrcOfCopy), cchSrc);
  638.        #else
  639.         lstrcpy((LPTSTR)((LPBYTE)pOD+pOD->dwSrcOfCopy), pszSrc);
  640.        #endif
  641.         }
  642.     else
  643.         pOD->dwSrcOfCopy=0;  //No string
  644.  
  645.     GlobalUnlock(hMem);
  646.     return hMem;
  647.     }
  648.  
  649.  
  650.  
  651.  
  652.  
  653. /*
  654.  * INOLE_CreateStorageOnHGlobal
  655.  *
  656.  * Purpose:
  657.  *  Create a memory based storage object on an memory lockbytes.
  658.  *
  659.  * Parameters:
  660.  *  grfMode --  flags passed to StgCreateDocfileOnILockBytes
  661.  *
  662.  *  NOTE: if hGlobal is NULL, then a new IStorage is created and
  663.  *              STGM_CREATE flag is passed to StgCreateDocfileOnILockBytes.
  664.  *        if hGlobal is non-NULL, then it is assumed that the hGlobal already
  665.  *              has an IStorage inside it and STGM_CONVERT flag is passed
  666.  *              to StgCreateDocfileOnILockBytes.
  667.  *
  668.  * Return Value:
  669.  *  IStorage *      Pointer to the storage we create.
  670.  */
  671.  
  672. STDAPI_(IStorage *) INOLE_CreateStorageOnHGlobal(DWORD grfMode)
  673.     {
  674.     DWORD           grfCreate=grfMode | STGM_CREATE;
  675.     HRESULT         hr;
  676.     ILockBytes     *pLB=NULL;
  677.     IStorage       *pIStorage=NULL;
  678.  
  679.     hr=CreateILockBytesOnHGlobal(NULL, TRUE, &pLB);
  680.  
  681.     if (FAILED(hr))
  682.         return NULL;
  683.  
  684.     hr=StgCreateDocfileOnILockBytes(pLB, grfCreate, 0, &pIStorage);
  685.  
  686.     pLB->Release();
  687.  
  688.     return SUCCEEDED(hr) ? pIStorage : NULL;
  689.     }
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698. /*
  699.  * INOLE_GetLinkSourceData
  700.  *
  701.  * Purpose:
  702.  *  Creates a CFSTR_LINKSOURCE data format, that is, a serialized
  703.  *  moniker in a stream.
  704.  *
  705.  * Parameters:
  706.  *  pmk             IMoniker * of the link.
  707.  *  pClsID          CLSID * to write into the stream.
  708.  *  pFE             FORMATETC * describing the data which
  709.  *                  should have TYMED_ISTREAM in it.
  710.  *  pSTM            STGMEDIUM in which to return the data.
  711.  *                  If this has TYMED_NULL, then this function
  712.  *                  allocates the stream, otherwise it writes
  713.  *                  into the stream in pSTM->pstm.
  714.  */
  715.  
  716. STDAPI INOLE_GetLinkSourceData(IMoniker *pmk, LPCLSID pClsID
  717.     , LPFORMATETC pFE, LPSTGMEDIUM pSTM)
  718.     {
  719.     LPSTREAM    pIStream = NULL;
  720.     DWORD       reserved = 0;
  721.     HRESULT     hr;
  722.  
  723.     pSTM->pUnkForRelease=NULL;
  724.  
  725.     if (TYMED_NULL==pSTM->tymed)
  726.         {
  727.         if (pFE->tymed & TYMED_ISTREAM)
  728.             {
  729.             hr=CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
  730.  
  731.             if (FAILED(hr))
  732.                 return ResultFromScode(E_OUTOFMEMORY);
  733.  
  734.             pSTM->pstm=pIStream;
  735.             pSTM->tymed=TYMED_ISTREAM;
  736.             }
  737.         else
  738.             return ResultFromScode(DATA_E_FORMATETC);
  739.         }
  740.     else
  741.         {
  742.         if (TYMED_ISTREAM==pSTM->tymed)
  743.             {
  744.             pSTM->tymed=TYMED_ISTREAM;
  745.             pSTM->pstm=pSTM->pstm;
  746.             }
  747.         else
  748.             return ResultFromScode(DATA_E_FORMATETC);
  749.        }
  750.  
  751.     hr=OleSaveToStream(pmk, pSTM->pstm);
  752.  
  753.     if (FAILED(hr))
  754.         return hr;
  755.  
  756.     return WriteClassStm(pSTM->pstm, *pClsID);
  757.     }
  758.  
  759.  
  760.  
  761.  
  762.  
  763. /*
  764.  * INOLE_RegisterAsRunning
  765.  *
  766.  * Purpose:
  767.  *  Registers a moniker as running in the running object
  768.  *  table, revoking any existing registration.
  769.  *
  770.  * Parameters:
  771.  *  pUnk            IUnknown * of the object.
  772.  *  pmk             IMoniker * naming the object.
  773.  *  dwFlags         DWORD flags to pass to IROT::Register
  774.  *  pdwReg          LPDWORD in which to store the registration key.
  775.  *
  776.  * Return Value:
  777.  *  None
  778.  */
  779.  
  780. STDAPI_(void) INOLE_RegisterAsRunning(IUnknown *pUnk
  781.     , IMoniker *pmk, DWORD dwFlags, LPDWORD pdwReg)
  782.     {
  783.     IRunningObjectTable    *pROT;
  784.     HRESULT                 hr;
  785.     DWORD                   dwReg=*pdwReg;
  786.  
  787.     if (NULL==pmk || NULL==pUnk || NULL==pdwReg)
  788.         return;
  789.  
  790.     dwReg=*pdwReg;
  791.  
  792.     if (FAILED(GetRunningObjectTable(0, &pROT)))
  793.         return;
  794.  
  795.     hr=pROT->Register(dwFlags, pUnk, pmk, pdwReg);
  796.  
  797.     if (MK_S_MONIKERALREADYREGISTERED==GetScode(hr))
  798.         {
  799.         if (0!=dwReg)
  800.             pROT->Revoke(dwReg);
  801.         }
  802.  
  803.     pROT->Release();
  804.     return;
  805.     }
  806.  
  807.  
  808.  
  809. /*
  810.  * INOLE_RevokeAsRunning
  811.  *
  812.  * Purpose:
  813.  *  Wrapper for IRunningObjectTable::Revoke
  814.  *
  815.  * Parameters:
  816.  *  pdwReg          LPDWORD containing the key on input, zeroed
  817.  *                  on output.
  818.  *
  819.  * Return Value:
  820.  *  None
  821.  */
  822.  
  823. STDAPI_(void) INOLE_RevokeAsRunning(LPDWORD pdwReg)
  824.     {
  825.     IRunningObjectTable    *pROT;
  826.  
  827.     if (0==*pdwReg)
  828.         return;
  829.  
  830.     if (FAILED(GetRunningObjectTable(0, &pROT)))
  831.         return;
  832.  
  833.     pROT->Revoke(*pdwReg);
  834.     pROT->Release();
  835.  
  836.     *pdwReg=0;
  837.     return;
  838.     }
  839.  
  840.  
  841.  
  842. /*
  843.  * INOLE_NoteChangeTime
  844.  *
  845.  * Purpose:
  846.  *  Wrapper for IRunningObjectTable::NoteChangeTime
  847.  *
  848.  * Parameters:
  849.  *  dwReg           DWORD identifying the running object to note.
  850.  *  pft             FILETIME * containing the new time.  If NULL,
  851.  *                  then we'll get it from CoFileTimeNow.
  852.  *  pszFile         LPTSTR to a filename.  If pft is NULL, we'll
  853.  *                  retrieve times from this file.
  854.  *
  855.  * Return Value:
  856.  *  None
  857.  */
  858.  
  859. STDAPI_(void) INOLE_NoteChangeTime(DWORD dwReg, FILETIME *pft
  860.     , LPTSTR pszFile)
  861.     {
  862.     IRunningObjectTable    *pROT;
  863.     FILETIME                ft;
  864.  
  865.     if (NULL==pft)
  866.         {
  867.         CoFileTimeNow(&ft);
  868.         pft=&ft;
  869.         }
  870.  
  871.     if (NULL!=pszFile)
  872.         GetFileTimes(pszFile, pft);
  873.  
  874.     if (FAILED(GetRunningObjectTable(0, &pROT)))
  875.         return;
  876.  
  877.     pROT->NoteChangeTime(dwReg, pft);
  878.     pROT->Release();
  879.     return;
  880.     }
  881.  
  882.  
  883.  
  884.  
  885. /*
  886.  * GetFileTimes
  887.  * (Internal)
  888.  *
  889.  * Purpose:
  890.  *  Retrieve the FILETIME structure for a given file.
  891.  */
  892.  
  893. static BOOL GetFileTimes(LPTSTR pszFileName, FILETIME *pft)
  894.     {
  895.    #ifdef WIN32
  896.     WIN32_FIND_DATA fd;
  897.     HANDLE          hFind;
  898.  
  899.     hFind=FindFirstFile(pszFileName, &fd);
  900.  
  901.     if (NULL==hFind || INVALID_HANDLE_VALUE==hFind)
  902.         return FALSE;
  903.  
  904.     FindClose(hFind);
  905.     *pft=fd.ftLastWriteTime;
  906.     return TRUE;
  907.    #else
  908.     static char           sz[256];
  909.     static struct _find_t fileinfo;
  910.  
  911.     lstrcpyn((LPSTR)sz, pszFileName, sizeof(sz)-1);
  912.     sz[sizeof(sz)-1]= '\0';
  913.     AnsiToOem(sz, sz);
  914.  
  915.     return (_dos_findfirst(sz,_A_NORMAL|_A_HIDDEN|_A_SUBDIR|_A_SYSTEM
  916.         , (struct _find_t *)&fileinfo) == 0
  917.         && CoDosDateTimeToFileTime(fileinfo.wr_date, fileinfo.wr_time
  918.         , pft));
  919.    #endif
  920.     }
  921.