Source code of Windows XP (NT5)
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.

647 lines
14 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: ShellEx.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 4/25/1996 RaviR Created
  15. //
  16. //____________________________________________________________________________
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include <mstask.h>
  20. #include "..\folderui\dbg.h"
  21. #include "..\folderui\macros.h"
  22. #include "dll.hxx"
  23. #include "..\folderui\jobicons.hxx"
  24. #include "..\folderui\util.hxx"
  25. #include "schedui.hxx"
  26. extern "C" const GUID IID_IShellExtInit;
  27. extern "C" const GUID IID_IShellPropSheetExt;
  28. TCHAR const c_szTask[] = TEXT("task!");
  29. class CSchedObjExt : public IShellExtInit,
  30. //public IContextMenu,
  31. public IShellPropSheetExt
  32. {
  33. public:
  34. CSchedObjExt();
  35. ~CSchedObjExt();
  36. // IUnknown methods
  37. DECLARE_STANDARD_IUNKNOWN;
  38. // IShellExtInit methods
  39. STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj,
  40. HKEY hkeyProgID);
  41. // IShellPropSheetExt methods
  42. STDMETHOD(AddPages)(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);
  43. STDMETHOD(ReplacePage)(UINT uPageID,
  44. LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam);
  45. private:
  46. CDllRef m_DllRef;
  47. LPDATAOBJECT m_pdtobj; // data object
  48. HKEY m_hkeyProgID; // reg. database key to ProgID
  49. }; // CSchedObjExt
  50. inline
  51. CSchedObjExt::CSchedObjExt()
  52. :
  53. m_ulRefs(1),
  54. m_pdtobj(NULL),
  55. m_hkeyProgID(NULL)
  56. {
  57. TRACE(CSchedObjExt, CSchedObjExt);
  58. }
  59. CSchedObjExt::~CSchedObjExt()
  60. {
  61. TRACE(CSchedObjExt, ~CSchedObjExt);
  62. if (m_pdtobj)
  63. {
  64. m_pdtobj->Release();
  65. }
  66. if (m_hkeyProgID)
  67. {
  68. RegCloseKey(m_hkeyProgID);
  69. }
  70. }
  71. //
  72. // IUnknown implementation
  73. //
  74. IMPLEMENT_STANDARD_IUNKNOWN(CSchedObjExt);
  75. STDMETHODIMP
  76. CSchedObjExt::QueryInterface(REFIID riid, void **ppvObject)
  77. {
  78. IUnknown *pUnkTemp = NULL;
  79. HRESULT hr = S_OK;
  80. if (ppvObject == NULL)
  81. {
  82. return(E_INVALIDARG);
  83. }
  84. *ppvObject = NULL; // in case of error.
  85. if (IsEqualIID(IID_IUnknown, riid) ||
  86. IsEqualIID(IID_IShellExtInit, riid))
  87. {
  88. pUnkTemp = (IUnknown *)(IShellExtInit *)this;
  89. }
  90. else if (IsEqualIID(IID_IShellPropSheetExt, riid))
  91. {
  92. pUnkTemp = (IUnknown *)(IShellPropSheetExt *)this;
  93. }
  94. else
  95. {
  96. hr = E_NOINTERFACE;
  97. }
  98. if ((pUnkTemp != NULL) && (SUCCEEDED(hr)))
  99. {
  100. *ppvObject = (void*)pUnkTemp;
  101. pUnkTemp->AddRef();
  102. }
  103. return(hr);
  104. }
  105. //____________________________________________________________________________
  106. //
  107. // Member: CSchedObjExt::Initialize
  108. //
  109. // Synopsis: S
  110. //
  111. // Arguments: [pidlFolder] -- IN
  112. // [pdtobj] -- IN
  113. // [hkeyProgID] -- IN
  114. //
  115. // Returns: HRESULT.
  116. //
  117. // History: 4/25/1996 RaviR Created
  118. //
  119. //____________________________________________________________________________
  120. STDMETHODIMP
  121. CSchedObjExt::Initialize(
  122. LPCITEMIDLIST pidlFolder,
  123. LPDATAOBJECT pdtobj,
  124. HKEY hkeyProgID)
  125. {
  126. TRACE(CSchedObjExt, Initialize);
  127. // Initialize can be called more than once.
  128. if (m_pdtobj)
  129. {
  130. m_pdtobj->Release();
  131. }
  132. if (m_hkeyProgID)
  133. {
  134. RegCloseKey(m_hkeyProgID);
  135. m_hkeyProgID = NULL;
  136. }
  137. // Duplicate the pdtobj pointer
  138. m_pdtobj = pdtobj;
  139. if (pdtobj)
  140. {
  141. pdtobj->AddRef();
  142. }
  143. // Duplicate the handle
  144. if (hkeyProgID)
  145. {
  146. RegOpenKeyEx(hkeyProgID, NULL, 0, KEY_ALL_ACCESS, &m_hkeyProgID);
  147. }
  148. return S_OK;
  149. }
  150. //+-------------------------------------------------------------------------
  151. //
  152. // Member: CSchedObjExt::IShellPropSheetExt::AddPages
  153. //
  154. // Synopsis: (from shlobj.h)
  155. // "The explorer calls this member function when it finds a
  156. // registered property sheet extension for a particular type
  157. // of object. For each additional page, the extension creates
  158. // a page object by calling CreatePropertySheetPage API and
  159. // calls lpfnAddPage.
  160. //
  161. // Arguments: lpfnAddPage -- Specifies the callback function.
  162. // lParam -- Specifies the opaque handle to be passed to the
  163. // callback function.
  164. //
  165. // Returns:
  166. //
  167. // History: 12-Oct-94 RaviR
  168. //
  169. //--------------------------------------------------------------------------
  170. STDMETHODIMP
  171. CSchedObjExt::AddPages(
  172. LPFNADDPROPSHEETPAGE lpfnAddPage,
  173. LPARAM lParam)
  174. {
  175. TRACE(CSchedObjExt, AddPages);
  176. //
  177. // Call IDataObject::GetData asking for a CF_HDROP (i.e., HDROP).
  178. //
  179. HRESULT hr = S_OK;
  180. STGMEDIUM medium;
  181. FORMATETC fmte = {CF_HDROP, (DVTARGETDEVICE *)NULL, DVASPECT_CONTENT,
  182. -1, TYMED_HGLOBAL };
  183. hr = m_pdtobj->GetData(&fmte, &medium);
  184. if (FAILED(hr))
  185. {
  186. CHECK_HRESULT(hr);
  187. return hr;
  188. }
  189. do
  190. {
  191. //
  192. // Ensure it is only a single selection.
  193. //
  194. UINT cObjects = DragQueryFile((HDROP)medium.hGlobal,
  195. (UINT)-1, NULL, 0);
  196. if (cObjects != 1)
  197. {
  198. hr = S_FALSE;
  199. break;
  200. }
  201. //
  202. // Create shared info for all pages
  203. //
  204. TCHAR szFile[MAX_PATH + 1];
  205. UINT cchRet = DragQueryFile((HDROP)medium.hGlobal, 0, szFile,
  206. ARRAYLEN(szFile));
  207. //
  208. // Bind to the ITask interface.
  209. //
  210. ITask * pIJob = NULL;
  211. hr = JFCreateAndLoadTask(NULL, szFile, &pIJob);
  212. BREAK_ON_FAIL(hr);
  213. // Add the tasks page
  214. hr = AddGeneralPage(lpfnAddPage, lParam, pIJob);
  215. CHECK_HRESULT(hr);
  216. // Add the schedule page
  217. hr = AddSchedulePage(lpfnAddPage, lParam, pIJob);
  218. CHECK_HRESULT(hr);
  219. // Add the settings page
  220. hr = AddSettingsPage(lpfnAddPage, lParam, pIJob);
  221. CHECK_HRESULT(hr);
  222. pIJob->Release();
  223. } while (0);
  224. ReleaseStgMedium(&medium);
  225. return S_OK;
  226. }
  227. //+-------------------------------------------------------------------------
  228. //
  229. // Member: CSchedObjExt::IShellPropSheetExt::ReplacePages
  230. //
  231. // Synopsis: (From shlobj.h)
  232. // "The explorer never calls this member of property sheet
  233. // extensions. The explorer calls this member of control panel
  234. // extensions, so that they can replace some of default control
  235. // panel pages (such as a page of mouse control panel)."
  236. //
  237. // Arguments: uPageID -- Specifies the page to be replaced.
  238. // lpfnReplace -- Specifies the callback function.
  239. // lParam -- Specifies the opaque handle to be passed to the
  240. // callback function.
  241. //
  242. // Returns:
  243. //
  244. // History: 12-Oct-94 RaviR
  245. //
  246. //--------------------------------------------------------------------------
  247. STDMETHODIMP
  248. CSchedObjExt::ReplacePage(
  249. UINT uPageID,
  250. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  251. LPARAM lParam)
  252. {
  253. TRACE(CSchedObjExt, ReplacePage);
  254. Win4Assert(!"CSchedObjExt::ReplacePage called, not implemented");
  255. return E_NOTIMPL;
  256. }
  257. /////////////////////////////////////////////////////////////////////////////
  258. //____________________________________________________________________________
  259. //
  260. // Function: JFGetSchedObjExt
  261. //
  262. // Synopsis: Create an instance of CSchedObjExt and return the requested
  263. // interface.
  264. //
  265. // Arguments: [riid] -- IN interface needed.
  266. // [ppvObj] -- OUT place to store the interface.
  267. //
  268. // Returns: HRESULT
  269. //
  270. // History: 1/24/1996 RaviR Created
  271. //____________________________________________________________________________
  272. HRESULT
  273. JFGetSchedObjExt(
  274. REFIID riid,
  275. LPVOID* ppvObj)
  276. {
  277. CSchedObjExt * pSchedObjExt = new CSchedObjExt();
  278. HRESULT hr = S_OK;
  279. if (pSchedObjExt != NULL)
  280. {
  281. hr = pSchedObjExt->QueryInterface(riid, ppvObj);
  282. CHECK_HRESULT(hr);
  283. pSchedObjExt->Release();
  284. }
  285. else
  286. {
  287. hr = E_OUTOFMEMORY;
  288. CHECK_HRESULT(hr);
  289. }
  290. return hr;
  291. }
  292. //////////////////////////////////////////////////////////////////////////////
  293. //////////////////////////////////////////////////////////////////////////////
  294. //////////////////////////////////////////////////////////////////////////////
  295. //////////////////////////////////////////////////////////////////////////////
  296. //////////////////////////////////////////////////////////////////////////////
  297. class CTaskIconExt : public IExtractIcon,
  298. public IPersistFile
  299. {
  300. public:
  301. CTaskIconExt(void);
  302. ~CTaskIconExt(void);
  303. // IUnknown methods
  304. DECLARE_STANDARD_IUNKNOWN;
  305. // IExtractIcon methods
  306. STDMETHOD(GetIconLocation)(UINT uFlags, LPTSTR szIconFile, UINT cchMax,
  307. int *piIndex, UINT *pwFlags);
  308. STDMETHOD(Extract)(LPCTSTR pszFile, UINT nIconIndex, HICON *phiconLarge,
  309. HICON *phiconSmall, UINT nIconSize);
  310. // IPersistFile methods
  311. STDMETHOD(GetClassID)(LPCLSID lpClsID);
  312. STDMETHOD(IsDirty)();
  313. STDMETHOD(Load)(LPCOLESTR pszFile, DWORD grfMode);
  314. STDMETHOD(Save)(LPCOLESTR pszFile, BOOL fRemember);
  315. STDMETHOD(SaveCompleted)(LPCOLESTR pszFile);
  316. STDMETHOD(GetCurFile)(LPOLESTR FAR *ppszFile);
  317. private:
  318. TCHAR m_szTask[MAX_PATH + 1];
  319. }; // CTaskIconExt
  320. inline
  321. CTaskIconExt::CTaskIconExt(void)
  322. :
  323. m_ulRefs(1)
  324. {
  325. TRACE(CTaskIconExt, CTaskIconExt);
  326. m_szTask[0] = TEXT('\0');
  327. }
  328. inline
  329. CTaskIconExt::~CTaskIconExt(void)
  330. {
  331. TRACE(CTaskIconExt, ~CTaskIconExt);
  332. }
  333. //
  334. // IUnknown implementation
  335. //
  336. IMPLEMENT_STANDARD_IUNKNOWN(CTaskIconExt);
  337. STDMETHODIMP
  338. CTaskIconExt::QueryInterface(REFIID riid, LPVOID* ppvObj)
  339. {
  340. HRESULT hr = S_OK;
  341. if (IsEqualIID(IID_IUnknown, riid) ||
  342. IsEqualIID(IID_IPersistFile, riid))
  343. {
  344. *ppvObj = (IUnknown*)(IPersistFile*) this;
  345. }
  346. else if (IsEqualIID(IID_IExtractIcon, riid))
  347. {
  348. *ppvObj = (IUnknown*)(IExtractIcon*) this;
  349. }
  350. else
  351. {
  352. *ppvObj = NULL;
  353. hr = E_NOINTERFACE;
  354. }
  355. if (SUCCEEDED(hr))
  356. {
  357. this->AddRef();
  358. }
  359. return hr;
  360. }
  361. //____________________________________________________________________________
  362. //
  363. // Member: CTaskIconExt::IExtractIcon::GetIconLocation
  364. //
  365. // Arguments: [uFlags] -- IN
  366. // [szIconFile] -- IN
  367. // [cchMax] -- IN
  368. // [piIndex] -- IN
  369. // [pwFlags] -- IN
  370. //
  371. // Returns: HTRESULT
  372. //
  373. // History: 1/5/1996 RaviR Created
  374. //
  375. //____________________________________________________________________________
  376. STDMETHODIMP
  377. CTaskIconExt::GetIconLocation(
  378. UINT uFlags,
  379. LPTSTR szIconFile,
  380. UINT cchMax,
  381. int * piIndex,
  382. UINT * pwFlags)
  383. {
  384. TRACE(CTaskIconExt, GetIconLocation);
  385. if (uFlags & GIL_OPENICON)
  386. {
  387. return S_FALSE;
  388. }
  389. *pwFlags = GIL_NOTFILENAME | GIL_PERINSTANCE;
  390. HRESULT hr = S_OK;
  391. UINT len = lstrlen(c_szTask);
  392. lstrcpy(szIconFile, c_szTask);
  393. hr = JFGetAppNameForTask(m_szTask, &szIconFile[len], cchMax - len);
  394. *piIndex = FALSE;
  395. return hr;
  396. }
  397. //____________________________________________________________________________
  398. //
  399. // Member: CTaskIconExt::Extract
  400. //
  401. // Arguments: [pszFile] -- IN
  402. // [nIconIndex] -- IN
  403. // [phiconLarge] -- IN
  404. // [phiconSmall] -- IN
  405. // [nIconSize] -- IN
  406. //
  407. // Returns: STDMETHODIMP
  408. //
  409. // History: 1/5/1996 RaviR Created
  410. //____________________________________________________________________________
  411. STDMETHODIMP
  412. CTaskIconExt::Extract(
  413. LPCTSTR pszFile,
  414. UINT nIconIndex,
  415. HICON * phiconLarge,
  416. HICON * phiconSmall,
  417. UINT nIconSize)
  418. {
  419. TRACE(CTaskIconExt, Extract);
  420. LPTSTR pszApp = (LPTSTR)(pszFile + lstrlen(c_szTask));
  421. CJobIcon ji;
  422. ji.GetIcons(pszApp, FALSE, phiconLarge, phiconSmall);
  423. return S_OK;
  424. }
  425. //____________________________________________________________________________
  426. //
  427. // Member: CTaskIconExt::Load
  428. //
  429. // Synopsis: S
  430. //
  431. // Arguments: [pszFile] -- IN
  432. // [grfMode] -- IN
  433. //
  434. // Returns: HRESULT.
  435. //
  436. // History: 4/25/1996 RaviR Created
  437. //
  438. //____________________________________________________________________________
  439. STDMETHODIMP
  440. CTaskIconExt::Load(
  441. LPCOLESTR pszFile,
  442. DWORD grfMode)
  443. {
  444. TRACE(CTaskIconExt, Load);
  445. #ifdef UNICODE
  446. lstrcpy(m_szTask, pszFile);
  447. #else
  448. UnicodeToAnsi(m_szTask, pszFile, MAX_PATH+1);
  449. #endif
  450. return S_OK;
  451. }
  452. // The following functions, which are part of the OLE IPersistFile interface,
  453. // are not required for shell extensions. In the unlikely event that they are
  454. // called, they return the error code E_FAIL.
  455. //
  456. STDMETHODIMP CTaskIconExt::GetClassID(LPCLSID lpClsID)
  457. {
  458. return E_FAIL;
  459. }
  460. STDMETHODIMP CTaskIconExt::IsDirty()
  461. {
  462. return E_FAIL;
  463. }
  464. STDMETHODIMP CTaskIconExt::Save(LPCOLESTR pszFile, BOOL fRemember)
  465. {
  466. return E_FAIL;
  467. }
  468. STDMETHODIMP CTaskIconExt::SaveCompleted(LPCOLESTR pszFile)
  469. {
  470. return E_FAIL;
  471. }
  472. STDMETHODIMP CTaskIconExt::GetCurFile(LPOLESTR FAR *ppszFile)
  473. {
  474. return E_FAIL;
  475. }
  476. //____________________________________________________________________________
  477. //
  478. // Function: JFGetTaskIconExt
  479. //
  480. // Synopsis: Create an instance of CTaskIconExt and return the requested
  481. // interface.
  482. //
  483. // Arguments: [riid] -- IN interface needed.
  484. // [ppvObj] -- OUT place to store the interface.
  485. //
  486. // Returns: HRESULT
  487. //
  488. // History: 1/24/1996 RaviR Created
  489. //____________________________________________________________________________
  490. HRESULT
  491. JFGetTaskIconExt(
  492. REFIID riid,
  493. LPVOID* ppvObj)
  494. {
  495. TRACE_FUNCTION(JFGetTaskIconExt);
  496. CTaskIconExt * pTaskIconExt = new CTaskIconExt();
  497. HRESULT hr = S_OK;
  498. if (pTaskIconExt != NULL)
  499. {
  500. hr = pTaskIconExt->QueryInterface(riid, ppvObj);
  501. CHECK_HRESULT(hr);
  502. pTaskIconExt->Release();
  503. }
  504. else
  505. {
  506. hr = E_OUTOFMEMORY;
  507. CHECK_HRESULT(hr);
  508. }
  509. return hr;
  510. }