copyhook.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 9k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. // Copy Hook Handler for CDFView shell extension
  3. //
  4. // Description:
  5. //     This object installs an ICopyHook handler that traps all
  6. //     copies/movies/renames in the shell so that we can special 
  7. //     case links to channel objects and unsubscribe them when
  8. //     the link is deleted. The implementation is in shdocvw for
  9. //     speed.
  10. //
  11. // julianj 6/16/97
  12. // 
  13. #include "priv.h"
  14. #include "sccls.h"
  15. #include "chanmgr.h"
  16. #include "channel.h"
  17. #include "../resource.h"
  18. #include <mluisupp.h>
  19. class CCDFCopyHook 
  20.                         : public ICopyHookA
  21.                         , public ICopyHookW
  22. {
  23. public:
  24.     
  25.     // *** IUnknown ***
  26.     STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  27.     STDMETHODIMP_(ULONG) AddRef(void);
  28.     STDMETHODIMP_(ULONG) Release(void);
  29.     // *** ICopyHookA method ***
  30.     STDMETHODIMP_(UINT) CopyCallback(HWND hwnd, 
  31.         UINT wFunc, UINT wFlags, LPCSTR pszSrcFile, DWORD dwSrcAttribs, LPCSTR pszDestFile, DWORD dwDestAttribs);
  32.     // *** ICopyHookW method ***
  33.     STDMETHODIMP_(UINT) CopyCallback(HWND hwnd, 
  34.         UINT wFunc, UINT wFlags, LPCWSTR pwzSrcFile, DWORD dwSrcAttribs, LPCWSTR pwzDestFile, DWORD dwDestAttribs);
  35. private:
  36.     CCDFCopyHook( HRESULT * pHr);
  37.     ~CCDFCopyHook();
  38.     BOOL IsSubscriptionFolder(LPCTSTR pszPath);
  39.     LONG m_cRef;
  40.     friend HRESULT CCDFCopyHook_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);    // for ctor
  41. };
  42. //The copyhook handler uses this function
  43. HRESULT Channel_GetFolder(LPTSTR pszPath, int cchPath)
  44. {
  45.     TCHAR szChannel[MAX_PATH];
  46.     TCHAR szFav[MAX_PATH];
  47.     ULONG cbChannel = sizeof(szChannel);
  48.     
  49.     if (SHGetSpecialFolderPath(NULL, szFav, CSIDL_FAVORITES, TRUE))
  50.     {
  51.         //
  52.         // Get the potentially localized name of the Channel folder from the
  53.         // registry if it is there.  Otherwise just read it from the resource.
  54.         // Then tack this on the favorites path.
  55.         //
  56.         if (ERROR_SUCCESS != SHRegGetUSValue(L"Software\Microsoft\Windows\CurrentVersion",
  57.                                              L"ChannelFolderName", NULL, (void*)szChannel,
  58.                                              &cbChannel, TRUE, NULL, 0))
  59.         {
  60.             MLLoadString(IDS_CHANNEL, szChannel, ARRAYSIZE(szChannel));
  61.         }
  62.         PathCombine(pszPath, szFav, szChannel);
  63.         //
  64.         // For IE5+ use the channels dir if it exists - else use favorites
  65.         //
  66.         if (!PathFileExists(pszPath))
  67.             StrCpyN(pszPath, szFav, cchPath);
  68.         return S_OK;
  69.     }    
  70.     
  71.     return E_FAIL;
  72. }
  73. //
  74. // Basic CreateInstance for this object
  75. //
  76. HRESULT CCDFCopyHook_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  77. {
  78.     if ( pUnkOuter )
  79.         return CLASS_E_NOAGGREGATION;
  80.     HRESULT hr = NOERROR;
  81.     CCDFCopyHook * pCDFCopyHook = new CCDFCopyHook( & hr );
  82.     if ( !pCDFCopyHook )
  83.     {
  84.         return E_OUTOFMEMORY;
  85.     }
  86.     if ( FAILED( hr ))
  87.     {
  88.         delete pCDFCopyHook;
  89.         return hr;
  90.     }
  91.     
  92.     *ppunk = SAFECAST(pCDFCopyHook, ICopyHookA *);
  93.     return NOERROR;
  94. }
  95. STDMETHODIMP CCDFCopyHook::QueryInterface( REFIID riid, LPVOID * ppvObj )
  96. {
  97.     if (IsEqualIID(riid, IID_IUnknown) ||
  98.         IsEqualIID(riid, IID_IShellCopyHookA))
  99.     {
  100.         *ppvObj = SAFECAST(this, ICopyHookA *);
  101.     }
  102.     else if (IsEqualIID(riid, IID_IShellCopyHookW))
  103.     {
  104.         *ppvObj = SAFECAST(this, ICopyHookW *);
  105.     }
  106.     else
  107.     {
  108.         *ppvObj = NULL;
  109.         return E_NOINTERFACE;
  110.     }
  111.     AddRef();
  112.     return NOERROR;
  113. }
  114. STDMETHODIMP_ (ULONG) CCDFCopyHook::AddRef()
  115. {
  116.     return InterlockedIncrement(&m_cRef);
  117. }
  118. STDMETHODIMP_ (ULONG) CCDFCopyHook::Release()
  119. {
  120.     if (InterlockedDecrement(&m_cRef))
  121.         return m_cRef;
  122.     delete this;
  123.     return 0;
  124. }
  125. CCDFCopyHook::CCDFCopyHook( HRESULT * pHr) : m_cRef(1)
  126. {
  127.     *pHr = S_OK;
  128.     DllAddRef();
  129. }
  130. CCDFCopyHook::~CCDFCopyHook()
  131. {
  132.     DllRelease();
  133. }
  134. ////////////////////////////////////////////////////////////////////////////////
  135. //
  136. // ICopyHookA::CopyCallback
  137. //
  138. // Either allows the shell to move, copy, delete, or rename a folder or printer
  139. // object, or disallows the shell from carrying out the operation. The shell 
  140. // calls each copy hook handler registered for a folder or printer object until
  141. // either all the handlers have been called or one of them returns IDCANCEL.
  142. //
  143. // RETURNS:
  144. //
  145. //  IDYES    - Allows the operation.
  146. //  IDNO     - Prevents the operation on this file, but continues with any other
  147. //             operations (for example, a batch copy operation).
  148. //  IDCANCEL - Prevents the current operation and cancels any pending operations
  149. //
  150. ////////////////////////////////////////////////////////////////////////////////
  151. UINT CCDFCopyHook::CopyCallback(
  152.     HWND hwnd,          // Handle of the parent window for displaying UI objects
  153.     UINT wFunc,         // Operation to perform. 
  154.     UINT wFlags,        // Flags that control the operation 
  155.     LPCSTR pszSrcFile,  // Pointer to the source file 
  156.     DWORD dwSrcAttribs, // Source file attributes 
  157.     LPCSTR pszDestFile, // Pointer to the destination file 
  158.     DWORD dwDestAttribs // Destination file attributes 
  159. )
  160. {
  161.     WCHAR szSrcFile[MAX_PATH];
  162.     WCHAR szDestFile[MAX_PATH];
  163.     AnsiToUnicode(pszSrcFile, szSrcFile, ARRAYSIZE(szSrcFile));
  164.     if (pszDestFile)    // shell32.dll can call with NULL for pszDestFile
  165.         AnsiToUnicode(pszDestFile, szDestFile, ARRAYSIZE(szDestFile));
  166.     else
  167.         szDestFile[0] = L'';
  168.     return CopyCallback(hwnd, wFunc, wFlags, szSrcFile, dwSrcAttribs, szSrcFile, dwDestAttribs);
  169. }
  170. CCDFCopyHook::IsSubscriptionFolder(LPCTSTR pszPath)
  171. {
  172.     TCHAR szSubsPath[MAX_PATH] = {0};
  173.     DWORD dwSize = SIZEOF(szSubsPath);
  174.     if (SHGetValueGoodBoot(HKEY_LOCAL_MACHINE, REGSTR_PATH_SUBSCRIPTION,
  175.                        REGSTR_VAL_DIRECTORY, NULL, (LPBYTE)szSubsPath, &dwSize) != ERROR_SUCCESS)
  176.     {
  177.         TCHAR szWindows[MAX_PATH];
  178.         GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows));
  179.         PathCombine(szSubsPath, szWindows, TEXT("Offline Web Pages"));
  180.     }
  181.     return 0 == StrCmpI(pszPath, szSubsPath);
  182. }
  183. ////////////////////////////////////////////////////////////////////////////////
  184. //
  185. // ICopyHookW::CopyCallback
  186. //
  187. // Currently we just thunk to the ansi version.
  188. //
  189. ////////////////////////////////////////////////////////////////////////////////
  190. UINT CCDFCopyHook::CopyCallback(
  191.     HWND hwnd,          // Handle of the parent window for displaying UI objects
  192.     UINT wFunc,         // Operation to perform. 
  193.     UINT wFlags,        // Flags that control the operation 
  194.     LPCWSTR pszSrcFile,  // Pointer to the source file 
  195.     DWORD dwSrcAttribs, // Source file attributes 
  196.     LPCWSTR pszDestFile, // Pointer to the destination file 
  197.     DWORD dwDestAttribs // Destination file attributes 
  198. )
  199. {
  200.     HRESULT hr;
  201.     ICopyHookA * pCDFViewCopyHookA;
  202.     TCHAR   szPath[MAX_PATH];
  203.     //
  204.     // Return immediately if this isn't a system folder or if isn't a delete or
  205.     // rename operation
  206.     //
  207.     if (!(wFunc == FO_DELETE || wFunc == FO_RENAME))
  208.     {
  209.         return IDYES;
  210.     }
  211.     // no rename of channels folder allowed.
  212.     if ((wFunc == FO_RENAME) 
  213.             && (Channel_GetFolder(szPath, ARRAYSIZE(szPath)) == S_OK) 
  214.             && (StrCmpI(szPath, pszSrcFile) ==  0))
  215.     {
  216.         MessageBeep(MB_OK);
  217.         return IDNO;
  218.     }
  219.     if (SHRestricted2W(REST_NoRemovingSubscriptions, NULL, 0) &&
  220.         IsSubscriptionFolder(pszSrcFile))
  221.     {
  222.         MessageBeep(MB_OK);
  223.         return IDNO;
  224.     }
  225.     if (!(dwSrcAttribs & FILE_ATTRIBUTE_SYSTEM))
  226.         return IDYES;
  227.     //
  228.     // REVIEW could check for guid in desktop.ini matching CDFVIEW but its 
  229.     // cleaner to have the ChannelMgr know about that
  230.     //
  231.     //
  232.     // Create the channel manager object and ask it for the copy hook iface
  233.     //
  234.     hr = CoCreateInstance(CLSID_ChannelMgr, NULL,  CLSCTX_INPROC_SERVER, 
  235.                           IID_IShellCopyHookA, (void**)&pCDFViewCopyHookA);
  236.     if (SUCCEEDED(hr))
  237.     {
  238.         //
  239.         // Delegate to the Copy hook handler in the channel mgr
  240.         //
  241.         CHAR szSrcFile[MAX_PATH];
  242.         CHAR szDestFile[MAX_PATH] = {''};
  243.         SHUnicodeToAnsi(pszSrcFile, szSrcFile, ARRAYSIZE(szSrcFile));
  244.         if (pszDestFile)
  245.             SHUnicodeToAnsi(pszDestFile, szDestFile, ARRAYSIZE(szDestFile));
  246.         UINT retValue = pCDFViewCopyHookA->CopyCallback(
  247.                 hwnd, wFunc, wFlags, szSrcFile, 
  248.                 dwSrcAttribs, szDestFile, dwDestAttribs);
  249.         pCDFViewCopyHookA->Release();
  250.         return retValue;
  251.     }
  252.     else
  253.     {
  254.         // Couldn't create ChannelMgr object for some reason 
  255.         TraceMsg(TF_ERROR, "Could not CoCreateInstance CLSID_ChannelMgr");
  256.         return IDYES;
  257.     }
  258. }