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.

1172 lines
27 KiB

  1. /*
  2. * propsht.cpp - IPropSheetExt implementation for CFusionShortcut class.
  3. */
  4. // * NOTE!!: this code is incomplete. Also error checking (any leak?),
  5. // * restructuring (for better coding/efficiency) to be done.
  6. // * Make 'Get'/'Set' private and use 'friend'?
  7. //BUGBUG: need wrappers around calls to m_pIdentity->SetAttribute() to also call Dirty(TRUE)...
  8. // * this file uses CharNext etc as it needs User32 anyway *
  9. /* Headers
  10. **********/
  11. #include "project.hpp"
  12. #include <prsht.h>
  13. #include "shellres.h"
  14. extern "C" WINSHELLAPI int WINAPI PickIconDlg(HWND hwnd, LPWSTR pwzIconPath, UINT cbIconPath, int *piIconIndex);
  15. extern HINSTANCE g_DllInstance;
  16. /* Types
  17. ********/
  18. // Fusion Shortcut property sheet data
  19. typedef enum _fusshcutpropsheetpgs
  20. {
  21. FUSIONSHCUT_PS_SHCUT_PAGE = 0x0000,
  22. FUSIONSHCUT_PS_REF_PAGE = 0x0001,
  23. ALL_FUSIONSHCUT_PS_PAGES
  24. }
  25. FUSIONSHCUTPSPAGES;
  26. typedef struct _fsps
  27. {
  28. CFusionShortcut* pfusshcut;
  29. WCHAR rgchIconFile[MAX_PATH];
  30. int niIcon;
  31. FUSIONSHCUTPSPAGES eCurPage;
  32. }
  33. FSPS;
  34. DECLARE_STANDARD_TYPES(FSPS);
  35. typedef FSPS* PFSPS;
  36. /* Module Constants
  37. *******************/
  38. // Tray notification window class
  39. //copied from shell32!
  40. #define WNDCLASS_TRAYNOTIFY L"Shell_TrayWnd" //internal_win40
  41. const WCHAR s_cwzTrayNotificationClass[] = WNDCLASS_TRAYNOTIFY;
  42. // HACKHACK: WMTRAY_SCREGISTERHOTKEY and WMTRAY_SCUNREGISTERHOTKEY are stolen
  43. // from shelldll\link.c.
  44. typedef const UINT CUINT;
  45. CUINT WMTRAY_SCREGISTERHOTKEY = (WM_USER + 233);
  46. CUINT WMTRAY_SCUNREGISTERHOTKEY = (WM_USER + 234);
  47. // show commands - N.b., the order of these constants must match the order of
  48. // the corresponding IDS_ string table constants.
  49. const UINT s_ucMaxShowCmdLen = MAX_PATH;
  50. const UINT s_ucMaxTypeLen = TYPESTRINGLENGTH;
  51. const int s_rgnShowCmds[] =
  52. {
  53. SW_SHOWNORMAL,
  54. SW_SHOWMINNOACTIVE,
  55. SW_SHOWMAXIMIZED
  56. };
  57. /*
  58. ** ExtractFileName()
  59. **
  60. ** Extracts the file name from a path name.
  61. **
  62. ** Arguments: pcwzPathName - path string from which to extract file name
  63. **
  64. ** Returns: Pointer to file name in path string.
  65. **
  66. ** Side Effects: none
  67. */
  68. #define BACKSLASH L'/'
  69. #define SLASH L'\\'
  70. #define COLON L':'
  71. #define IS_SLASH(ch) ((ch) == SLASH || (ch) == BACKSLASH)
  72. PCWSTR ExtractFileName(PCWSTR pcwzPathName)
  73. {
  74. PCWSTR pcwzLastComponent;
  75. PCWSTR pcwz;
  76. for (pcwzLastComponent = pcwz = pcwzPathName; *pcwz; pcwz = CharNext(pcwz))
  77. {
  78. if (IS_SLASH(*pcwz) || *pcwz == COLON)
  79. pcwzLastComponent = CharNext(pcwz);
  80. }
  81. ASSERT(IsValidPath(pcwzLastComponent));
  82. return(pcwzLastComponent);
  83. }
  84. /***************************** Private Functions *****************************/
  85. UINT CALLBACK FSPSCallback(HWND hwnd, UINT uMsg,
  86. LPPROPSHEETPAGE ppsp)
  87. {
  88. // this is called after FSPS_DlgProc WM_DESTROY (ie. FSPS_Destroy)
  89. // this func should do the frees/releases
  90. UINT uResult = TRUE;
  91. PFSPS pfsps = (PFSPS)(ppsp->lParam);
  92. // uMsg may be any value.
  93. ASSERT(! hwnd ||
  94. IS_VALID_HANDLE(hwnd, WND));
  95. switch (uMsg)
  96. {
  97. case PSPCB_CREATE:
  98. // from MSDN: A dialog box for a page is being created.
  99. // Return nonzero to allow it to be created, or zero to prevent it.
  100. break;
  101. case PSPCB_RELEASE:
  102. // ???? need checking if NULL
  103. pfsps->pfusshcut->Release();
  104. // free the FSPS structure, this is created in AddFSPS
  105. // delete only after the ref is removed
  106. delete pfsps;
  107. ppsp->lParam = NULL;
  108. break;
  109. default:
  110. // ignore other msg - unhandled
  111. break;
  112. }
  113. return(uResult);
  114. }
  115. void SetFSPSIcon(HWND hdlg, HICON hicon)
  116. {
  117. HICON hiconOld;
  118. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  119. ASSERT(IS_VALID_HANDLE(hicon, ICON));
  120. hiconOld = (HICON)SendDlgItemMessage(hdlg, IDD_ICON, STM_SETICON,
  121. (WPARAM)hicon, 0);
  122. if (hiconOld)
  123. DestroyIcon(hiconOld);
  124. return;
  125. }
  126. void SetFSPSFileNameAndIcon(HWND hdlg)
  127. {
  128. HRESULT hr;
  129. CFusionShortcut* pfusshcut;
  130. WCHAR rgchFile[MAX_PATH];
  131. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  132. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  133. hr = pfusshcut->GetCurFile(rgchFile, sizeof(rgchFile) / sizeof(WCHAR));
  134. if (hr == S_OK)
  135. {
  136. SHFILEINFO shfi;
  137. DWORD_PTR dwResult;
  138. dwResult = SHGetFileInfo(rgchFile, 0, &shfi, sizeof(shfi),
  139. (SHGFI_DISPLAYNAME | SHGFI_ICON));
  140. if (dwResult)
  141. {
  142. LPWSTR pwzFileName;
  143. pwzFileName = (LPWSTR)ExtractFileName(shfi.szDisplayName);
  144. EVAL(SetDlgItemText(hdlg, IDD_NAME, pwzFileName));
  145. SetFSPSIcon(hdlg, shfi.hIcon);
  146. }
  147. else
  148. {
  149. hr = E_FAIL;
  150. }
  151. }
  152. if (hr != S_OK)
  153. EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
  154. return;
  155. }
  156. void SetFSPSWorkingDirectory(HWND hdlg)
  157. {
  158. CFusionShortcut* pfusshcut;
  159. HRESULT hr;
  160. WCHAR rgchWorkingDirectory[MAX_PATH];
  161. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  162. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  163. hr = pfusshcut->GetWorkingDirectory(rgchWorkingDirectory,
  164. sizeof(rgchWorkingDirectory) / sizeof(WCHAR));
  165. if (hr == S_OK)
  166. {
  167. EVAL(SetDlgItemText(hdlg, IDD_START_IN, rgchWorkingDirectory));
  168. }
  169. else
  170. {
  171. EVAL(SetDlgItemText(hdlg, IDD_START_IN, g_cwzEmptyString));
  172. }
  173. return;
  174. }
  175. void InitFSPSHotkey(HWND hdlg)
  176. {
  177. CFusionShortcut* pfusshcut;
  178. WORD wHotkey;
  179. HRESULT hr;
  180. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  181. // Set hotkey combinations.
  182. SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETRULES,
  183. (HKCOMB_NONE | HKCOMB_A | HKCOMB_C | HKCOMB_S),
  184. (HOTKEYF_CONTROL | HOTKEYF_ALT));
  185. // Set current hotkey.
  186. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  187. hr = pfusshcut->GetHotkey(&wHotkey);
  188. SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
  189. return;
  190. }
  191. void InitFSPSShowCmds(HWND hdlg)
  192. {
  193. int niShowCmd;
  194. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  195. for (niShowCmd = IDS_SHOW_NORMAL;
  196. niShowCmd <= IDS_SHOW_MAXIMIZED;
  197. niShowCmd++)
  198. {
  199. WCHAR rgchShowCmd[s_ucMaxShowCmdLen];
  200. if (LoadString(g_DllInstance, niShowCmd, rgchShowCmd, //MLLoadStringA
  201. s_ucMaxShowCmdLen))//sizeof(rgchShowCmd)))
  202. {
  203. SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_ADDSTRING, 0,
  204. (LPARAM)rgchShowCmd);
  205. }
  206. }
  207. return;
  208. }
  209. void SetFSPSShowCmd(HWND hdlg)
  210. {
  211. CFusionShortcut* pfusshcut;
  212. int nShowCmd;
  213. int i;
  214. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  215. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  216. pfusshcut->GetShowCmd(&nShowCmd);
  217. for (i = 0; i < ARRAY_ELEMENTS(s_rgnShowCmds); i++)
  218. {
  219. if (s_rgnShowCmds[i] == nShowCmd)
  220. break;
  221. }
  222. if (i >= ARRAY_ELEMENTS(s_rgnShowCmds))
  223. {
  224. ASSERT(i == ARRAY_ELEMENTS(s_rgnShowCmds));
  225. i = 0; // default is 0 == 'normal'
  226. }
  227. SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_SETCURSEL, i, 0);
  228. return;
  229. }
  230. void SetFSPSFriendlyName(HWND hdlg)
  231. {
  232. CFusionShortcut* pfusshcut;
  233. HRESULT hr;
  234. WCHAR rgchString[DISPLAYNAMESTRINGLENGTH];
  235. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  236. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  237. hr = pfusshcut->GetDescription(rgchString, sizeof(rgchString) / sizeof(WCHAR));
  238. if (hr == S_OK)
  239. {
  240. EVAL(SetDlgItemText(hdlg, IDD_DISPLAY_NAME, rgchString));
  241. }
  242. else
  243. {
  244. EVAL(SetDlgItemText(hdlg, IDD_DISPLAY_NAME, g_cwzEmptyString));
  245. }
  246. return;
  247. }
  248. void SetFSPSName(HWND hdlg)
  249. {
  250. CFusionShortcut* pfusshcut;
  251. HRESULT hr;
  252. DWORD ccString = 0;
  253. LPWSTR pwzString = NULL;
  254. LPASSEMBLY_IDENTITY pId = NULL;
  255. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  256. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  257. if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
  258. {
  259. hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzString, &ccString);
  260. if (hr == S_OK)
  261. {
  262. EVAL(SetDlgItemText(hdlg, IDD_NAME, pwzString));
  263. delete [] pwzString;
  264. }
  265. pId->Release();
  266. }
  267. if (hr != S_OK)
  268. {
  269. EVAL(SetDlgItemText(hdlg, IDD_NAME, g_cwzEmptyString));
  270. }
  271. return;
  272. }
  273. void SetFSPSVersion(HWND hdlg)
  274. {
  275. CFusionShortcut* pfusshcut;
  276. HRESULT hr;
  277. DWORD ccString = 0;
  278. LPWSTR pwzString = NULL;
  279. LPASSEMBLY_IDENTITY pId = NULL;
  280. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  281. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  282. if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
  283. {
  284. hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION, &pwzString, &ccString);
  285. if (hr == S_OK)
  286. {
  287. EVAL(SetDlgItemText(hdlg, IDD_VERSION, pwzString));
  288. delete [] pwzString;
  289. }
  290. pId->Release();
  291. }
  292. if (hr != S_OK)
  293. {
  294. EVAL(SetDlgItemText(hdlg, IDD_VERSION, g_cwzEmptyString));
  295. }
  296. return;
  297. }
  298. void SetFSPSCulture(HWND hdlg)
  299. {
  300. CFusionShortcut* pfusshcut;
  301. HRESULT hr;
  302. DWORD ccString = 0;
  303. LPWSTR pwzString = NULL;
  304. LPASSEMBLY_IDENTITY pId = NULL;
  305. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  306. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  307. if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
  308. {
  309. hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzString, &ccString);
  310. if (hr == S_OK)
  311. {
  312. EVAL(SetDlgItemText(hdlg, IDD_CULTURE, pwzString));
  313. delete [] pwzString;
  314. }
  315. pId->Release();
  316. }
  317. if (hr != S_OK)
  318. {
  319. EVAL(SetDlgItemText(hdlg, IDD_CULTURE, g_cwzEmptyString));
  320. }
  321. return;
  322. }
  323. void SetFSPSPKT(HWND hdlg)
  324. {
  325. CFusionShortcut* pfusshcut;
  326. HRESULT hr;
  327. DWORD ccString = 0;
  328. LPWSTR pwzString = NULL;
  329. LPASSEMBLY_IDENTITY pId = NULL;
  330. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  331. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  332. if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
  333. {
  334. hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzString, &ccString);
  335. if (hr == S_OK)
  336. {
  337. EVAL(SetDlgItemText(hdlg, IDD_PKT, pwzString));
  338. delete [] pwzString;
  339. }
  340. pId->Release();
  341. }
  342. if (hr != S_OK)
  343. {
  344. EVAL(SetDlgItemText(hdlg, IDD_PKT, g_cwzEmptyString));
  345. }
  346. return;
  347. }
  348. void SetFSPSCodebase(HWND hdlg)
  349. {
  350. CFusionShortcut* pfusshcut;
  351. HRESULT hr;
  352. WCHAR rgchString[MAX_URL_LENGTH];
  353. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  354. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  355. hr = pfusshcut->GetCodebase(rgchString, sizeof(rgchString) / sizeof(WCHAR));
  356. if (hr == S_OK)
  357. {
  358. EVAL(SetDlgItemText(hdlg, IDD_CODEBASE, rgchString));
  359. }
  360. else
  361. {
  362. EVAL(SetDlgItemText(hdlg, IDD_CODEBASE, g_cwzEmptyString));
  363. }
  364. return;
  365. }
  366. void SetFSPSEntrypoint(HWND hdlg)
  367. {
  368. CFusionShortcut* pfusshcut;
  369. HRESULT hr;
  370. WCHAR rgchString[MAX_PATH];
  371. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  372. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  373. hr = pfusshcut->GetPath(rgchString, sizeof(rgchString) / sizeof(WCHAR), NULL, 0);
  374. if (hr == S_OK)
  375. {
  376. EVAL(SetDlgItemText(hdlg, IDD_ENTRYPOINT, rgchString));
  377. }
  378. else
  379. {
  380. EVAL(SetDlgItemText(hdlg, IDD_ENTRYPOINT, g_cwzEmptyString));
  381. }
  382. return;
  383. }
  384. void SetFSPSType(HWND hdlg)
  385. {
  386. CFusionShortcut* pfusshcut;
  387. HRESULT hr;
  388. DWORD ccString = 0;
  389. LPWSTR pwzString = NULL;
  390. LPASSEMBLY_IDENTITY pId = NULL;
  391. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  392. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  393. if (SUCCEEDED(hr = pfusshcut->GetAssemblyIdentity(&pId)))
  394. {
  395. hr = pId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE, &pwzString, &ccString);
  396. if (hr == S_OK)
  397. {
  398. EVAL(SetDlgItemText(hdlg, IDD_TYPE, pwzString));
  399. delete [] pwzString;
  400. }
  401. pId->Release();
  402. }
  403. if (hr != S_OK)
  404. {
  405. EVAL(SetDlgItemText(hdlg, IDD_TYPE, g_cwzEmptyString));
  406. }
  407. return;
  408. }
  409. BOOL FSPS_InitDialog(HWND hdlg, WPARAM wparam, LPARAM lparam)
  410. {
  411. // wparam may be any value.
  412. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  413. // this set PROPSHEETPAGE struct to DWLP_USER
  414. SetWindowLongPtr(hdlg, DWLP_USER, lparam);
  415. // Initialize control contents.
  416. if (((PFSPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == FUSIONSHCUT_PS_SHCUT_PAGE)
  417. {
  418. SetFSPSFileNameAndIcon(hdlg);
  419. // note: need limits on all editbox!
  420. SetFSPSFriendlyName(hdlg);
  421. SendDlgItemMessage(hdlg, IDD_CODEBASE, EM_LIMITTEXT, MAX_URL_LENGTH - 1, 0);
  422. SetFSPSCodebase(hdlg);
  423. //InitFSPSType(hdlg);
  424. SetFSPSType(hdlg);
  425. SendDlgItemMessage(hdlg, IDD_ENTRYPOINT, EM_LIMITTEXT, MAX_PATH - 1, 0);
  426. SetFSPSEntrypoint(hdlg);
  427. SendDlgItemMessage(hdlg, IDD_START_IN, EM_LIMITTEXT, MAX_PATH - 1, 0);
  428. SetFSPSWorkingDirectory(hdlg);
  429. InitFSPSHotkey(hdlg);
  430. InitFSPSShowCmds(hdlg);
  431. SetFSPSShowCmd(hdlg);
  432. }
  433. else if (((PFSPS)(((PROPSHEETPAGE*)lparam)->lParam))->eCurPage == FUSIONSHCUT_PS_REF_PAGE)
  434. {
  435. // note: need limits on all editbox!
  436. SetFSPSFriendlyName(hdlg);
  437. SetFSPSName(hdlg);
  438. SetFSPSVersion(hdlg);
  439. SetFSPSCulture(hdlg);
  440. SetFSPSPKT(hdlg);
  441. }
  442. // else do nothing?
  443. return(TRUE);
  444. }
  445. BOOL FSPS_Destroy(HWND hdlg, WPARAM wparam, LPARAM lparam)
  446. {
  447. // FSPSCallback is called after this func. The remaining frees/releases are there
  448. // wparam may be any value.
  449. // lparam may be any value.
  450. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  451. SetWindowLongPtr(hdlg, DWLP_USER, NULL);
  452. return(TRUE);
  453. }
  454. void FSPSChanged(HWND hdlg)
  455. {
  456. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  457. PropSheet_Changed(GetParent(hdlg), hdlg);
  458. return;
  459. }
  460. HRESULT ChooseIcon(HWND hdlg)
  461. {
  462. HRESULT hr;
  463. PFSPS pfsps;
  464. CFusionShortcut* pfusshcut;
  465. WCHAR rgchTempIconFile[MAX_PATH];
  466. int niIcon;
  467. UINT uFlags;
  468. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  469. pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
  470. pfusshcut = pfsps->pfusshcut;
  471. if (pfusshcut->GetIconLocation(0, rgchTempIconFile,
  472. sizeof(rgchTempIconFile)/sizeof(WCHAR), &niIcon, &uFlags) != S_OK)
  473. {
  474. rgchTempIconFile[0] = '\0';
  475. niIcon = 0;
  476. }
  477. ASSERT(wcslen(rgchTempIconFile) < (sizeof(rgchTempIconFile)/sizeof(WCHAR)));
  478. // a private shell32.dll export (by ordinal)...
  479. if (PickIconDlg(hdlg, rgchTempIconFile, sizeof(rgchTempIconFile)/sizeof(WCHAR), &niIcon)) //??? sizeof
  480. {
  481. ASSERT(wcslen(rgchTempIconFile) < (sizeof(pfsps->rgchIconFile)/sizeof(WCHAR)));
  482. wcscpy(pfsps->rgchIconFile, rgchTempIconFile);
  483. pfsps->niIcon = niIcon;
  484. hr = S_OK;
  485. }
  486. else
  487. {
  488. hr = E_FAIL;
  489. }
  490. return(hr);
  491. }
  492. void UpdateFSPSIcon(HWND hdlg)
  493. {
  494. PFSPS pfsps;
  495. HICON hicon;
  496. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  497. pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
  498. ASSERT(pfsps->rgchIconFile[0]);
  499. hicon = ExtractIcon(g_DllInstance, pfsps->rgchIconFile, pfsps->niIcon);
  500. if (hicon)
  501. SetFSPSIcon(hdlg, hicon);
  502. return;
  503. }
  504. BOOL FSPS_Command(HWND hdlg, WPARAM wparam, LPARAM lparam)
  505. {
  506. BOOL bMsgHandled = FALSE;
  507. WORD wCmd;
  508. // wparam may be any value.
  509. // lparam may be any value.
  510. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  511. wCmd = HIWORD(wparam);
  512. switch (LOWORD(wparam))
  513. {
  514. case IDD_CODEBASE:
  515. case IDD_HOTKEY:
  516. case IDD_ENTRYPOINT:
  517. case IDD_START_IN:
  518. case IDD_DISPLAY_NAME:
  519. case IDD_NAME:
  520. case IDD_VERSION:
  521. case IDD_CULTURE:
  522. case IDD_PKT:
  523. case IDD_TYPE:
  524. if (wCmd == EN_CHANGE)
  525. {
  526. FSPSChanged(hdlg);
  527. bMsgHandled = TRUE;
  528. }
  529. break;
  530. case IDD_SHOW_CMD:
  531. if (wCmd == LBN_SELCHANGE)
  532. {
  533. FSPSChanged(hdlg);
  534. bMsgHandled = TRUE;
  535. }
  536. break;
  537. case IDD_CHANGE_ICON:
  538. // Ignore return value.
  539. if (ChooseIcon(hdlg) == S_OK)
  540. {
  541. UpdateFSPSIcon(hdlg);
  542. FSPSChanged(hdlg);
  543. }
  544. bMsgHandled = TRUE;
  545. break;
  546. default:
  547. break;
  548. }
  549. return(bMsgHandled);
  550. }
  551. HRESULT InjectFSPSData(HWND hdlg)
  552. {
  553. // BUGBUG: TODO: this function should validate the user's changes...
  554. HRESULT hr = S_OK;
  555. PFSPS pfsps;
  556. CFusionShortcut* pfusshcut;
  557. LPWSTR pwzURL;
  558. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  559. pfsps = (PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam);
  560. pfusshcut = pfsps->pfusshcut;
  561. return(hr);
  562. }
  563. HRESULT FSPSSave(HWND hdlg)
  564. {
  565. HRESULT hr;
  566. CFusionShortcut* pfusshcut;
  567. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  568. pfusshcut = ((PFSPS)(((PROPSHEETPAGE*)GetWindowLongPtr(hdlg, DWLP_USER))->lParam))->pfusshcut;
  569. if (pfusshcut->IsDirty() == S_OK)
  570. {
  571. // BUGBUG: TODO: IPersistFile::Save is not implemented
  572. hr = pfusshcut->Save((LPCOLESTR)NULL, FALSE);
  573. }
  574. else
  575. {
  576. hr = S_OK;
  577. }
  578. return(hr);
  579. }
  580. BOOL FSPS_Notify(HWND hdlg, WPARAM wparam, LPARAM lparam)
  581. {
  582. BOOL bMsgHandled = FALSE;
  583. // wparam may be any value.
  584. // lparam may be any value.
  585. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  586. switch (((NMHDR*)lparam)->code)
  587. {
  588. case PSN_APPLY:
  589. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FSPSSave(hdlg) == S_OK ?
  590. PSNRET_NOERROR :
  591. PSNRET_INVALID_NOCHANGEPAGE);
  592. bMsgHandled = TRUE;
  593. break;
  594. case PSN_KILLACTIVE:
  595. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectFSPSData(hdlg)));
  596. bMsgHandled = TRUE;
  597. break;
  598. default:
  599. break;
  600. }
  601. return(bMsgHandled);
  602. }
  603. INT_PTR CALLBACK FSPS_DlgProc(HWND hdlg, UINT uMsg, WPARAM wparam,
  604. LPARAM lparam)
  605. {
  606. INT_PTR bMsgHandled = FALSE;
  607. // uMsg may be any value.
  608. // wparam may be any value.
  609. // lparam may be any value.
  610. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  611. switch (uMsg)
  612. {
  613. case WM_INITDIALOG:
  614. bMsgHandled = FSPS_InitDialog(hdlg, wparam, lparam);
  615. break;
  616. case WM_DESTROY:
  617. bMsgHandled = FSPS_Destroy(hdlg, wparam, lparam);
  618. break;
  619. case WM_COMMAND:
  620. bMsgHandled = FSPS_Command(hdlg, wparam, lparam);
  621. break;
  622. case WM_NOTIFY:
  623. bMsgHandled = FSPS_Notify(hdlg, wparam, lparam);
  624. break;
  625. default:
  626. break;
  627. }
  628. return(bMsgHandled);
  629. }
  630. HRESULT AddFSPS(CFusionShortcut* pfusshcut,
  631. LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lparam)
  632. {
  633. HRESULT hr = S_OK;
  634. PFSPS pfsps;
  635. PROPSHEETPAGE psp;
  636. HPROPSHEETPAGE hpsp;
  637. PFSPS pfsps2;
  638. PROPSHEETPAGE psp2;
  639. HPROPSHEETPAGE hpsp2;
  640. // lparam may be any value.
  641. // this is deleted in FSPSCallback
  642. pfsps = new FSPS;
  643. if (pfsps == NULL)
  644. {
  645. hr = E_OUTOFMEMORY;
  646. goto exit;
  647. }
  648. ZeroMemory(pfsps, sizeof(*pfsps));
  649. psp.dwSize = sizeof(psp);
  650. psp.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
  651. psp.hInstance = g_DllInstance; //MLGetHinst();
  652. psp.pszTemplate = MAKEINTRESOURCE(DLG_FUS_SHORTCUT_PROP_SHEET);
  653. psp.pfnDlgProc = &FSPS_DlgProc;
  654. psp.pfnCallback = &FSPSCallback;
  655. psp.lParam = (LPARAM)pfsps;
  656. psp.hIcon = 0; // not used
  657. psp.pszTitle = NULL; // not used
  658. psp.pcRefParent = 0; // not used
  659. pfsps->pfusshcut = pfusshcut;
  660. pfsps->eCurPage = FUSIONSHCUT_PS_SHCUT_PAGE; // page 1
  661. // will psp be copied in this func? else this won't work...!!??
  662. hpsp = CreatePropertySheetPage(&psp);
  663. if (hpsp)
  664. {
  665. if ((*pfnAddPage)(hpsp, lparam))
  666. {
  667. pfusshcut->AddRef();
  668. }
  669. else
  670. {
  671. DestroyPropertySheetPage(hpsp);
  672. hr = E_FAIL;
  673. goto exit;
  674. }
  675. }
  676. else
  677. {
  678. hr = E_OUTOFMEMORY;
  679. goto exit;
  680. }
  681. // this is deleted in FSPSCallback
  682. pfsps2 = new FSPS;
  683. if (pfsps2 == NULL)
  684. {
  685. hr = E_OUTOFMEMORY;
  686. goto exit;
  687. }
  688. ZeroMemory(pfsps2, sizeof(*pfsps2));
  689. psp2.dwSize = sizeof(psp2);
  690. psp2.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
  691. psp2.hInstance = g_DllInstance; //MLGetHinst();
  692. psp2.pszTemplate = MAKEINTRESOURCE(DLG_FUS_SHORTCUT_PROP_SHEET_APPNAME);
  693. psp2.pfnDlgProc = &FSPS_DlgProc;
  694. psp2.pfnCallback = &FSPSCallback;
  695. psp2.lParam = (LPARAM)pfsps2;
  696. psp2.hIcon = 0; // not used
  697. psp2.pszTitle = NULL; // not used
  698. psp2.pcRefParent = 0; // not used
  699. pfsps2->pfusshcut = pfusshcut;
  700. pfsps2->eCurPage = FUSIONSHCUT_PS_REF_PAGE; // page 2
  701. // will psp be copied in this func? else this won't work...!!??
  702. hpsp2 = CreatePropertySheetPage(&psp2);
  703. if (hpsp2)
  704. {
  705. if ((*pfnAddPage)(hpsp2, lparam))
  706. {
  707. pfusshcut->AddRef();
  708. }
  709. else
  710. {
  711. DestroyPropertySheetPage(hpsp2);
  712. hr = E_FAIL;
  713. goto exit;
  714. }
  715. }
  716. else
  717. {
  718. hr = E_OUTOFMEMORY;
  719. goto exit;
  720. }
  721. exit:
  722. return(hr);
  723. }
  724. /****************************** Public Functions *****************************/
  725. BOOL RegisterGlobalHotkey(WORD wOldHotkey, WORD wNewHotkey,
  726. LPCWSTR pcwzPath)
  727. {
  728. // BUGBUG?: does this work??
  729. BOOL bResult = FALSE;
  730. HWND hwndTray;
  731. ASSERT(! wOldHotkey || IsValidHotkey(wOldHotkey));
  732. ASSERT(! wNewHotkey || IsValidHotkey(wNewHotkey));
  733. ASSERT(IsValidPath(pcwzPath));
  734. hwndTray = FindWindow(s_cwzTrayNotificationClass, 0);
  735. if (hwndTray)
  736. {
  737. if (wOldHotkey)
  738. {
  739. SendMessage(hwndTray, WMTRAY_SCUNREGISTERHOTKEY, wOldHotkey, 0);
  740. }
  741. if (wNewHotkey)
  742. {
  743. ATOM atom = GlobalAddAtom(pcwzPath);
  744. ASSERT(atom);
  745. if (atom)
  746. {
  747. SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey, (LPARAM)atom);
  748. GlobalDeleteAtom(atom);
  749. }
  750. }
  751. bResult = TRUE;
  752. }
  753. /*else
  754. {
  755. bResult = FALSE;
  756. }*/
  757. return(bResult);
  758. }
  759. /********************************** Methods **********************************/
  760. HRESULT STDMETHODCALLTYPE CFusionShortcut::Initialize(LPCITEMIDLIST pcidlFolder,
  761. IDataObject* pido,
  762. HKEY hkeyProgID)
  763. {
  764. HRESULT hr;
  765. STGMEDIUM stgmed;
  766. FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  767. ASSERT(NULL != pido);
  768. ASSERT(IS_VALID_HANDLE(hkeyProgID, KEY));
  769. hr = pido->GetData(&fmtetc, &stgmed);
  770. if (hr == S_OK)
  771. {
  772. WCHAR wzPath[MAX_PATH];
  773. if (DragQueryFile((HDROP)stgmed.hGlobal, 0, wzPath, sizeof(wzPath)/sizeof(*wzPath)))
  774. {
  775. //mode is ignored for now
  776. hr = Load(wzPath, 0);
  777. }
  778. // else path len > MAX_PATH or other error
  779. ReleaseStgMedium(&stgmed);
  780. }
  781. return(hr);
  782. }
  783. HRESULT STDMETHODCALLTYPE CFusionShortcut::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage,
  784. LPARAM lparam)
  785. {
  786. HRESULT hr;
  787. // lparam may be any value.
  788. hr = AddFSPS(this, pfnAddPage, lparam);
  789. // BUGBUG: why this does not work?
  790. // From MSDN:
  791. //With version 4.71 and later, you can request that a particular property
  792. //sheet page be displayed first, instead of the default page. To do so,
  793. //return the one-based index of the desired page. For example, if you
  794. //want the second of three pages displayed, the return value should be 2.
  795. //Note that this return value is a request. The property sheet may still
  796. //display the default page. --> see doc for AddPages()
  797. if (SUCCEEDED(hr))
  798. hr = HRESULT(4); // or 3??
  799. return(hr);
  800. }
  801. HRESULT STDMETHODCALLTYPE CFusionShortcut::ReplacePage(UINT uPageID,
  802. LPFNADDPROPSHEETPAGE pfnReplaceWith,
  803. LPARAM lparam)
  804. {
  805. HRESULT hr;
  806. // lparam may be any value.
  807. // uPageID may be any value.
  808. hr = E_NOTIMPL;
  809. return(hr);
  810. }
  811. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetCodebase(LPCWSTR pcwzCodebase)
  812. {
  813. HRESULT hr = S_OK;
  814. BOOL bDifferent;
  815. LPWSTR pwzNewCodebase = NULL;
  816. // Set m_pwzCodebase to codebase.
  817. // check if empty string?
  818. bDifferent = ! ((! pcwzCodebase && ! m_pwzCodebase) ||
  819. (pcwzCodebase && m_pwzCodebase &&
  820. ! wcscmp(pcwzCodebase, m_pwzCodebase)));
  821. if (bDifferent && pcwzCodebase)
  822. {
  823. // (+ 1) for null terminator.
  824. pwzNewCodebase = new(WCHAR[wcslen(pcwzCodebase) + 1]);
  825. if (pwzNewCodebase)
  826. wcscpy(pwzNewCodebase, pcwzCodebase);
  827. else
  828. hr = E_OUTOFMEMORY;
  829. }
  830. if (hr == S_OK && bDifferent)
  831. {
  832. if (m_pwzCodebase)
  833. delete [] m_pwzCodebase;
  834. m_pwzCodebase = pwzNewCodebase;
  835. Dirty(TRUE);
  836. }
  837. return(hr);
  838. }
  839. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetCodebase(LPWSTR pwzCodebase,
  840. int ncBufLen)
  841. {
  842. HRESULT hr = S_OK;
  843. // Get description from m_pwzCodebase.
  844. if (m_pwzCodebase)
  845. {
  846. if (pwzCodebase == NULL || ncBufLen <= 0)
  847. hr = E_INVALIDARG;
  848. else
  849. {
  850. wcsncpy(pwzCodebase, m_pwzCodebase, ncBufLen-1);
  851. pwzCodebase[ncBufLen-1] = L'\0';
  852. }
  853. }
  854. else
  855. {
  856. if (ncBufLen > 0 && pwzCodebase != NULL)
  857. pwzCodebase = L'\0';
  858. }
  859. ASSERT(hr == S_OK &&
  860. (ncBufLen <= 0 ||
  861. EVAL(wcslen(pwzCodebase) < ncBufLen)));
  862. return(hr);
  863. }