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

Windows编程

开发平台:

Visual C++

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