Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

318 lines
9.1 KiB

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