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.

358 lines
9.5 KiB

  1. #include "precomp.hxx"
  2. #pragma hdrstop
  3. #include <shguidp.h> // CLSID_MyDocuments, CLSID_ShellFSFolder
  4. #include <shellp.h> // SHCoCreateInstance
  5. #include <shlguidp.h> // IID_IResolveShellLink
  6. #include "util.h"
  7. #include "dll.h"
  8. #include "resource.h"
  9. #include "prop.h"
  10. HRESULT _GetUIObjectForMyDocs(REFIID riid, void **ppv)
  11. {
  12. LPITEMIDLIST pidl;
  13. HRESULT hr = SHGetFolderLocation(NULL, CSIDL_PERSONAL | CSIDL_FLAG_NO_ALIAS, NULL, 0, &pidl);
  14. if (SUCCEEDED(hr))
  15. {
  16. hr = SHGetUIObjectFromFullPIDL(pidl, NULL, riid, ppv);
  17. ILFree(pidl);
  18. }
  19. return hr;
  20. }
  21. // send to "My Documents" handler
  22. class CMyDocsSendTo : public IDropTarget, IPersistFile
  23. {
  24. public:
  25. CMyDocsSendTo();
  26. HRESULT _InitTarget();
  27. // IUnknown
  28. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  29. STDMETHOD_(ULONG, AddRef)();
  30. STDMETHOD_(ULONG, Release)();
  31. // IDropTarget
  32. STDMETHODIMP DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
  33. STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
  34. STDMETHODIMP DragLeave();
  35. STDMETHODIMP Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
  36. // IPersist
  37. STDMETHOD(GetClassID)(CLSID *pClassID);
  38. // IPersistFile
  39. STDMETHOD(IsDirty)(void);
  40. STDMETHOD(Load)(LPCOLESTR pszFileName, DWORD dwMode);
  41. STDMETHOD(Save)(LPCOLESTR pszFileName, BOOL fRemember);
  42. STDMETHOD(SaveCompleted)(LPCOLESTR pszFileName);
  43. STDMETHOD(GetCurFile)(LPOLESTR *ppszFileName);
  44. private:
  45. ~CMyDocsSendTo();
  46. LONG _cRef;
  47. IDropTarget *_pdtgt;
  48. };
  49. CMyDocsSendTo::CMyDocsSendTo() : _cRef(1)
  50. {
  51. DllAddRef();
  52. }
  53. CMyDocsSendTo::~CMyDocsSendTo()
  54. {
  55. if (_pdtgt)
  56. _pdtgt->Release();
  57. DllRelease();
  58. }
  59. STDMETHODIMP CMyDocsSendTo::QueryInterface(REFIID riid, void **ppv)
  60. {
  61. static const QITAB qit[] = {
  62. QITABENT(CMyDocsSendTo, IDropTarget),
  63. QITABENT(CMyDocsSendTo, IPersistFile),
  64. QITABENTMULTI(CMyDocsSendTo, IPersist, IPersistFile),
  65. { 0 },
  66. };
  67. return QISearch(this, qit, riid, ppv);
  68. }
  69. STDMETHODIMP_(ULONG) CMyDocsSendTo::AddRef()
  70. {
  71. return InterlockedIncrement(&_cRef);
  72. }
  73. STDMETHODIMP_(ULONG) CMyDocsSendTo::Release()
  74. {
  75. ASSERT( 0 != _cRef );
  76. ULONG cRef = InterlockedDecrement(&_cRef);
  77. if ( 0 == cRef )
  78. {
  79. delete this;
  80. }
  81. return cRef;
  82. }
  83. HRESULT CMyDocsSendTo::_InitTarget()
  84. {
  85. if (_pdtgt)
  86. return S_OK;
  87. return _GetUIObjectForMyDocs(IID_PPV_ARG(IDropTarget, &_pdtgt));
  88. }
  89. STDMETHODIMP CMyDocsSendTo::DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  90. {
  91. *pdwEffect &= ~DROPEFFECT_MOVE; // don't let this be destructive
  92. HRESULT hr = _InitTarget();
  93. if (SUCCEEDED(hr))
  94. hr = _pdtgt->DragEnter(pDataObject, grfKeyState, pt, pdwEffect);
  95. return hr;
  96. }
  97. STDMETHODIMP CMyDocsSendTo::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  98. {
  99. *pdwEffect &= ~DROPEFFECT_MOVE; // don't let this be destructive
  100. HRESULT hr = _InitTarget();
  101. if (SUCCEEDED(hr))
  102. hr = _pdtgt->DragOver(grfKeyState, pt, pdwEffect);
  103. return hr;
  104. }
  105. STDMETHODIMP CMyDocsSendTo::DragLeave()
  106. {
  107. HRESULT hr = _InitTarget();
  108. if (SUCCEEDED(hr))
  109. hr = _pdtgt->DragLeave();
  110. return hr;
  111. }
  112. STDMETHODIMP CMyDocsSendTo::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  113. {
  114. *pdwEffect &= ~DROPEFFECT_MOVE; // don't let this be destructive
  115. HRESULT hr = _InitTarget();
  116. if (SUCCEEDED(hr))
  117. hr = _pdtgt->Drop(pDataObject, grfKeyState, pt, pdwEffect);
  118. return hr;
  119. }
  120. STDMETHODIMP CMyDocsSendTo::GetClassID(CLSID *pClassID)
  121. {
  122. *pClassID = CLSID_MyDocsDropTarget;
  123. return S_OK;
  124. }
  125. STDMETHODIMP CMyDocsSendTo::IsDirty(void)
  126. {
  127. return S_OK; // no
  128. }
  129. STDMETHODIMP CMyDocsSendTo::Load(LPCOLESTR pszFileName, DWORD dwMode)
  130. {
  131. if (_pdtgt)
  132. return S_OK;
  133. UpdateSendToFile(); // refresh the send to target (in case the desktop icon was renamed)
  134. return S_OK;
  135. }
  136. STDMETHODIMP CMyDocsSendTo::Save(LPCOLESTR pszFileName, BOOL fRemember)
  137. {
  138. return S_OK;
  139. }
  140. STDMETHODIMP CMyDocsSendTo::SaveCompleted(LPCOLESTR pszFileName)
  141. {
  142. return S_OK;
  143. }
  144. STDMETHODIMP CMyDocsSendTo::GetCurFile(LPOLESTR *ppszFileName)
  145. {
  146. *ppszFileName = NULL;
  147. return E_NOTIMPL;
  148. }
  149. HRESULT CMyDocsSendTo_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  150. {
  151. CMyDocsSendTo* pdt = new CMyDocsSendTo();
  152. if (pdt)
  153. {
  154. *ppunk = SAFECAST(pdt, IDropTarget *);
  155. return S_OK;
  156. }
  157. *ppunk = NULL;
  158. return E_OUTOFMEMORY;
  159. }
  160. // properyt page and context menu shell extension
  161. class CMyDocsProp : public IShellPropSheetExt, public IShellExtInit
  162. {
  163. public:
  164. CMyDocsProp();
  165. // IUnknown
  166. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  167. STDMETHOD_(ULONG, AddRef)();
  168. STDMETHOD_(ULONG, Release)();
  169. // IShellExtInit
  170. STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject *lpdobj, HKEY hkeyProgID);
  171. // IShellPropSheetExt
  172. STDMETHOD(AddPages)(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
  173. STDMETHOD(ReplacePage)(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam);
  174. private:
  175. ~CMyDocsProp();
  176. void _AddExtraPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
  177. LONG _cRef;
  178. };
  179. CMyDocsProp::CMyDocsProp() : _cRef(1)
  180. {
  181. DllAddRef();
  182. }
  183. CMyDocsProp::~CMyDocsProp()
  184. {
  185. DllRelease();
  186. }
  187. STDMETHODIMP CMyDocsProp::QueryInterface( REFIID riid, void **ppv)
  188. {
  189. static const QITAB qit[] = {
  190. QITABENT(CMyDocsProp, IShellPropSheetExt),
  191. QITABENT(CMyDocsProp, IShellExtInit),
  192. { 0 },
  193. };
  194. return QISearch(this, qit, riid, ppv);
  195. }
  196. STDMETHODIMP_ (ULONG) CMyDocsProp::AddRef()
  197. {
  198. return InterlockedIncrement(&_cRef);
  199. }
  200. STDMETHODIMP_ (ULONG) CMyDocsProp::Release()
  201. {
  202. ASSERT( 0 != _cRef );
  203. ULONG cRef = InterlockedDecrement(&_cRef);
  204. if ( 0 == cRef )
  205. {
  206. delete this;
  207. }
  208. return cRef;
  209. }
  210. STDMETHODIMP CMyDocsProp::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdobj, HKEY hkey)
  211. {
  212. return S_OK;
  213. }
  214. // {f81e9010-6ea4-11ce-a7ff-00aa003ca9f6}
  215. const CLSID CLSID_CShare = {0xf81e9010, 0x6ea4, 0x11ce, 0xa7, 0xff, 0x00, 0xaa, 0x00, 0x3c, 0xa9, 0xf6 };
  216. // {1F2E5C40-9550-11CE-99D2-00AA006E086C}
  217. const CLSID CLSID_RShellExt = {0x1F2E5C40, 0x9550, 0x11CE, 0x99, 0xD2, 0x00, 0xAA, 0x00, 0x6E, 0x08, 0x6C };
  218. const CLSID *c_rgFilePages[] = {
  219. &CLSID_ShellFileDefExt,
  220. &CLSID_CShare,
  221. &CLSID_RShellExt,
  222. };
  223. const CLSID *c_rgDrivePages[] = {
  224. &CLSID_ShellDrvDefExt,
  225. &CLSID_CShare,
  226. &CLSID_RShellExt,
  227. };
  228. // add optional pages to Explore/Options.
  229. void CMyDocsProp::_AddExtraPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  230. {
  231. IDataObject *pdtobj;
  232. if (SUCCEEDED(_GetUIObjectForMyDocs(IID_PPV_ARG(IDataObject, &pdtobj))))
  233. {
  234. TCHAR szPath[MAX_PATH];
  235. SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_DONT_VERIFY, NULL, SHGFP_TYPE_CURRENT, szPath);
  236. BOOL fDriveRoot = PathIsRoot(szPath) && !PathIsUNC(szPath);
  237. const CLSID** pCLSIDs = fDriveRoot ? c_rgDrivePages : c_rgFilePages;
  238. int nCLSIDs = (int)(fDriveRoot ? ARRAYSIZE(c_rgDrivePages) : ARRAYSIZE(c_rgFilePages));
  239. for (int i = 0; i < nCLSIDs; i++)
  240. {
  241. IUnknown *punk;
  242. // We need to CoCreate for IUnknown instead of IShellPropSheetExt because the
  243. // class factory for the Win9x sharing property sheet (msshrui.dll) is buggy
  244. // and return E_NOINTERFACE ISPSE...
  245. HRESULT hr = SHCoCreateInstance(NULL, pCLSIDs[i], NULL, IID_PPV_ARG(IUnknown, &punk));
  246. if (SUCCEEDED(hr))
  247. {
  248. IShellPropSheetExt *pspse;
  249. hr = punk->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
  250. punk->Release();
  251. if (SUCCEEDED(hr))
  252. {
  253. IShellExtInit *psei;
  254. if (SUCCEEDED(pspse->QueryInterface(IID_PPV_ARG(IShellExtInit, &psei))))
  255. {
  256. hr = psei->Initialize(NULL, pdtobj, NULL);
  257. psei->Release();
  258. }
  259. if (SUCCEEDED(hr))
  260. pspse->AddPages(pfnAddPage, lParam);
  261. pspse->Release();
  262. }
  263. }
  264. }
  265. }
  266. }
  267. STDMETHODIMP CMyDocsProp::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  268. {
  269. HRESULT hr = S_OK;
  270. PROPSHEETPAGE psp = {0};
  271. psp.dwSize = sizeof(psp);
  272. psp.dwFlags = PSP_DEFAULT;
  273. psp.hInstance = g_hInstance;
  274. psp.pszTemplate = MAKEINTRESOURCE(DLG_TARGET);
  275. psp.pfnDlgProc = TargetDlgProc;
  276. HPROPSHEETPAGE hPage = CreatePropertySheetPage( &psp );
  277. if (hPage)
  278. {
  279. pfnAddPage( hPage, lParam );
  280. _AddExtraPages(pfnAddPage, lParam);
  281. }
  282. return hr;
  283. }
  284. STDMETHODIMP CMyDocsProp::ReplacePage( UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
  285. {
  286. return E_NOTIMPL;
  287. }
  288. HRESULT CMyDocsProp_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  289. {
  290. CMyDocsProp* pmp = new CMyDocsProp();
  291. if (pmp)
  292. {
  293. *ppunk = SAFECAST(pmp, IShellExtInit *);
  294. return S_OK;
  295. }
  296. *ppunk = NULL;
  297. return E_OUTOFMEMORY;
  298. }