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.

957 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: cpaction.cpp
  8. //
  9. // This module implements the various 'action' objects used by the
  10. // Control Panel's 'category' view. Each 'link' in the UI has an
  11. // associated 'action'. The action objects are defined in cpnamespc.cpp.
  12. // All 'action' objects are designed so that object construction is
  13. // very cheap and that minimal processing is performed until the action
  14. // is invoked.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "shellprv.h"
  18. #include <idhidden.h>
  19. #include "cpviewp.h"
  20. #include "cpaction.h"
  21. #include "cpguids.h"
  22. #include "cpuiele.h"
  23. #include "cputil.h"
  24. //// from shell\sdspatch\sdfolder.cpp
  25. VARIANT_BOOL GetBarricadeStatus(LPCTSTR pszValueName);
  26. //
  27. // Disable warning. ShellExecute uses SEH.
  28. // "nonstandard extension used: 'Execute' uses SEH and 'se' has destructor".
  29. //
  30. #pragma warning( push )
  31. #pragma warning( disable:4509 )
  32. using namespace CPL;
  33. HRESULT
  34. CRestrictApplet::IsRestricted(
  35. ICplNamespace *pns
  36. ) const
  37. {
  38. UNREFERENCED_PARAMETER(pns);
  39. DBG_ENTER(FTF_CPANEL, "RestrictApplet");
  40. HRESULT hr = S_FALSE;
  41. if (!IsAppletEnabled(m_pszFile, m_pszApplet))
  42. {
  43. hr = S_OK;
  44. }
  45. DBG_EXIT_HRES(FTF_CPANEL, "RestrictApplet", hr);
  46. return hr;
  47. }
  48. //--------------------------------------------------------------------------
  49. // CAction implementation
  50. //--------------------------------------------------------------------------
  51. CAction::CAction(
  52. const CPL::IRestrict *pRestrict // optional. default = NULL
  53. ) : m_pRestrict(pRestrict)
  54. {
  55. }
  56. //
  57. // Returns:
  58. // S_FALSE - Not restricted.
  59. // S_OK - Restricted.
  60. // Failure - Cannot determine.
  61. //
  62. HRESULT
  63. CAction::IsRestricted(
  64. ICplNamespace *pns
  65. ) const
  66. {
  67. HRESULT hr = S_FALSE; // Assume not restricted.
  68. if (NULL != m_pRestrict)
  69. {
  70. hr = m_pRestrict->IsRestricted(pns);
  71. }
  72. return THR(hr);
  73. }
  74. //--------------------------------------------------------------------------
  75. // COpenUserMgrApplet implementation
  76. //--------------------------------------------------------------------------
  77. COpenUserMgrApplet::COpenUserMgrApplet(
  78. const CPL::IRestrict *pRestrict // optional. default = NULL
  79. ): CAction(pRestrict)
  80. {
  81. }
  82. HRESULT
  83. COpenUserMgrApplet::Execute(
  84. HWND hwndParent,
  85. IUnknown *punkSite
  86. ) const
  87. {
  88. DBG_ENTER(FTF_CPANEL, "COpenUserMgrApplet::Execute");
  89. HRESULT hr = E_FAIL;
  90. if (IsOsServer())
  91. {
  92. CShellExecute action(L"lusrmgr.msc");
  93. hr = action.Execute(hwndParent, punkSite);
  94. }
  95. else
  96. {
  97. COpenCplApplet action(L"nusrmgr.cpl");
  98. hr = action.Execute(hwndParent, punkSite);
  99. }
  100. DBG_EXIT_HRES(FTF_CPANEL, "COpenUserMgrApplet::Execute", hr);
  101. return THR(hr);
  102. }
  103. //--------------------------------------------------------------------------
  104. // COpenCplApplet implementation
  105. //--------------------------------------------------------------------------
  106. COpenCplApplet::COpenCplApplet(
  107. LPCWSTR pszApplet,
  108. const CPL::IRestrict *pRestrict // optional. default = NULL
  109. ) : CAction(pRestrict),
  110. m_pszApplet(pszApplet)
  111. {
  112. ASSERT(NULL != pszApplet);
  113. }
  114. HRESULT
  115. COpenCplApplet::Execute(
  116. HWND hwndParent,
  117. IUnknown *punkSite
  118. ) const
  119. {
  120. DBG_ENTER(FTF_CPANEL, "COpenCplApplet::Execute");
  121. ASSERT(NULL != m_pszApplet);
  122. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  123. UNREFERENCED_PARAMETER(punkSite);
  124. WCHAR szArgs[MAX_PATH];
  125. wsprintfW(szArgs, L"shell32.dll,Control_RunDLL %s", m_pszApplet);
  126. TraceMsg(TF_CPANEL, "Executing: \"rundll32.exe %s\"", szArgs);
  127. SHELLEXECUTEINFOW sei = {
  128. sizeof(sei), // cbSize;
  129. SEE_MASK_DOENVSUBST, // fMask
  130. hwndParent, // hwnd
  131. NULL, // lpVerb
  132. L"rundll32.exe", // lpFile
  133. szArgs, // lpParameters
  134. NULL, // lpDirectory
  135. SW_SHOWNORMAL, // nShow
  136. 0, // hInstApp
  137. NULL, // lpIDList
  138. NULL, // lpClass
  139. NULL, // hkeyClass
  140. 0, // dwHotKey
  141. NULL, // hIcon
  142. NULL // hProcess
  143. };
  144. HRESULT hr = S_OK;
  145. if (!ShellExecuteExW(&sei))
  146. {
  147. hr = CPL::ResultFromLastError();
  148. }
  149. DBG_EXIT_HRES(FTF_CPANEL, "COpenCplApplet::Execute", hr);
  150. return THR(hr);
  151. }
  152. //--------------------------------------------------------------------------
  153. // COpenDeskCpl implementation
  154. //--------------------------------------------------------------------------
  155. COpenDeskCpl::COpenDeskCpl(
  156. eDESKCPLTAB eCplTab,
  157. const CPL::IRestrict *pRestrict // optional. default = NULL
  158. ) : CAction(pRestrict),
  159. m_eCplTab(eCplTab)
  160. {
  161. }
  162. HRESULT
  163. COpenDeskCpl::Execute(
  164. HWND hwndParent,
  165. IUnknown *punkSite
  166. ) const
  167. {
  168. DBG_ENTER(FTF_CPANEL, "COpenDeskCpl::Execute");
  169. TraceMsg(TF_CPANEL, "Desk CPL tab ID = %d", m_eCplTab);
  170. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  171. UNREFERENCED_PARAMETER(punkSite);
  172. HRESULT hr = E_FAIL;
  173. WCHAR szTab[MAX_PATH];
  174. const int iTab = CPL::DeskCPL_GetTabIndex(m_eCplTab, szTab, ARRAYSIZE(szTab));
  175. if (CPLTAB_ABSENT != iTab)
  176. {
  177. WCHAR szArgs[MAX_PATH];
  178. wnsprintfW(szArgs, ARRAYSIZE(szArgs), L"desk.cpl ,@%ls", szTab);
  179. COpenCplApplet oca(szArgs);
  180. hr = oca.Execute(hwndParent, punkSite);
  181. }
  182. DBG_EXIT_HRES(FTF_CPANEL, "COpenDeskCpl::Execute", hr);
  183. return THR(hr);
  184. }
  185. //--------------------------------------------------------------------------
  186. // CNavigateURL implementation
  187. //--------------------------------------------------------------------------
  188. CNavigateURL::CNavigateURL(
  189. LPCWSTR pszURL,
  190. const CPL::IRestrict *pRestrict // optional. default = NULL
  191. ) : CAction(pRestrict),
  192. m_pszURL(pszURL)
  193. {
  194. ASSERT(NULL != pszURL);
  195. }
  196. HRESULT
  197. CNavigateURL::Execute(
  198. HWND hwndParent,
  199. IUnknown *punkSite
  200. ) const
  201. {
  202. DBG_ENTER(FTF_CPANEL, "CNavigateURL::Execute");
  203. ASSERT(NULL != m_pszURL);
  204. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  205. UNREFERENCED_PARAMETER(hwndParent);
  206. TraceMsg(TF_CPANEL, "URL = \"%s\"", m_pszURL);
  207. IWebBrowser2 *pwb;
  208. HRESULT hr = IUnknown_QueryService(punkSite, SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pwb);
  209. if (SUCCEEDED(hr))
  210. {
  211. LPTSTR pszExpanded;
  212. hr = CPL::ExpandEnvironmentVars(m_pszURL, &pszExpanded);
  213. if (SUCCEEDED(hr))
  214. {
  215. VARIANT varURL;
  216. hr = InitVariantFromStr(&varURL, pszExpanded);
  217. if (SUCCEEDED(hr))
  218. {
  219. VARIANT varEmpty;
  220. VariantInit(&varEmpty);
  221. VARIANT varFlags;
  222. varFlags.vt = VT_UINT;
  223. varFlags.uintVal = 0;
  224. hr = pwb->Navigate2(&varURL, &varFlags, &varEmpty, &varEmpty, &varEmpty);
  225. VariantClear(&varURL);
  226. }
  227. LocalFree(pszExpanded);
  228. }
  229. pwb->Release();
  230. }
  231. DBG_EXIT_HRES(FTF_CPANEL, "CNavigateURL::Execute", hr);
  232. return THR(hr);
  233. }
  234. //--------------------------------------------------------------------------
  235. // COpenTroubleshooter implementation
  236. //--------------------------------------------------------------------------
  237. COpenTroubleshooter::COpenTroubleshooter(
  238. LPCWSTR pszTs,
  239. const CPL::IRestrict *pRestrict // optional. default = NULL
  240. ) : CAction(pRestrict),
  241. m_pszTs(pszTs)
  242. {
  243. ASSERT(NULL != pszTs);
  244. }
  245. HRESULT
  246. COpenTroubleshooter::Execute(
  247. HWND hwndParent,
  248. IUnknown *punkSite
  249. ) const
  250. {
  251. DBG_ENTER(FTF_CPANEL, "COpenTroubleshooter::Execute");
  252. ASSERT(NULL != m_pszTs);
  253. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  254. UNREFERENCED_PARAMETER(punkSite);
  255. WCHAR szPath[MAX_PATH];
  256. wnsprintfW(szPath, ARRAYSIZE(szPath), L"hcp://help/tshoot/%s", m_pszTs);
  257. CNavigateURL actionURL(szPath);
  258. HRESULT hr = actionURL.Execute(hwndParent, punkSite);
  259. DBG_EXIT_HRES(FTF_CPANEL, "COpenTroubleshooter::Execute", hr);
  260. return THR(hr);
  261. }
  262. //--------------------------------------------------------------------------
  263. // CShellExecute implementation
  264. //--------------------------------------------------------------------------
  265. CShellExecute::CShellExecute(
  266. LPCWSTR pszExe,
  267. LPCWSTR pszArgs, // optional. default = NULL.
  268. const CPL::IRestrict *pRestrict // optional. default = NULL
  269. ) : CAction(pRestrict),
  270. m_pszExe(pszExe),
  271. m_pszArgs(pszArgs)
  272. {
  273. ASSERT(NULL != pszExe);
  274. }
  275. HRESULT
  276. CShellExecute::Execute(
  277. HWND hwndParent,
  278. IUnknown *punkSite
  279. ) const
  280. {
  281. DBG_ENTER(FTF_CPANEL, "CShellExecute::Execute");
  282. ASSERT(NULL != m_pszExe);
  283. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  284. UNREFERENCED_PARAMETER(punkSite);
  285. TraceMsg(TF_CPANEL, "ShellExecute: \"%s %s\"", m_pszExe, m_pszArgs ? m_pszArgs : L"<no args>");
  286. SHELLEXECUTEINFOW sei = {
  287. sizeof(sei), // cbSize;
  288. SEE_MASK_DOENVSUBST, // fMask
  289. hwndParent, // hwnd
  290. L"open", // lpVerb
  291. m_pszExe, // lpFile
  292. m_pszArgs, // lpParameters
  293. NULL, // lpDirectory
  294. SW_SHOWNORMAL, // nShow
  295. 0, // hInstApp
  296. NULL, // lpIDList
  297. NULL, // lpClass
  298. NULL, // hkeyClass
  299. 0, // dwHotKey
  300. NULL, // hIcon
  301. NULL // hProcess
  302. };
  303. HRESULT hr = S_OK;
  304. if (!ShellExecuteExW(&sei))
  305. {
  306. hr = CPL::ResultFromLastError();
  307. }
  308. DBG_EXIT_HRES(FTF_CPANEL, "CShellExecute::Execute", hr);
  309. return THR(hr);
  310. }
  311. //--------------------------------------------------------------------------
  312. // CRundll32 implementation
  313. // This is a simple wrapper around CShellExecute that saves an instance
  314. // definition from having to type L"%SystemRoot%\\system32\\rundll32.exe".
  315. //--------------------------------------------------------------------------
  316. CRunDll32::CRunDll32(
  317. LPCWSTR pszArgs,
  318. const CPL::IRestrict *pRestrict // optional. default = NULL
  319. ) : CAction(pRestrict),
  320. m_pszArgs(pszArgs)
  321. {
  322. ASSERT(NULL != pszArgs);
  323. }
  324. HRESULT
  325. CRunDll32::Execute(
  326. HWND hwndParent,
  327. IUnknown *punkSite
  328. ) const
  329. {
  330. DBG_ENTER(FTF_CPANEL, "CRunDll32::Execute");
  331. ASSERT(NULL != m_pszArgs);
  332. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  333. TraceMsg(TF_CPANEL, "CRunDll32: \"%s\"", m_pszArgs);
  334. CShellExecute se(L"%SystemRoot%\\system32\\rundll32.exe", m_pszArgs);
  335. HRESULT hr = se.Execute(hwndParent, punkSite);
  336. DBG_EXIT_HRES(FTF_CPANEL, "CRunDll32::Execute", hr);
  337. return THR(hr);
  338. }
  339. //--------------------------------------------------------------------------
  340. // CExecDiskUtil implementation
  341. //--------------------------------------------------------------------------
  342. CExecDiskUtil::CExecDiskUtil(
  343. eDISKUTILS eUtil,
  344. const CPL::IRestrict *pRestrict // optional. default = NULL
  345. ) : CAction(pRestrict),
  346. m_eUtil(eUtil)
  347. {
  348. ASSERT(eDISKUTIL_NUMUTILS > m_eUtil);
  349. }
  350. HRESULT
  351. CExecDiskUtil::Execute(
  352. HWND hwndParent,
  353. IUnknown *punkSite
  354. ) const
  355. {
  356. DBG_ENTER(FTF_CPANEL, "CExecDiskUtil::Execute");
  357. TCHAR szValue[MAX_PATH];
  358. DWORD dwType;
  359. DWORD cbValue = sizeof(szValue);
  360. //
  361. // These strings must remain in sync with the eDISKUTILS enumeration.
  362. //
  363. static LPCTSTR rgpszRegNames[] = {
  364. TEXT("MyComputer\\backuppath"), // eDISKUTIL_BACKUP
  365. TEXT("MyComputer\\defragpath"), // eDISKUTIL_DEFRAG
  366. TEXT("MyComputer\\cleanuppath"), // eDISKUTIL_CLEANUP
  367. };
  368. HRESULT hr = SKGetValue(SHELLKEY_HKLM_EXPLORER,
  369. rgpszRegNames[int(m_eUtil)],
  370. NULL,
  371. &dwType,
  372. szValue,
  373. &cbValue);
  374. if (SUCCEEDED(hr))
  375. {
  376. LPTSTR pszExpanded = NULL;
  377. //
  378. // Expand environment strings.
  379. // According to the code in shell32\drvx.cpp, some apps
  380. // use embedded env vars even if the value type is REG_SZ.
  381. //
  382. hr = CPL::ExpandEnvironmentVars(szValue, &pszExpanded);
  383. if (SUCCEEDED(hr))
  384. {
  385. //
  386. // The drive utility command strings were designed to be
  387. // invoked from the drives property page. They therefore
  388. // accept a drive letter. Since control panel launches
  389. // the utilities for no particular drive, we need to remove
  390. // the "%c:" format specifier.
  391. //
  392. hr = _RemoveDriveLetterFmtSpec(pszExpanded);
  393. if (SUCCEEDED(hr))
  394. {
  395. TCHAR szArgs[MAX_PATH] = {0};
  396. PathRemoveBlanks(pszExpanded);
  397. PathSeperateArgs(pszExpanded, szArgs);
  398. //
  399. // Note that it's valid to use a NULL restriction here.
  400. // If there's a restriction on the CExecDiskUtil object
  401. // we won't get this far (i.e. Execute isn't called).
  402. //
  403. CShellExecute exec(pszExpanded, szArgs);
  404. hr = exec.Execute(hwndParent, punkSite);
  405. }
  406. LocalFree(pszExpanded);
  407. }
  408. }
  409. DBG_EXIT_HRES(FTF_CPANEL, "CExecDiskUtil::Execute", hr);
  410. return THR(hr);
  411. }
  412. //
  413. // The command line strings for the backup, defrag and disk cleanup utilities
  414. // can contain a format specifier for the drive letter. That's because
  415. // they're designed to be opened from a particular volume's "Tools" property
  416. // page. Control Panel launches these from outside the context of any particular
  417. // volume. Therefore, the drive letter is not available and the the format
  418. // specifier is unused. This function removes that format specifier if it exists.
  419. //
  420. // i.e.: "c:\windows\system32\ntbackup.exe" -> "c:\windows\system32\ntbackpu.exe"
  421. // "c:\windows\system32\cleanmgr.exe /D %c:" -> "c:\windows\system32\cleanmgr.exe"
  422. // "c:\windows\system32\defrg.msc %c:" -> "c:\windows\system32\defrg.msc"
  423. //
  424. HRESULT
  425. CExecDiskUtil::_RemoveDriveLetterFmtSpec( // [static]
  426. LPTSTR pszCmdLine
  427. )
  428. {
  429. LPCTSTR pszRead = pszCmdLine;
  430. LPTSTR pszWrite = pszCmdLine;
  431. while(*pszRead)
  432. {
  433. if (TEXT('%') == *pszRead && TEXT('c') == *(pszRead + 1))
  434. {
  435. //
  436. // Skip over the "%c" or "%c:" fmt specifier.
  437. //
  438. pszRead += 2;
  439. if (TEXT(':') == *pszRead)
  440. {
  441. pszRead++;
  442. }
  443. }
  444. if (*pszRead)
  445. {
  446. *pszWrite++ = *pszRead++;
  447. }
  448. }
  449. *pszWrite = *pszRead; // pick up null terminator.
  450. return S_OK;
  451. }
  452. //--------------------------------------------------------------------------
  453. // COpenCplCategory implementation
  454. //--------------------------------------------------------------------------
  455. COpenCplCategory::COpenCplCategory(
  456. eCPCAT eCategory,
  457. const CPL::IRestrict *pRestrict // optional. default = NULL
  458. ) : CAction(pRestrict),
  459. m_eCategory(eCategory)
  460. {
  461. }
  462. HRESULT
  463. COpenCplCategory::Execute(
  464. HWND hwndParent,
  465. IUnknown *punkSite
  466. ) const
  467. {
  468. DBG_ENTER(FTF_CPANEL, "COpenCplCategory::Execute");
  469. TraceMsg(TF_CPANEL, "Category ID = %d", m_eCategory);
  470. ASSERT(NULL != punkSite);
  471. UNREFERENCED_PARAMETER(hwndParent);
  472. IShellBrowser *psb;
  473. HRESULT hr = CPL::ShellBrowserFromSite(punkSite, &psb);
  474. if (SUCCEEDED(hr))
  475. {
  476. LPITEMIDLIST pidlFolder;
  477. hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlFolder);
  478. if (SUCCEEDED(hr))
  479. {
  480. WCHAR szCategory[10];
  481. wsprintfW(szCategory, L"%d", m_eCategory);
  482. LPITEMIDLIST pidlTemp = ILAppendHiddenStringW(pidlFolder, IDLHID_NAVIGATEMARKER, szCategory);
  483. if (NULL == pidlTemp)
  484. {
  485. hr = E_OUTOFMEMORY;
  486. }
  487. else
  488. {
  489. pidlFolder = pidlTemp;
  490. pidlTemp = NULL;
  491. hr = CPL::BrowseIDListInPlace(pidlFolder, psb);
  492. }
  493. ILFree(pidlFolder);
  494. }
  495. psb->Release();
  496. }
  497. DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory::Execute", hr);
  498. return THR(hr);
  499. }
  500. //--------------------------------------------------------------------------
  501. // COpenCplCategory2 implementation
  502. //--------------------------------------------------------------------------
  503. COpenCplCategory2::COpenCplCategory2(
  504. eCPCAT eCategory,
  505. const IAction *pDefAction,
  506. const CPL::IRestrict *pRestrict // optional. default = NULL
  507. ) : CAction(pRestrict),
  508. m_eCategory(eCategory),
  509. m_pDefAction(pDefAction)
  510. {
  511. }
  512. HRESULT
  513. COpenCplCategory2::Execute(
  514. HWND hwndParent,
  515. IUnknown *punkSite
  516. ) const
  517. {
  518. DBG_ENTER(FTF_CPANEL, "COpenCplCategory2::Execute");
  519. TraceMsg(TF_CPANEL, "Category ID = %d", m_eCategory);
  520. ASSERT(NULL != punkSite);
  521. bool bOpenCategory = false;
  522. HRESULT hr = _ExecuteActionOnSingleCplApplet(hwndParent, punkSite, &bOpenCategory);
  523. if (SUCCEEDED(hr))
  524. {
  525. if (bOpenCategory)
  526. {
  527. //
  528. // Category has more than one CPL.
  529. // Open the category page.
  530. //
  531. COpenCplCategory action(m_eCategory);
  532. hr = action.Execute(hwndParent, punkSite);
  533. }
  534. }
  535. DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory2::Execute", hr);
  536. return THR(hr);
  537. }
  538. HRESULT
  539. COpenCplCategory2::_ExecuteActionOnSingleCplApplet(
  540. HWND hwndParent,
  541. IUnknown *punkSite,
  542. bool *pbOpenCategory // optional. Can be NULL
  543. ) const
  544. {
  545. DBG_ENTER(FTF_CPANEL, "COpenCplCategory2::_ExecuteActionOnSingleCplApplet");
  546. bool bOpenCategory = true;
  547. ICplView *pview;
  548. HRESULT hr = CPL::ControlPanelViewFromSite(punkSite, &pview);
  549. if (SUCCEEDED(hr))
  550. {
  551. IServiceProvider *psp;
  552. hr = pview->QueryInterface(IID_IServiceProvider, (void **)&psp);
  553. if (SUCCEEDED(hr))
  554. {
  555. ICplNamespace *pns;
  556. hr = psp->QueryService(SID_SControlPanelView, IID_ICplNamespace, (void **)&pns);
  557. if (SUCCEEDED(hr))
  558. {
  559. ICplCategory *pCategory;
  560. hr = pns->GetCategory(m_eCategory, &pCategory);
  561. if (SUCCEEDED(hr))
  562. {
  563. IEnumUICommand *penum;
  564. hr = pCategory->EnumCplApplets(&penum);
  565. if (SUCCEEDED(hr))
  566. {
  567. //
  568. // See if the category has more than one CPL applet
  569. // assigned to it.
  570. //
  571. ULONG cApplets = 0;
  572. IUICommand *rgpuic[2] = {0};
  573. if (SUCCEEDED(hr = penum->Next(ARRAYSIZE(rgpuic), rgpuic, &cApplets)))
  574. {
  575. for (int i = 0; i < ARRAYSIZE(rgpuic); i++)
  576. {
  577. ATOMICRELEASE(rgpuic[i]);
  578. }
  579. if (2 > cApplets)
  580. {
  581. //
  582. // There's zero or one CPLs registered for this category.
  583. // Simply execute the default action. If there's one
  584. // we assume it's the "default" applet (i.e. ARP or
  585. // User Accounts).
  586. //
  587. hr = m_pDefAction->IsRestricted(pns);
  588. if (SUCCEEDED(hr))
  589. {
  590. if (S_FALSE == hr)
  591. {
  592. bOpenCategory = false;
  593. hr = m_pDefAction->Execute(hwndParent, punkSite);
  594. }
  595. else
  596. {
  597. //
  598. // Default action is restricted.
  599. // Open the category page. Note that the
  600. // category page may be displayed as a 'barrier'
  601. // if no tasks or CPL applets are available.
  602. //
  603. ASSERT(bOpenCategory);
  604. }
  605. }
  606. }
  607. }
  608. penum->Release();
  609. }
  610. pCategory->Release();
  611. }
  612. pns->Release();
  613. }
  614. psp->Release();
  615. }
  616. pview->Release();
  617. }
  618. if (NULL != pbOpenCategory)
  619. {
  620. *pbOpenCategory = bOpenCategory;
  621. }
  622. DBG_EXIT_HRES(FTF_CPANEL, "COpenCplCategory2::_ExecuteActionOnSingleCplApplet", hr);
  623. return THR(hr);
  624. }
  625. //--------------------------------------------------------------------------
  626. // COpenCplView implementation
  627. //--------------------------------------------------------------------------
  628. COpenCplView::COpenCplView(
  629. eCPVIEWTYPE eViewType,
  630. const CPL::IRestrict *pRestrict // optional. default = NULL
  631. ) : CAction(pRestrict),
  632. m_eViewType(eViewType)
  633. {
  634. }
  635. HRESULT
  636. COpenCplView::Execute(
  637. HWND hwndParent,
  638. IUnknown *punkSite
  639. ) const
  640. {
  641. UNREFERENCED_PARAMETER(hwndParent);
  642. ASSERT(NULL != punkSite);
  643. HRESULT hr = _SetFolderBarricadeStatus();
  644. if (SUCCEEDED(hr))
  645. {
  646. IShellBrowser *psb;
  647. hr = CPL::ShellBrowserFromSite(punkSite, &psb);
  648. if (SUCCEEDED(hr))
  649. {
  650. LPITEMIDLIST pidlFolder;
  651. hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlFolder);
  652. if (SUCCEEDED(hr))
  653. {
  654. hr = CPL::BrowseIDListInPlace(pidlFolder, psb);
  655. ILFree(pidlFolder);
  656. }
  657. psb->Release();
  658. }
  659. }
  660. return THR(hr);
  661. }
  662. HRESULT
  663. COpenCplView::_SetFolderBarricadeStatus(
  664. void
  665. ) const
  666. {
  667. VARIANT_BOOL vtb = VARIANT_FALSE;
  668. if (eCPVIEWTYPE_CATEGORY == m_eViewType)
  669. {
  670. vtb = VARIANT_TRUE;
  671. }
  672. else
  673. {
  674. ASSERT(eCPVIEWTYPE_CLASSIC == m_eViewType);
  675. }
  676. HRESULT hr = CPL::SetControlPanelBarricadeStatus(vtb);
  677. return THR(hr);
  678. }
  679. //--------------------------------------------------------------------------
  680. // CAddPrinter implementation
  681. //--------------------------------------------------------------------------
  682. CAddPrinter::CAddPrinter(
  683. const CPL::IRestrict *pRestrict // optional. default = NULL
  684. ) : CAction(pRestrict)
  685. {
  686. }
  687. HRESULT
  688. CAddPrinter::Execute(
  689. HWND hwndParent,
  690. IUnknown *punkSite
  691. ) const
  692. {
  693. DBG_ENTER(FTF_CPANEL, "CAddPrinter::Execute");
  694. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  695. UNREFERENCED_PARAMETER(punkSite);
  696. HRESULT hr = E_FAIL;
  697. if (SHInvokePrinterCommandW(hwndParent,
  698. PRINTACTION_OPEN,
  699. L"WinUtils_NewObject",
  700. NULL,
  701. FALSE))
  702. {
  703. //
  704. // Navigate to the printers folder after invoking the add-printer wizard.
  705. // This gives the user visual feedback when a printer is added. We navigate
  706. // even if the user cancels the wizard because we cannot determine if the
  707. // wizard was cancelled. We've determined this is acceptable.
  708. //
  709. CNavigateURL prnfldr(L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}");
  710. hr = prnfldr.Execute(hwndParent, punkSite);
  711. }
  712. DBG_EXIT_HRES(FTF_CPANEL, "CAddPrinter::Execute", hr);
  713. return THR(hr);
  714. }
  715. //--------------------------------------------------------------------------
  716. // CTrayCommand implementation
  717. //--------------------------------------------------------------------------
  718. CTrayCommand::CTrayCommand(
  719. UINT idm,
  720. const CPL::IRestrict *pRestrict // optional. default = NULL
  721. ) : CAction(pRestrict),
  722. m_idm(idm)
  723. {
  724. }
  725. HRESULT
  726. CTrayCommand::Execute(
  727. HWND hwndParent,
  728. IUnknown *punkSite
  729. ) const
  730. {
  731. UNREFERENCED_PARAMETER(hwndParent);
  732. UNREFERENCED_PARAMETER(punkSite);
  733. // APPHACK! 221008 DesktopX creates their own window with class
  734. // name "Shell_TrayWnd", so if we're not careful we will end
  735. // posting the messages to the wrong window. They create their
  736. // window with the title "CTrayServer"; ours has a null title.
  737. // Use the null title to find the correct window.
  738. HWND hwndTray = FindWindowA(WNDCLASS_TRAYNOTIFY, "");
  739. if (hwndTray)
  740. {
  741. PostMessage(hwndTray, WM_COMMAND, m_idm, 0);
  742. }
  743. return S_OK;
  744. }
  745. //--------------------------------------------------------------------------
  746. // CActionNYI implementation
  747. //--------------------------------------------------------------------------
  748. CActionNYI::CActionNYI(
  749. LPCWSTR pszText
  750. ) : m_pszText(pszText)
  751. {
  752. }
  753. HRESULT
  754. CActionNYI::Execute(
  755. HWND hwndParent,
  756. IUnknown *punkSite
  757. ) const
  758. {
  759. ASSERT(NULL == hwndParent || IsWindow(hwndParent));
  760. UNREFERENCED_PARAMETER(punkSite);
  761. HRESULT hr = E_OUTOFMEMORY;
  762. if (NULL != m_pszText)
  763. {
  764. MessageBoxW(hwndParent, m_pszText, L"Action Not Yet Implemented", MB_OK);
  765. hr = S_OK;
  766. }
  767. return THR(hr);
  768. }
  769. #pragma warning( pop )