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.

955 lines
26 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: ShellExtensions.cpp
  7. //
  8. // Contents: object to implement propertypage extensions
  9. // for Win2k shim layer
  10. //
  11. // History: 23-september-00 clupu Created
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "stdafx.h"
  16. #include "resource.h"
  17. #include "xpsp1res.h"
  18. #include "ShellExtensions.h"
  19. #include <sfc.h>
  20. UINT g_DllRefCount = 0;
  21. extern HINSTANCE g_hInstance;
  22. typedef struct _LAYER_INFO {
  23. WCHAR wszInternalName[32];
  24. UINT nstrFriendlyName;
  25. } LAYER_INFO, *PLAYER_INFO;
  26. //
  27. // internal definitions of layer names
  28. //
  29. #define STR_LAYER_WIN95 L"WIN95"
  30. #define STR_LAYER_WIN98 L"WIN98"
  31. #define STR_LAYER_WINNT L"NT4SP5"
  32. #define STR_LAYER_WIN2K L"WIN2000"
  33. #define STR_LAYER_256COLOR L"256COLOR"
  34. #define STR_LAYER_LORES L"640X480"
  35. #define STR_LAYER_DISABLETHEMES L"DISABLETHEMES"
  36. #define STR_LAYER_DISABLECICERO L"DISABLECICERO"
  37. const LAYER_INFO g_LayerInfo[] =
  38. {
  39. {
  40. STR_LAYER_WIN95,
  41. IDS_LAYER_WIN95_EXT
  42. },
  43. {
  44. STR_LAYER_WIN98,
  45. IDS_LAYER_WIN98_EXT,
  46. },
  47. {
  48. STR_LAYER_WINNT,
  49. IDS_LAYER_NT4_EXT
  50. },
  51. {
  52. STR_LAYER_WIN2K,
  53. IDS_LAYER_WIN2K_EXT
  54. }
  55. };
  56. #define NUM_LAYERS (sizeof(g_LayerInfo)/sizeof(g_LayerInfo[0]))
  57. typedef BOOL (STDAPICALLTYPE *_pfn_AllowPermLayer)(WCHAR* pwszPath);
  58. typedef BOOL (STDAPICALLTYPE *_pfn_GetPermLayers)(WCHAR* pwszPath, WCHAR *pwszLayers, DWORD *pdwBytes, DWORD dwFlags);
  59. typedef BOOL (STDAPICALLTYPE *_pfn_SetPermLayers)(WCHAR* pwszPath, WCHAR *pwszLayers, BOOL bMachine);
  60. HINSTANCE g_hAppHelp = NULL;
  61. HINSTANCE g_hQfeRes = NULL;
  62. _pfn_AllowPermLayer g_pfnAllowPermLayer = NULL;
  63. _pfn_GetPermLayers g_pfnGetPermLayers = NULL;
  64. _pfn_SetPermLayers g_pfnSetPermLayers = NULL;
  65. BOOL InitAppHelpCalls(void)
  66. {
  67. HINSTANCE hAppHelp;
  68. if (g_hAppHelp) {
  69. //
  70. // we're already inited
  71. //
  72. return TRUE;
  73. }
  74. hAppHelp = LoadLibrary(TEXT("apphelp.dll"));
  75. if (!hAppHelp) {
  76. LogMsg(_T("[InitAppHelpCalls] Can't get handle to apphelp.dll.\n"));
  77. return FALSE;
  78. }
  79. g_pfnAllowPermLayer = (_pfn_AllowPermLayer)GetProcAddress(hAppHelp, "AllowPermLayer");
  80. g_pfnGetPermLayers = (_pfn_GetPermLayers)GetProcAddress(hAppHelp, "GetPermLayers");
  81. g_pfnSetPermLayers = (_pfn_SetPermLayers)GetProcAddress(hAppHelp, "SetPermLayers");
  82. if (!g_pfnAllowPermLayer || !g_pfnGetPermLayers || !g_pfnSetPermLayers) {
  83. LogMsg(_T("[InitAppHelpCalls] Can't get function pointers.\n"));
  84. return FALSE;
  85. }
  86. //
  87. // this needs to be here at the end to avoid a race condition
  88. //
  89. g_hAppHelp = hAppHelp;
  90. return TRUE;
  91. }
  92. //////////////////////////////////////////////////////////////////////////
  93. // SetLayerInfo
  94. //
  95. BOOL
  96. SetLayerInfo(
  97. TCHAR* szPath,
  98. int nMainLayer,
  99. BOOL b256,
  100. BOOL b640,
  101. BOOL bDisableThemes,
  102. BOOL bDisableCicero)
  103. {
  104. WCHAR wszLayers[256];
  105. //
  106. // build layer string
  107. //
  108. wszLayers[0] = 0;
  109. if (nMainLayer >= 0 && nMainLayer < NUM_LAYERS) {
  110. wcscat(wszLayers, g_LayerInfo[nMainLayer].wszInternalName);
  111. }
  112. if (b256) {
  113. if (wszLayers[0]) {
  114. wcscat(wszLayers, L" ");
  115. }
  116. wcscat(wszLayers, STR_LAYER_256COLOR);
  117. }
  118. if (b640) {
  119. if (wszLayers[0]) {
  120. wcscat(wszLayers, L" ");
  121. }
  122. wcscat(wszLayers, STR_LAYER_LORES);
  123. }
  124. if (bDisableThemes) {
  125. if (wszLayers[0]) {
  126. wcscat(wszLayers, L" ");
  127. }
  128. wcscat(wszLayers, STR_LAYER_DISABLETHEMES);
  129. }
  130. if (bDisableCicero) {
  131. if (wszLayers[0]) {
  132. wcscat(wszLayers, L" ");
  133. }
  134. wcscat(wszLayers, STR_LAYER_DISABLECICERO);
  135. }
  136. //
  137. // set it
  138. //
  139. return g_pfnSetPermLayers(szPath, wszLayers, FALSE);
  140. }
  141. //////////////////////////////////////////////////////////////////////////
  142. // GetLayerInfo
  143. //
  144. BOOL
  145. GetLayerInfo(
  146. TCHAR* szPath,
  147. int* pnMainLayer,
  148. BOOL* pb256,
  149. BOOL* pb640,
  150. BOOL* pbDisableThemes,
  151. BOOL* pbDisableCicero)
  152. {
  153. WCHAR wszLayers[256];
  154. DWORD dwBytes = sizeof(wszLayers);
  155. int i;
  156. if (!pnMainLayer || !pb256 || !pb640 || !pbDisableThemes || !pbDisableCicero) {
  157. LogMsg(_T("[GetLayerInfo] NULL param passed in\n"));
  158. return FALSE;
  159. }
  160. //
  161. // get layer string
  162. //
  163. if (!g_pfnGetPermLayers(szPath, wszLayers, &dwBytes, GPLK_ALL)) {
  164. *pnMainLayer = -1;
  165. *pb256 = FALSE;
  166. *pb640 = FALSE;
  167. *pbDisableThemes = FALSE;
  168. *pbDisableCicero = FALSE;
  169. return TRUE;
  170. }
  171. LogMsg(_T("[GetLayerInfo] Layers \"%s\"\n"), wszLayers);
  172. //
  173. // Make the layer string upper case, so we'll match case-insensitive
  174. //
  175. _wcsupr(wszLayers);
  176. //
  177. // find the first layer that matches
  178. //
  179. *pnMainLayer = -1;
  180. for (i = 0; i < NUM_LAYERS; ++i) {
  181. if (wcsstr(wszLayers, g_LayerInfo[i].wszInternalName) != NULL) {
  182. *pnMainLayer = i;
  183. }
  184. }
  185. if (wcsstr(wszLayers, STR_LAYER_256COLOR) != NULL) {
  186. *pb256 = TRUE;
  187. } else {
  188. *pb256 = FALSE;
  189. }
  190. if (wcsstr(wszLayers, STR_LAYER_LORES) != NULL) {
  191. *pb640 = TRUE;
  192. } else {
  193. *pb640 = FALSE;
  194. }
  195. if (wcsstr(wszLayers, STR_LAYER_DISABLETHEMES) != NULL) {
  196. *pbDisableThemes = TRUE;
  197. LogMsg(_T("[GetLayerInfo] Themes disabled\n"));
  198. } else {
  199. *pbDisableThemes = FALSE;
  200. LogMsg(_T("[GetLayerInfo] Themes enabled\n"));
  201. }
  202. if (wcsstr(wszLayers, STR_LAYER_DISABLECICERO) != NULL) {
  203. *pbDisableCicero = TRUE;
  204. LogMsg(_T("[GetLayerInfo] Cicero disabled\n"));
  205. } else {
  206. *pbDisableCicero = FALSE;
  207. LogMsg(_T("[GetLayerInfo] Cicero enabled\n"));
  208. }
  209. return TRUE;
  210. }
  211. void
  212. NotifyDataChanged(HWND hDlg)
  213. {
  214. HWND hParent;
  215. if (!hDlg) {
  216. LogMsg(_T("[NotifyDataChanged] NULL handle passed in\n"));
  217. return;
  218. }
  219. hParent = GetParent(hDlg);
  220. if (!hParent) {
  221. LogMsg(_T("[NotifyDataChanged] Can't get get prop sheet parent\n"));
  222. return;
  223. }
  224. PropSheet_Changed(hParent, hDlg);
  225. }
  226. BOOL
  227. SearchGroupForSID(
  228. DWORD dwGroup,
  229. BOOL* pfIsMember
  230. )
  231. {
  232. PSID pSID;
  233. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  234. BOOL fRes = TRUE;
  235. if (!AllocateAndInitializeSid(&SIDAuth,
  236. 2,
  237. SECURITY_BUILTIN_DOMAIN_RID,
  238. dwGroup,
  239. 0,
  240. 0,
  241. 0,
  242. 0,
  243. 0,
  244. 0,
  245. &pSID)) {
  246. LogMsg(_T("[SearchGroupForSID] AllocateAndInitializeSid failed 0x%x\n"), GetLastError());
  247. fRes = FALSE;
  248. }
  249. if (!CheckTokenMembership(NULL, pSID, pfIsMember)) {
  250. LogMsg(_T("[SearchGroupForSID] CheckTokenMembership failed 0x%x\n"), GetLastError());
  251. fRes = FALSE;
  252. }
  253. FreeSid(pSID);
  254. return fRes;
  255. }
  256. //////////////////////////////////////////////////////////////////////////
  257. // LayerPageDlgProc
  258. //
  259. // The dialog proc for the layer property page.
  260. INT_PTR CALLBACK
  261. LayerPageDlgProc(
  262. HWND hdlg,
  263. UINT uMsg,
  264. WPARAM wParam,
  265. LPARAM lParam)
  266. {
  267. int wCode = LOWORD(wParam);
  268. int wNotifyCode = HIWORD(wParam);
  269. int nLayer = -1;
  270. BOOL b256 = FALSE;
  271. BOOL b640 = FALSE;
  272. BOOL bDTh = FALSE;
  273. BOOL bDCicero = FALSE;
  274. switch (uMsg) {
  275. case WM_INITDIALOG:
  276. {
  277. PROPSHEETPAGE* ppsp = (PROPSHEETPAGE*)lParam;
  278. DWORD dwFlags = 0;
  279. CLayerUIPropPage* pPropPage = (CLayerUIPropPage*)ppsp->lParam;
  280. BOOL bSystemBinary;
  281. int i;
  282. LogMsg(_T("[LayerPageDlgProc] WM_INITDIALOG - item \"%s\"\n"),
  283. pPropPage->m_szFile);
  284. //
  285. // Store the name of the EXE/LNK in the dialog.
  286. //
  287. SetWindowLongPtr(hdlg, GWLP_USERDATA, (LONG_PTR)pPropPage->m_szFile);
  288. //
  289. // Add the names of the layers.
  290. //
  291. for (i = 0; i < NUM_LAYERS; ++i) {
  292. TCHAR szFriendlyName[100];
  293. if (LoadString(g_hInstance, g_LayerInfo[i].nstrFriendlyName, szFriendlyName, 100)) {
  294. SendDlgItemMessage(hdlg,
  295. IDC_LAYER_NAME,
  296. CB_ADDSTRING,
  297. 0,
  298. (LPARAM)szFriendlyName);
  299. }
  300. }
  301. //
  302. // Check if the EXE is SFPed.
  303. //
  304. bSystemBinary = SfcIsFileProtected(0, pPropPage->m_szFile);
  305. //
  306. // Check to see if we can change layers on this file
  307. //
  308. if (!g_pfnAllowPermLayer(pPropPage->m_szFile) || bSystemBinary) {
  309. TCHAR szTemp[256] = _T("");
  310. SendDlgItemMessage(hdlg, IDC_LAYER_NAME, CB_SETCURSEL, 0, 0);
  311. EnableWindow(GetDlgItem(hdlg, IDC_USE_LAYER), FALSE);
  312. EnableWindow(GetDlgItem(hdlg, IDC_256COLORS), FALSE);
  313. EnableWindow(GetDlgItem(hdlg, IDC_640X480), FALSE);
  314. EnableWindow(GetDlgItem(hdlg, IDC_ENABLE_THEMES), FALSE);
  315. EnableWindow(GetDlgItem(hdlg, IDC_DISABLECICERO), FALSE);
  316. //
  317. // Change the text on the static object
  318. //
  319. if (bSystemBinary) {
  320. LoadString(g_hInstance, IDS_COMPAT_UNAVAILABLE_SYSTEM, szTemp, 256);
  321. } else {
  322. LoadString(g_hInstance, IDS_COMPAT_UNAVAILABLE, szTemp, 256);
  323. }
  324. SendDlgItemMessage(hdlg, IDC_TEXT_INSTRUCTIONS, WM_SETTEXT, 0, (LPARAM)szTemp);
  325. } else {
  326. //
  327. // Read the layer storage for info on this item.
  328. //
  329. GetLayerInfo(pPropPage->m_szFile, &nLayer, &b256, &b640, &bDTh, &bDCicero);
  330. //
  331. // Select the appropriate layer for this item. If no info
  332. // is available in the layer store, default to the Win9x layer.
  333. //
  334. if (nLayer != -1) {
  335. SendDlgItemMessage(hdlg, IDC_LAYER_NAME, CB_SETCURSEL, nLayer, 0);
  336. EnableWindow(GetDlgItem(hdlg, IDC_LAYER_NAME), TRUE);
  337. SendDlgItemMessage(hdlg, IDC_USE_LAYER, BM_SETCHECK, BST_CHECKED, 0);
  338. } else {
  339. SendDlgItemMessage(hdlg, IDC_LAYER_NAME, CB_SETCURSEL, 0, 0);
  340. EnableWindow(GetDlgItem(hdlg, IDC_LAYER_NAME), FALSE);
  341. SendDlgItemMessage(hdlg, IDC_USE_LAYER, BM_SETCHECK, BST_UNCHECKED, 0);
  342. }
  343. if (b256) {
  344. SendDlgItemMessage(hdlg, IDC_256COLORS, BM_SETCHECK, BST_CHECKED, 0);
  345. }
  346. if (b640) {
  347. SendDlgItemMessage(hdlg, IDC_640X480, BM_SETCHECK, BST_CHECKED, 0);
  348. }
  349. if (bDTh) {
  350. SendDlgItemMessage(hdlg, IDC_ENABLE_THEMES, BM_SETCHECK, BST_CHECKED, 0);
  351. }
  352. if (bDCicero) {
  353. SendDlgItemMessage(hdlg, IDC_DISABLECICERO, BM_SETCHECK, BST_CHECKED, 0);
  354. }
  355. }
  356. break;
  357. }
  358. case WM_HELP:
  359. {
  360. LPHELPINFO lphi;
  361. lphi = (LPHELPINFO)lParam;
  362. if (lphi->iContextType == HELPINFO_WINDOW) {
  363. WinHelp((HWND)lphi->hItemHandle,
  364. L"Windows.hlp",
  365. HELP_CONTEXTPOPUP,
  366. (DWORD)lphi->iCtrlId);
  367. MessageBeep(0);
  368. }
  369. break;;
  370. }
  371. case WM_COMMAND:
  372. {
  373. switch (wNotifyCode) {
  374. case CBN_SELCHANGE:
  375. NotifyDataChanged(hdlg);
  376. return TRUE;
  377. }
  378. switch (wCode) {
  379. case IDC_256COLORS:
  380. case IDC_640X480:
  381. case IDC_ENABLE_THEMES:
  382. case IDC_DISABLECICERO:
  383. NotifyDataChanged(hdlg);
  384. break;
  385. case IDC_USE_LAYER:
  386. if (SendDlgItemMessage(hdlg, IDC_USE_LAYER, BM_GETCHECK, 0, 0) == BST_CHECKED) {
  387. EnableWindow(GetDlgItem(hdlg, IDC_LAYER_NAME), TRUE);
  388. } else {
  389. EnableWindow(GetDlgItem(hdlg, IDC_LAYER_NAME), FALSE);
  390. }
  391. NotifyDataChanged(hdlg);
  392. break;
  393. default:
  394. return FALSE;
  395. }
  396. break;
  397. }
  398. case WM_NOTIFY:
  399. {
  400. NMHDR *pHdr = (NMHDR*)lParam;
  401. switch (pHdr->code) {
  402. case NM_CLICK:
  403. case NM_RETURN:
  404. {
  405. if ((int)wParam != IDC_LEARN) {
  406. break;
  407. }
  408. SHELLEXECUTEINFO sei = { 0 };
  409. sei.cbSize = sizeof(SHELLEXECUTEINFO);
  410. sei.fMask = SEE_MASK_DOENVSUBST;
  411. sei.hwnd = hdlg;
  412. sei.nShow = SW_SHOWNORMAL;
  413. sei.lpFile = _T("hcp://services/subsite?node=TopLevelBucket_4/")
  414. _T("Fixing_a_problem&topic=MS-ITS%3A%25HELP_LOCATION")
  415. _T("%25%5Cmisc.chm%3A%3A/compatibility_tab_and_wizard.htm")
  416. _T("&select=TopLevelBucket_4/Fixing_a_problem/")
  417. _T("Application_and_software_problems");
  418. ShellExecuteEx(&sei);
  419. break;
  420. }
  421. case PSN_APPLY:
  422. {
  423. TCHAR *szFile;
  424. szFile = (TCHAR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
  425. if (szFile) {
  426. if (SendDlgItemMessage(hdlg, IDC_USE_LAYER, BM_GETCHECK, 0, 0) == BST_CHECKED) {
  427. LRESULT retval;
  428. retval = SendDlgItemMessage(hdlg, IDC_LAYER_NAME, CB_GETCURSEL, 0, 0);
  429. if (retval == CB_ERR) {
  430. LogMsg(_T("[LayerPageDlgProc] Can't get combobox selection\n"));
  431. nLayer = -1;
  432. } else {
  433. nLayer = (int)retval;
  434. }
  435. } else {
  436. nLayer = -1;
  437. }
  438. b256 = SendDlgItemMessage(hdlg, IDC_256COLORS, BM_GETCHECK, 0, 0) == BST_CHECKED;
  439. b640 = SendDlgItemMessage(hdlg, IDC_640X480, BM_GETCHECK, 0, 0) == BST_CHECKED;
  440. bDTh = SendDlgItemMessage(hdlg, IDC_ENABLE_THEMES, BM_GETCHECK, 0, 0) == BST_CHECKED;
  441. bDCicero = SendDlgItemMessage(hdlg, IDC_DISABLECICERO, BM_GETCHECK, 0, 0) == BST_CHECKED;
  442. SetLayerInfo(szFile, nLayer, b256, b640, bDTh, bDCicero);
  443. } else {
  444. LogMsg(_T("[LayerPageDlgProc] Can't get file name from WindowLong\n"));
  445. }
  446. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  447. break;
  448. }
  449. }
  450. return TRUE;
  451. }
  452. default:
  453. return FALSE;
  454. }
  455. return TRUE;
  456. }
  457. //////////////////////////////////////////////////////////////////////////
  458. // LayerPageCallbackProc
  459. //
  460. // The callback for the property page.
  461. UINT CALLBACK
  462. LayerPageCallbackProc(
  463. HWND hwnd,
  464. UINT uMsg,
  465. LPPROPSHEETPAGE ppsp
  466. )
  467. {
  468. switch (uMsg) {
  469. case PSPCB_RELEASE:
  470. if (ppsp->lParam != 0) {
  471. CLayerUIPropPage* pPropPage = (CLayerUIPropPage*)(ppsp->lParam);
  472. LogMsg(_T("[LayerPageCallbackProc] releasing CLayerUIPropPage\n"));
  473. pPropPage->Release();
  474. }
  475. if (g_hQfeRes) {
  476. FreeLibrary(g_hQfeRes);
  477. g_hQfeRes = NULL;
  478. }
  479. break;
  480. }
  481. return 1;
  482. }
  483. BOOL
  484. GetExeFromLnk(
  485. TCHAR* pszLnk,
  486. TCHAR* pszExe,
  487. int cchSize
  488. )
  489. {
  490. HRESULT hres;
  491. IShellLink* psl = NULL;
  492. IPersistFile* pPf = NULL;
  493. TCHAR szArg[MAX_PATH];
  494. BOOL bSuccess = FALSE;
  495. IShellLinkDataList* psldl;
  496. EXP_DARWIN_LINK* pexpDarwin;
  497. hres = CoCreateInstance(CLSID_ShellLink,
  498. NULL,
  499. CLSCTX_INPROC_SERVER,
  500. IID_IShellLink,
  501. (LPVOID*)&psl);
  502. if (FAILED(hres)) {
  503. LogMsg(_T("[GetExeFromLnk] CoCreateInstance failed\n"));
  504. return FALSE;
  505. }
  506. hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&pPf);
  507. if (FAILED(hres)) {
  508. LogMsg(_T("[GetExeFromLnk] QueryInterface for IPersistFile failed\n"));
  509. goto cleanup;
  510. }
  511. //
  512. // Load the link file.
  513. //
  514. hres = pPf->Load(pszLnk, STGM_READ);
  515. if (FAILED(hres)) {
  516. LogMsg(_T("[GetExeFromLnk] failed to load link \"%s\"\n"),
  517. pszLnk);
  518. goto cleanup;
  519. }
  520. //
  521. // See if this is a DARWIN link.
  522. //
  523. hres = psl->QueryInterface(IID_IShellLinkDataList, (LPVOID*)&psldl);
  524. if (FAILED(hres)) {
  525. LogMsg(_T("[GetExeFromLnk] failed to get IShellLinkDataList.\n"));
  526. } else {
  527. hres = psldl->CopyDataBlock(EXP_DARWIN_ID_SIG, (void**)&pexpDarwin);
  528. if (SUCCEEDED(hres)) {
  529. LogMsg(_T("[GetExeFromLnk] this is a DARWIN link \"%s\".\n"),
  530. pszLnk);
  531. goto cleanup;
  532. }
  533. }
  534. //
  535. // Resolve the link.
  536. //
  537. hres = psl->Resolve(NULL,
  538. SLR_NOTRACK | SLR_NOSEARCH | SLR_NO_UI | SLR_NOUPDATE);
  539. if (FAILED(hres)) {
  540. LogMsg(_T("[GetExeFromLnk] failed to resolve the link \"%s\"\n"),
  541. pszLnk);
  542. goto cleanup;
  543. }
  544. pszExe[0] = 0;
  545. //
  546. // Get the path to the link target.
  547. //
  548. hres = psl->GetPath(pszExe,
  549. cchSize,
  550. NULL,
  551. SLGP_UNCPRIORITY);
  552. if (FAILED(hres)) {
  553. LogMsg(_T("[GetExeFromLnk] failed to get the path for link \"%s\"\n"),
  554. pszLnk);
  555. goto cleanup;
  556. }
  557. bSuccess = TRUE;
  558. cleanup:
  559. if (pPf != NULL) {
  560. pPf->Release();
  561. }
  562. psl->Release();
  563. return bSuccess;
  564. }
  565. //////////////////////////////////////////////////////////////////////////
  566. // CLayerUIPropPage
  567. CLayerUIPropPage::CLayerUIPropPage()
  568. {
  569. LogMsg(_T("[CLayerUIPropPage::CLayerUIPropPage]\n"));
  570. }
  571. CLayerUIPropPage::~CLayerUIPropPage()
  572. {
  573. LogMsg(_T("[CLayerUIPropPage::~CLayerUIPropPage]\n"));
  574. }
  575. //////////////////////////////////////////////////////////////////////////
  576. //
  577. // Function: ValidateExecutableFile
  578. //
  579. // This function exists also in compatUI.dll for the purpose of validating
  580. // the file as being acceptable for compatibility handling. It looks at the
  581. // file extension to determine whether a given file is "acceptable"
  582. //
  583. BOOL
  584. ValidateExecutableFile(
  585. LPCTSTR pszPath,
  586. BOOL bValidateFileExists,
  587. BOOL* pbIsLink
  588. )
  589. {
  590. LPTSTR rgExt[] = { // this list should be sorted
  591. _T("BAT"),
  592. _T("CMD"),
  593. _T("COM"),
  594. _T("EXE"),
  595. _T("LNK"),
  596. _T("PIF")
  597. };
  598. LPTSTR pExt;
  599. TCHAR szLnk[] = _T("LNK");
  600. int i;
  601. int iCmp = 1;
  602. pExt = PathFindExtension(pszPath);
  603. if (pExt == NULL || *pExt == TEXT('\0')) {
  604. return FALSE;
  605. }
  606. ++pExt; // move past '.'
  607. for (i = 0; i < sizeof(rgExt)/sizeof(rgExt[0]) && iCmp > 0; ++i) {
  608. iCmp = _tcsicmp(pExt, rgExt[i]);
  609. }
  610. if (iCmp) {
  611. return FALSE;
  612. }
  613. if (pbIsLink) {
  614. *pbIsLink = !_tcsicmp(pExt, szLnk);
  615. }
  616. return bValidateFileExists ? PathFileExists(pszPath) : TRUE;
  617. }
  618. //////////////////////////////////////////////////////////////////////////
  619. // IShellExtInit methods
  620. STDMETHODIMP
  621. CLayerUIPropPage::Initialize(
  622. LPCITEMIDLIST pIDFolder,
  623. LPDATAOBJECT pDataObj,
  624. HKEY hKeyID
  625. )
  626. {
  627. LogMsg(_T("[CLayerUIPropPage::Initialize]\n"));
  628. if (pDataObj == NULL) {
  629. LogMsg(_T("\t failed. bad argument.\n"));
  630. return E_INVALIDARG;
  631. }
  632. //
  633. // init the apphelp calls
  634. //
  635. if (!InitAppHelpCalls()) {
  636. LogMsg(_T("\t failed. couldn't init apphelp calls.\n"));
  637. return E_FAIL;
  638. }
  639. //
  640. // Store a pointer to the data object
  641. //
  642. m_spDataObj = pDataObj;
  643. //
  644. // If a data object pointer was passed in, save it and
  645. // extract the file name.
  646. //
  647. STGMEDIUM medium;
  648. UINT uCount;
  649. FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1,
  650. TYMED_HGLOBAL};
  651. if (SUCCEEDED(m_spDataObj->GetData(&fe, &medium))) {
  652. //
  653. // Get the file name from the CF_HDROP.
  654. //
  655. uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1,
  656. NULL, 0);
  657. if (uCount > 0) {
  658. TCHAR szExe[MAX_PATH];
  659. BOOL bIsLink = FALSE;
  660. DragQueryFile((HDROP)medium.hGlobal, 0, szExe,
  661. sizeof(szExe) / sizeof(TCHAR));
  662. LogMsg(_T("\tProp page for: \"%s\".\n"), szExe);
  663. m_szFile[0] = 0;
  664. if (ValidateExecutableFile(szExe, TRUE, &bIsLink)) {
  665. if (bIsLink) {
  666. //
  667. // the file is a link indeed, get the contents
  668. //
  669. if (!GetExeFromLnk(szExe, m_szFile, MAX_PATH)) {
  670. //
  671. // can't get exe from the link, m_szFile[0] == 0
  672. //
  673. LogMsg(_T("Couldn't convert \"%s\" to EXE.\n"), m_szFile);
  674. } else {
  675. LogMsg(_T("\tLNK points to: \"%s\".\n"), m_szFile);
  676. //
  677. // check to see if it's a shortcut to an EXE file
  678. //
  679. if (!ValidateExecutableFile(m_szFile, FALSE, NULL)) {
  680. //
  681. // shortcut points to a file of the unsupported type, reset the name
  682. //
  683. LogMsg(_T("\tNot an EXE file. Won't init prop page.\n"), m_szFile);
  684. m_szFile[0] = 0;
  685. }
  686. }
  687. } else {
  688. //
  689. // not a link, just copy the filename
  690. //
  691. _tcscpy(m_szFile, szExe);
  692. }
  693. } else {
  694. //
  695. // this is the case when the file is not .lnk, exe or other recognizable type
  696. //
  697. LogMsg(_T("\tNot an EXE or LNK file. Won't init prop page.\n"), m_szFile);
  698. }
  699. }
  700. ReleaseStgMedium(&medium);
  701. } else {
  702. LogMsg(_T("\t failed to get the data.\n"));
  703. }
  704. return NOERROR;
  705. }
  706. //////////////////////////////////////////////////////////////////////////
  707. // IShellPropSheetExt methods
  708. STDMETHODIMP
  709. CLayerUIPropPage::AddPages(
  710. LPFNADDPROPSHEETPAGE lpfnAddPage,
  711. LPARAM lParam
  712. )
  713. {
  714. PROPSHEETPAGE psp;
  715. HPROPSHEETPAGE hPage;
  716. TCHAR szCompatibility[128] = _T("");
  717. BOOL fIsGuest = FALSE;
  718. HINSTANCE hInstRes = _Module.m_hInst;
  719. LogMsg(_T("[CLayerUIPropPage::AddPages]\n"));
  720. if (m_szFile[0] == 0) {
  721. return S_OK;
  722. }
  723. //
  724. // Disable the property page for guests
  725. //
  726. if (!SearchGroupForSID(DOMAIN_ALIAS_RID_GUESTS, &fIsGuest)) {
  727. LogMsg(_T("\tFailed to lookup the GUEST account\n"));
  728. return S_OK;
  729. }
  730. if (fIsGuest) {
  731. LogMsg(_T("\tDisable the compatibility page for the GUEST account\n"));
  732. return S_OK;
  733. }
  734. if (!LoadString(g_hInstance, IDS_COMPATIBILITY, szCompatibility, 128)) {
  735. LogMsg(_T("\tFailed to load \"Compatibility\" resource string\n"));
  736. return S_OK;
  737. }
  738. g_hQfeRes = LoadLibrary(_T("xpsp1res.dll"));
  739. if (g_hQfeRes) {
  740. hInstRes = g_hQfeRes;
  741. }
  742. psp.dwSize = sizeof(psp);
  743. psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
  744. psp.hInstance = hInstRes;
  745. psp.pszTemplate = MAKEINTRESOURCE(IDD_LAYER_PROPPAGE);
  746. psp.hIcon = 0;
  747. psp.pszTitle = szCompatibility;
  748. psp.pfnDlgProc = (DLGPROC)LayerPageDlgProc;
  749. psp.pcRefParent = &g_DllRefCount;
  750. psp.pfnCallback = LayerPageCallbackProc;
  751. psp.lParam = (LPARAM)this;
  752. LogMsg(_T("\titem \"%s\".\n"), m_szFile);
  753. LogMsg(_T("\tg_DllRefCount %d.\n"), g_DllRefCount);
  754. AddRef();
  755. hPage = CreatePropertySheetPage(&psp);
  756. if (hPage != NULL) {
  757. if (lpfnAddPage(hPage, lParam)) {
  758. return S_OK;
  759. } else {
  760. DestroyPropertySheetPage(hPage);
  761. Release();
  762. return S_OK;
  763. }
  764. } else {
  765. return E_OUTOFMEMORY;
  766. }
  767. return E_FAIL;
  768. }
  769. STDMETHODIMP
  770. CLayerUIPropPage::ReplacePage(
  771. UINT uPageID,
  772. LPFNADDPROPSHEETPAGE lpfnReplacePage,
  773. LPARAM lParam
  774. )
  775. {
  776. LogMsg(_T("[CLayerUIPropPage::ReplacePage]\n"));
  777. return S_OK;
  778. }