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.

1427 lines
33 KiB

  1. /*
  2. * propsht.cpp - IPropSheetExt implementation for URL class.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.hpp"
  7. #pragma hdrstop
  8. #undef NO_HELP // for help.h
  9. #include <help.h>
  10. #undef IDH_COMM_GROUPBOX // for addon.h
  11. #include <addon.h>
  12. #include "resource.h"
  13. #include <mluisupp.h>
  14. /* Types
  15. ********/
  16. /* Internet Shortcut property sheet data */
  17. typedef struct _isps
  18. {
  19. PROPSHEETPAGE psp;
  20. PInternetShortcut pintshcut;
  21. char rgchIconFile[MAX_PATH_LEN];
  22. int niIcon;
  23. }
  24. ISPS;
  25. DECLARE_STANDARD_TYPES(ISPS);
  26. /* Module Constants
  27. *******************/
  28. #pragma data_seg(DATA_SEG_READ_ONLY)
  29. // Tray notification window class
  30. PRIVATE_DATA const char s_cszTrayNotificationClass[] = WNDCLASS_TRAYNOTIFY;
  31. // HACKHACK: WMTRAY_SCREGISTERHOTKEY and WMTRAY_SCUNREGISTERHOTKEY are stolen
  32. // from shelldll\link.c.
  33. PRIVATE_DATA CUINT WMTRAY_SCREGISTERHOTKEY = (WM_USER + 233);
  34. PRIVATE_DATA CUINT WMTRAY_SCUNREGISTERHOTKEY = (WM_USER + 234);
  35. // show commands - N.b., the order of these constants must match the order of
  36. // the corresponding IDS_ string table constants.
  37. PRIVATE_DATA const UINT s_ucMaxShowCmdLen = MAX_PATH_LEN;
  38. PRIVATE_DATA const int s_rgnShowCmds[] =
  39. {
  40. SW_SHOWNORMAL,
  41. SW_SHOWMINNOACTIVE,
  42. SW_SHOWMAXIMIZED
  43. };
  44. // help files
  45. PRIVATE_DATA const char s_cszPlusHelpFile[] = "Plus!.hlp";
  46. // help topics
  47. PRIVATE_DATA const DWORD s_rgdwHelpIDs[] =
  48. {
  49. IDD_LINE_1, NO_HELP,
  50. IDD_LINE_2, NO_HELP,
  51. IDD_ICON, IDH_FCAB_LINK_ICON,
  52. IDD_NAME, IDH_FCAB_LINK_NAME,
  53. IDD_URL_TEXT, IDH_INTERNET_SHORTCUT_TARGET,
  54. IDD_URL, IDH_INTERNET_SHORTCUT_TARGET,
  55. IDD_HOTKEY_TEXT, IDH_FCAB_LINK_HOTKEY,
  56. IDD_HOTKEY, IDH_FCAB_LINK_HOTKEY,
  57. IDD_START_IN_TEXT, IDH_FCAB_LINK_WORKING,
  58. IDD_START_IN, IDH_FCAB_LINK_WORKING,
  59. IDD_SHOW_CMD, IDH_FCAB_LINK_RUN,
  60. IDD_CHANGE_ICON, IDH_FCAB_LINK_CHANGEICON,
  61. 0, 0
  62. };
  63. #pragma data_seg()
  64. /***************************** Private Functions *****************************/
  65. #ifdef DEBUG
  66. PRIVATE_CODE BOOL IsValidPCISPS(PCISPS pcisps)
  67. {
  68. return(IS_VALID_READ_PTR(pcisps, CISPS) &&
  69. IS_VALID_STRUCT_PTR(&(pcisps->psp), CPROPSHEETPAGE) &&
  70. IS_VALID_STRUCT_PTR(pcisps->pintshcut, CInternetShortcut) &&
  71. EVAL(IsValidIconIndex(*(pcisps->rgchIconFile) ? S_OK : S_FALSE, pcisps->rgchIconFile, sizeof(pcisps->rgchIconFile), pcisps->niIcon)));
  72. }
  73. #endif
  74. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  75. PRIVATE_CODE UINT CALLBACK ISPSCallback(HWND hwnd, UINT uMsg,
  76. LPPROPSHEETPAGE ppsp)
  77. {
  78. UINT uResult = TRUE;
  79. PISPS pisps = (PISPS)ppsp;
  80. // uMsg may be any value.
  81. ASSERT(! hwnd ||
  82. IS_VALID_HANDLE(hwnd, WND));
  83. ASSERT(IS_VALID_STRUCT_PTR((PCISPS)ppsp, CISPS));
  84. switch (uMsg)
  85. {
  86. case PSPCB_CREATE:
  87. TRACE_OUT(("ISPSCallback(): Received PSPCB_CREATE."));
  88. break;
  89. case PSPCB_RELEASE:
  90. TRACE_OUT(("ISPSCallback(): Received PSPCB_RELEASE."));
  91. pisps->pintshcut->Release();
  92. break;
  93. default:
  94. TRACE_OUT(("ISPSCallback(): Unhandled message %u.",
  95. uMsg));
  96. break;
  97. }
  98. return(uResult);
  99. }
  100. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  101. PRIVATE_CODE void SetISPSIcon(HWND hdlg, HICON hicon)
  102. {
  103. HICON hiconOld;
  104. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  105. ASSERT(IS_VALID_HANDLE(hicon, ICON));
  106. hiconOld = (HICON)SendDlgItemMessage(hdlg, IDD_ICON, STM_SETICON,
  107. (WPARAM)hicon, 0);
  108. if (hiconOld)
  109. DestroyIcon(hiconOld);
  110. TRACE_OUT(("SetISPSIcon(): Set property sheet icon to %#lx.",
  111. hicon));
  112. return;
  113. }
  114. PRIVATE_CODE void SetISPSFileNameAndIcon(HWND hdlg)
  115. {
  116. HRESULT hr;
  117. PInternetShortcut pintshcut;
  118. char rgchFile[MAX_PATH_LEN];
  119. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  120. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  121. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  122. hr = pintshcut->GetCurFile(rgchFile, sizeof(rgchFile));
  123. if (hr == S_OK)
  124. {
  125. SHFILEINFO shfi;
  126. DWORD_PTR dwResult;
  127. dwResult = SHGetFileInfo(rgchFile, 0, &shfi, sizeof(shfi),
  128. (SHGFI_DISPLAYNAME | SHGFI_ICON));
  129. if (dwResult)
  130. {
  131. PSTR pszFileName;
  132. pszFileName = (PSTR)ExtractFileName(shfi.szDisplayName);
  133. EVAL(SetDlgItemText(hdlg, IDD_NAME, pszFileName));
  134. TRACE_OUT(("SetISPSFileNameAndIcon(): Set property sheet file name to \"%s\".",
  135. pszFileName));
  136. SetISPSIcon(hdlg, shfi.hIcon);
  137. }
  138. else
  139. {
  140. hr = E_FAIL;
  141. TRACE_OUT(("SetISPSFileNameAndIcon(): SHGetFileInfo() failed, returning %lu.",
  142. dwResult));
  143. }
  144. }
  145. else
  146. TRACE_OUT(("SetISPSFileNameAndIcon(): GetCurFile() failed, returning %s.",
  147. GetHRESULTString(hr)));
  148. if (hr != S_OK)
  149. EVAL(SetDlgItemText(hdlg, IDD_NAME, EMPTY_STRING));
  150. return;
  151. }
  152. PRIVATE_CODE void SetISPSURL(HWND hdlg)
  153. {
  154. PInternetShortcut pintshcut;
  155. HRESULT hr;
  156. PSTR pszURL;
  157. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  158. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  159. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  160. hr = pintshcut->GetURL(&pszURL);
  161. if (hr == S_OK)
  162. {
  163. EVAL(SetDlgItemText(hdlg, IDD_URL, pszURL));
  164. TRACE_OUT(("SetISPSURL(): Set property sheet URL to \"%s\".",
  165. pszURL));
  166. SHFree(pszURL);
  167. pszURL = NULL;
  168. }
  169. else
  170. EVAL(SetDlgItemText(hdlg, IDD_URL, EMPTY_STRING));
  171. return;
  172. }
  173. PRIVATE_CODE void SetISPSWorkingDirectory(HWND hdlg)
  174. {
  175. PInternetShortcut pintshcut;
  176. HRESULT hr;
  177. char rgchWorkingDirectory[MAX_PATH_LEN];
  178. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  179. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  180. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  181. hr = pintshcut->GetWorkingDirectory(rgchWorkingDirectory,
  182. sizeof(rgchWorkingDirectory));
  183. if (hr == S_OK)
  184. {
  185. EVAL(SetDlgItemText(hdlg, IDD_START_IN, rgchWorkingDirectory));
  186. TRACE_OUT(("SetISPSWorkingDirectory(): Set property sheet working directory to \"%s\".",
  187. rgchWorkingDirectory));
  188. }
  189. else
  190. {
  191. TRACE_OUT(("SetISPSWorkingDirectory(): GetWorkingDirectory() failed, returning %s.",
  192. GetHRESULTString(hr)));
  193. EVAL(SetDlgItemText(hdlg, IDD_START_IN, EMPTY_STRING));
  194. }
  195. return;
  196. }
  197. PRIVATE_CODE void InitISPSHotkey(HWND hdlg)
  198. {
  199. PInternetShortcut pintshcut;
  200. WORD wHotkey;
  201. HRESULT hr;
  202. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  203. // Set hotkey combinations.
  204. SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETRULES,
  205. (HKCOMB_NONE | HKCOMB_A | HKCOMB_C | HKCOMB_S),
  206. (HOTKEYF_CONTROL | HOTKEYF_ALT));
  207. // Set current hotkey.
  208. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  209. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  210. hr = pintshcut->GetHotkey(&wHotkey);
  211. SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
  212. return;
  213. }
  214. PRIVATE_CODE void InitISPSShowCmds(HWND hdlg)
  215. {
  216. int niShowCmd;
  217. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  218. for (niShowCmd = IDS_SHOW_NORMAL;
  219. niShowCmd <= IDS_SHOW_MAXIMIZED;
  220. niShowCmd++)
  221. {
  222. char rgchShowCmd[s_ucMaxShowCmdLen];
  223. if (MLLoadStringA(niShowCmd, rgchShowCmd,
  224. sizeof(rgchShowCmd)))
  225. {
  226. SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_ADDSTRING, 0,
  227. (LPARAM)rgchShowCmd);
  228. TRACE_OUT(("InitISPSShowCmds(): Added show command \"%s\".",
  229. rgchShowCmd));
  230. }
  231. else
  232. ERROR_OUT(("InitISPSShowCmds(): Unable to load string %d.",
  233. niShowCmd));
  234. }
  235. return;
  236. }
  237. PRIVATE_CODE void SetISPSShowCmd(HWND hdlg)
  238. {
  239. PInternetShortcut pintshcut;
  240. int nShowCmd;
  241. int i;
  242. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  243. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  244. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  245. pintshcut->GetShowCmd(&nShowCmd);
  246. for (i = 0; i < ARRAY_ELEMENTS(s_rgnShowCmds); i++)
  247. {
  248. if (s_rgnShowCmds[i] == nShowCmd)
  249. break;
  250. }
  251. if (i >= ARRAY_ELEMENTS(s_rgnShowCmds))
  252. {
  253. ASSERT(i == ARRAY_ELEMENTS(s_rgnShowCmds));
  254. WARNING_OUT(("SetISPSShowCmd(): Unrecognized show command %d. Defaulting to normal.",
  255. nShowCmd));
  256. i = 0;
  257. }
  258. SendDlgItemMessage(hdlg, IDD_SHOW_CMD, CB_SETCURSEL, i, 0);
  259. TRACE_OUT(("SetISPSShowCmd(): Set property sheet show command to index %d.",
  260. i));
  261. return;
  262. }
  263. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  264. PRIVATE_CODE BOOL ISPS_InitDialog(HWND hdlg, WPARAM wparam, LPARAM lparam)
  265. {
  266. PInternetShortcut pintshcut;
  267. // wparam may be any value.
  268. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  269. ASSERT(IS_VALID_STRUCT_PTR((PCISPS)lparam, CISPS));
  270. SetWindowLongPtr(hdlg, DWLP_USER, lparam);
  271. pintshcut = ((PISPS)lparam)->pintshcut;
  272. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  273. // Initialize control contents.
  274. SetISPSFileNameAndIcon(hdlg);
  275. SendDlgItemMessage(hdlg, IDD_URL, EM_LIMITTEXT, g_ucMaxURLLen - 1, 0);
  276. SetISPSURL(hdlg);
  277. SendDlgItemMessage(hdlg, IDD_START_IN, EM_LIMITTEXT, MAX_PATH_LEN - 1, 0);
  278. SetISPSWorkingDirectory(hdlg);
  279. InitISPSHotkey(hdlg);
  280. InitISPSShowCmds(hdlg);
  281. SetISPSShowCmd(hdlg);
  282. return(TRUE);
  283. }
  284. PRIVATE_CODE BOOL ISPS_Destroy(HWND hdlg, WPARAM wparam, LPARAM lparam)
  285. {
  286. PInternetShortcut pintshcut;
  287. // wparam may be any value.
  288. // lparam may be any value.
  289. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  290. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  291. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  292. SetWindowLongPtr(hdlg, DWLP_USER, NULL);
  293. return(TRUE);
  294. }
  295. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  296. PRIVATE_CODE void ISPSChanged(HWND hdlg)
  297. {
  298. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  299. PropSheet_Changed(GetParent(hdlg), hdlg);
  300. return;
  301. }
  302. PRIVATE_CODE HRESULT ChooseIcon(HWND hdlg)
  303. {
  304. HRESULT hr;
  305. PISPS pisps;
  306. PInternetShortcut pintshcut;
  307. char rgchTempIconFile[MAX_PATH_LEN];
  308. int niIcon;
  309. UINT uFlags;
  310. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  311. pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
  312. ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
  313. pintshcut = pisps->pintshcut;
  314. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  315. if (pintshcut->GetIconLocation(0, rgchTempIconFile,
  316. sizeof(rgchTempIconFile), &niIcon, &uFlags)
  317. != S_OK)
  318. {
  319. rgchTempIconFile[0] = '\0';
  320. niIcon = 0;
  321. }
  322. ASSERT(lstrlen(rgchTempIconFile) < sizeof(rgchTempIconFile));
  323. if (RUNNING_NT)
  324. {
  325. WCHAR uTempIconFile[MAX_PATH_LEN];
  326. MultiByteToWideChar(CP_ACP, 0, rgchTempIconFile, -1,
  327. uTempIconFile, MAX_PATH_LEN);
  328. if (PickIconDlg(hdlg, uTempIconFile, MAX_PATH_LEN, &niIcon))
  329. {
  330. WideCharToMultiByte(CP_ACP, 0, uTempIconFile, -1, pisps->rgchIconFile,
  331. MAX_PATH_LEN, NULL, NULL);
  332. pisps->niIcon = niIcon;
  333. hr = S_OK;
  334. }
  335. else
  336. {
  337. hr = E_FAIL;
  338. TRACE_OUT(("ChooseIcon(NT): PickIconDlg() failed."));
  339. }
  340. }
  341. else
  342. {
  343. if (PickIconDlg(hdlg, (LPWSTR)rgchTempIconFile, sizeof(rgchTempIconFile), &niIcon)) // (LPWSTR) so it builds, but works downlevel
  344. {
  345. ASSERT(lstrlen(rgchTempIconFile) < sizeof(pisps->rgchIconFile));
  346. lstrcpy(pisps->rgchIconFile, rgchTempIconFile);
  347. pisps->niIcon = niIcon;
  348. hr = S_OK;
  349. }
  350. else
  351. {
  352. hr = E_FAIL;
  353. TRACE_OUT(("ChooseIcon(): PickIconDlg() failed."));
  354. }
  355. }
  356. return(hr);
  357. }
  358. PRIVATE_CODE void UpdateISPSIcon(HWND hdlg)
  359. {
  360. PISPS pisps;
  361. HICON hicon;
  362. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  363. pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
  364. ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
  365. ASSERT(pisps->rgchIconFile[0]);
  366. // This icon does not have the link arrow overlayed. shell32.dll's
  367. // Shortcut property sheet has the same bug.
  368. hicon = ExtractIcon(GetThisModulesHandle(), pisps->rgchIconFile,
  369. pisps->niIcon);
  370. if (hicon)
  371. SetISPSIcon(hdlg, hicon);
  372. else
  373. WARNING_OUT(("UpdateISPSIcon(): ExtractIcon() failed for icon %d in file %s.",
  374. pisps->niIcon,
  375. pisps->rgchIconFile));
  376. return;
  377. }
  378. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  379. PRIVATE_CODE BOOL ISPS_Command(HWND hdlg, WPARAM wparam, LPARAM lparam)
  380. {
  381. BOOL bMsgHandled = FALSE;
  382. WORD wCmd;
  383. // wparam may be any value.
  384. // lparam may be any value.
  385. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  386. wCmd = HIWORD(wparam);
  387. switch (LOWORD(wparam))
  388. {
  389. case IDD_URL:
  390. case IDD_HOTKEY:
  391. case IDD_START_IN:
  392. if (wCmd == EN_CHANGE)
  393. {
  394. ISPSChanged(hdlg);
  395. bMsgHandled = TRUE;
  396. }
  397. break;
  398. case IDD_SHOW_CMD:
  399. if (wCmd == LBN_SELCHANGE)
  400. {
  401. ISPSChanged(hdlg);
  402. bMsgHandled = TRUE;
  403. }
  404. break;
  405. case IDD_CHANGE_ICON:
  406. // Ignore return value.
  407. if (ChooseIcon(hdlg) == S_OK)
  408. {
  409. UpdateISPSIcon(hdlg);
  410. ISPSChanged(hdlg);
  411. }
  412. bMsgHandled = TRUE;
  413. break;
  414. default:
  415. break;
  416. }
  417. return(bMsgHandled);
  418. }
  419. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  420. PRIVATE_CODE HRESULT ComplainAboutURL(HWND hwndParent, PCSTR pcszURL,
  421. HRESULT hrError)
  422. {
  423. HRESULT hr;
  424. int nResult;
  425. // Validate hrError below.
  426. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  427. ASSERT(IS_VALID_STRING_PTR(pcszURL, CSTR));
  428. switch (hrError)
  429. {
  430. case URL_E_UNREGISTERED_PROTOCOL:
  431. {
  432. PSTR pszProtocol;
  433. hr = CopyURLProtocol(pcszURL, &pszProtocol);
  434. if (hr == S_OK)
  435. {
  436. if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  437. MAKEINTRESOURCE(IDS_UNREGISTERED_PROTOCOL),
  438. (MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION),
  439. &nResult, pszProtocol))
  440. {
  441. switch (nResult)
  442. {
  443. case IDYES:
  444. hr = S_OK;
  445. TRACE_OUT(("ComplainAboutURL(): Allowing URL %s despite unregistered protocol %s, by request.",
  446. pcszURL,
  447. pszProtocol));
  448. break;
  449. default:
  450. ASSERT(nResult == IDNO);
  451. hr = E_FAIL;
  452. TRACE_OUT(("ComplainAboutURL(): Not allowing URL %s because of unregistered protocol %s, as directed.",
  453. pcszURL,
  454. pszProtocol));
  455. break;
  456. }
  457. }
  458. delete pszProtocol;
  459. pszProtocol = NULL;
  460. }
  461. break;
  462. }
  463. default:
  464. ASSERT(hrError == URL_E_INVALID_SYNTAX);
  465. if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  466. MAKEINTRESOURCE(IDS_INVALID_URL_SYNTAX),
  467. (MB_OK | MB_ICONEXCLAMATION), &nResult, pcszURL)) {
  468. ASSERT(nResult == IDOK);
  469. }
  470. hr = E_FAIL;
  471. TRACE_OUT(("ComplainAboutURL(): Not allowing URL %s because of invalid syntax.",
  472. pcszURL));
  473. break;
  474. }
  475. return(hr);
  476. }
  477. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  478. PRIVATE_CODE HRESULT ComplainAboutWorkingDirectory(HWND hwndParent,
  479. PCSTR pcszWorkingDirectory,
  480. HRESULT hrError)
  481. {
  482. int nResult;
  483. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  484. ASSERT(IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR));
  485. ASSERT(hrError == E_PATH_NOT_FOUND);
  486. if (MyMsgBox(hwndParent, MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  487. MAKEINTRESOURCE(IDS_WORKING_DIR_NOT_FOUND),
  488. (MB_OK | MB_ICONEXCLAMATION), &nResult, pcszWorkingDirectory)) {
  489. ASSERT(nResult == IDOK);
  490. }
  491. TRACE_OUT(("ComplainAboutWorkingDirectory(): Not allowing non-existent working directory %s.",
  492. pcszWorkingDirectory));
  493. return(E_FAIL);
  494. }
  495. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  496. PRIVATE_CODE HRESULT InjectISPSData(HWND hdlg)
  497. {
  498. HRESULT hr;
  499. PISPS pisps;
  500. PInternetShortcut pintshcut;
  501. PSTR pszURL;
  502. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  503. pisps = (PISPS)GetWindowLongPtr(hdlg, DWLP_USER);
  504. ASSERT(IS_VALID_STRUCT_PTR(pisps, CISPS));
  505. pintshcut = pisps->pintshcut;
  506. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  507. hr = CopyDlgItemText(hdlg, IDD_URL, &pszURL);
  508. if (SUCCEEDED(hr))
  509. {
  510. PCSTR pcszURLToUse;
  511. PSTR pszTranslatedURL;
  512. pcszURLToUse = pszURL;
  513. if (hr == S_OK)
  514. {
  515. hr = TranslateURL(pszURL, (TRANSLATEURL_FL_GUESS_PROTOCOL |
  516. TRANSLATEURL_FL_USE_DEFAULT_PROTOCOL),
  517. &pszTranslatedURL);
  518. if (SUCCEEDED(hr))
  519. {
  520. if (hr == S_OK)
  521. pcszURLToUse = pszTranslatedURL;
  522. else
  523. ASSERT(hr == S_FALSE);
  524. hr = ValidateURL(pcszURLToUse);
  525. if (FAILED(hr))
  526. {
  527. hr = ComplainAboutURL(hdlg, pcszURLToUse, hr);
  528. if (FAILED(hr))
  529. SetEditFocus(GetDlgItem(hdlg, IDD_URL));
  530. }
  531. }
  532. }
  533. else
  534. {
  535. // A blank URL is OK.
  536. ASSERT(hr == S_FALSE);
  537. pszTranslatedURL = NULL;
  538. }
  539. if (SUCCEEDED(hr))
  540. {
  541. hr = pintshcut->SetURL(pcszURLToUse, 0);
  542. if (hr == S_OK)
  543. {
  544. WORD wHotkey;
  545. WORD wOldHotkey;
  546. // Refresh URL in case it was changed by TranslateURL().
  547. SetISPSURL(hdlg);
  548. wHotkey = (WORD)SendDlgItemMessage(hdlg, IDD_HOTKEY, HKM_GETHOTKEY,
  549. 0, 0);
  550. hr = pintshcut->GetHotkey(&wOldHotkey);
  551. if (hr == S_OK)
  552. {
  553. hr = pintshcut->SetHotkey(wHotkey);
  554. if (hr == S_OK)
  555. {
  556. char szFile[MAX_PATH_LEN];
  557. hr = pintshcut->GetCurFile(szFile, sizeof(szFile));
  558. if (hr == S_OK)
  559. {
  560. if (RegisterGlobalHotkey(wOldHotkey, wHotkey, szFile))
  561. {
  562. PSTR pszWorkingDirectory;
  563. hr = CopyDlgItemText(hdlg, IDD_START_IN,
  564. &pszWorkingDirectory);
  565. if (SUCCEEDED(hr))
  566. {
  567. if (hr == S_OK)
  568. {
  569. hr = ValidateWorkingDirectory(pszWorkingDirectory);
  570. if (FAILED(hr))
  571. hr = ComplainAboutWorkingDirectory(hdlg,
  572. pszWorkingDirectory,
  573. hr);
  574. if (FAILED(hr))
  575. SetEditFocus(GetDlgItem(hdlg, IDD_START_IN));
  576. }
  577. if (SUCCEEDED(hr))
  578. {
  579. hr = pintshcut->SetWorkingDirectory(pszWorkingDirectory);
  580. if (hr == S_OK)
  581. {
  582. // Refresh working directory in case it was changed by
  583. // SetWorkingDirectory().
  584. SetISPSWorkingDirectory(hdlg);
  585. if (pisps->rgchIconFile[0])
  586. hr = pintshcut->SetIconLocation(pisps->rgchIconFile,
  587. pisps->niIcon);
  588. if (hr == S_OK)
  589. {
  590. INT_PTR iShowCmd;
  591. iShowCmd = SendDlgItemMessage(hdlg,
  592. IDD_SHOW_CMD,
  593. CB_GETCURSEL,
  594. 0, 0);
  595. if (iShowCmd >= 0 &&
  596. iShowCmd < ARRAY_ELEMENTS(s_rgnShowCmds))
  597. pintshcut->SetShowCmd(s_rgnShowCmds[iShowCmd]);
  598. else
  599. hr = E_UNEXPECTED;
  600. }
  601. }
  602. }
  603. if (pszWorkingDirectory)
  604. {
  605. delete pszWorkingDirectory;
  606. pszWorkingDirectory = NULL;
  607. }
  608. }
  609. }
  610. else
  611. hr = E_FAIL;
  612. }
  613. }
  614. }
  615. }
  616. }
  617. if (pszURL)
  618. {
  619. delete pszURL;
  620. pszURL = NULL;
  621. }
  622. if (pszTranslatedURL)
  623. {
  624. LocalFree(pszTranslatedURL);
  625. pszTranslatedURL = NULL;
  626. }
  627. }
  628. if (hr == S_OK)
  629. TRACE_OUT(("InjectISPSData(): Injected property sheet data into Internet Shortcut successfully."));
  630. else
  631. WARNING_OUT(("InjectISPSData(): Failed to inject property sheet data into Internet Shortcut, returning %s.",
  632. GetHRESULTString(hr)));
  633. return(hr);
  634. }
  635. PRIVATE_CODE HRESULT ISPSSave(HWND hdlg)
  636. {
  637. HRESULT hr;
  638. PInternetShortcut pintshcut;
  639. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  640. pintshcut = ((PISPS)GetWindowLongPtr(hdlg, DWLP_USER))->pintshcut;
  641. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  642. if (pintshcut->IsDirty() == S_OK)
  643. {
  644. hr = pintshcut->Save((LPCOLESTR)NULL, FALSE);
  645. if (hr == S_OK)
  646. TRACE_OUT(("ISPSSave(): Saved Internet Shortcut successfully."));
  647. else
  648. WARNING_OUT(("ISPSSave(): Save() failed, returning %s.",
  649. GetHRESULTString(hr)));
  650. }
  651. else
  652. {
  653. TRACE_OUT(("ISPSSave(): Internet Shortcut unchanged. No save required."));
  654. hr = S_OK;
  655. }
  656. return(hr);
  657. }
  658. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  659. PRIVATE_CODE BOOL ISPS_Notify(HWND hdlg, WPARAM wparam, LPARAM lparam)
  660. {
  661. BOOL bMsgHandled = FALSE;
  662. // wparam may be any value.
  663. // lparam may be any value.
  664. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  665. switch (((PNMHDR)lparam)->code)
  666. {
  667. case PSN_APPLY:
  668. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, ISPSSave(hdlg) == S_OK ?
  669. PSNRET_NOERROR :
  670. PSNRET_INVALID_NOCHANGEPAGE);
  671. bMsgHandled = TRUE;
  672. break;
  673. case PSN_KILLACTIVE:
  674. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectISPSData(hdlg)));
  675. bMsgHandled = TRUE;
  676. break;
  677. default:
  678. break;
  679. }
  680. return(bMsgHandled);
  681. }
  682. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  683. PRIVATE_CODE PCSTR ISPS_GetHelpFileFromControl(HWND hwndControl)
  684. {
  685. PCSTR pcszHelpFile = NULL;
  686. int nControlID = 0;
  687. ASSERT(! hwndControl ||
  688. IS_VALID_HANDLE(hwndControl, WND));
  689. if (hwndControl)
  690. {
  691. nControlID = GetDlgCtrlID(hwndControl);
  692. switch (nControlID)
  693. {
  694. case IDD_URL_TEXT:
  695. case IDD_URL:
  696. // URL help comes from the Plus! Pack help file.
  697. pcszHelpFile = s_cszPlusHelpFile;
  698. break;
  699. default:
  700. // Other help is borrowed from the default Win95 help file.
  701. break;
  702. }
  703. }
  704. TRACE_OUT(("ISPS_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx).",
  705. pcszHelpFile ? pcszHelpFile : "default Win95 help file",
  706. nControlID,
  707. hwndControl));
  708. ASSERT(! pcszHelpFile ||
  709. IS_VALID_STRING_PTR(pcszHelpFile, CSTR));
  710. return(pcszHelpFile);
  711. }
  712. PRIVATE_CODE INT_PTR CALLBACK ISPS_DlgProc(HWND hdlg, UINT uMsg, WPARAM wparam,
  713. LPARAM lparam)
  714. {
  715. INT_PTR bMsgHandled = FALSE;
  716. // uMsg may be any value.
  717. // wparam may be any value.
  718. // lparam may be any value.
  719. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  720. switch (uMsg)
  721. {
  722. case WM_INITDIALOG:
  723. bMsgHandled = ISPS_InitDialog(hdlg, wparam, lparam);
  724. break;
  725. case WM_DESTROY:
  726. bMsgHandled = ISPS_Destroy(hdlg, wparam, lparam);
  727. break;
  728. case WM_COMMAND:
  729. bMsgHandled = ISPS_Command(hdlg, wparam, lparam);
  730. break;
  731. case WM_NOTIFY:
  732. bMsgHandled = ISPS_Notify(hdlg, wparam, lparam);
  733. break;
  734. case WM_HELP:
  735. SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lparam)->hItemHandle),
  736. ISPS_GetHelpFileFromControl((HWND)(((LPHELPINFO)lparam)->hItemHandle)),
  737. HELP_WM_HELP, (DWORD_PTR)(PVOID)s_rgdwHelpIDs);
  738. bMsgHandled = TRUE;
  739. break;
  740. case WM_CONTEXTMENU:
  741. {
  742. POINT pt;
  743. LPARAM_TO_POINT(lparam, pt);
  744. EVAL(ScreenToClient(hdlg, &pt));
  745. SHWinHelpOnDemandWrap((HWND)wparam,
  746. ISPS_GetHelpFileFromControl(ChildWindowFromPoint(hdlg, pt)),
  747. HELP_CONTEXTMENU, (DWORD_PTR)(PVOID)s_rgdwHelpIDs);
  748. bMsgHandled = TRUE;
  749. break;
  750. }
  751. default:
  752. break;
  753. }
  754. return(bMsgHandled);
  755. }
  756. PRIVATE_CODE HRESULT AddISPS(PInternetShortcut pintshcut,
  757. LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lparam)
  758. {
  759. HRESULT hr;
  760. ISPS isps;
  761. HPROPSHEETPAGE hpsp;
  762. // lparam may be any value.
  763. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CInternetShortcut));
  764. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  765. ZeroMemory(&isps, sizeof(isps));
  766. isps.psp.dwSize = sizeof(isps);
  767. isps.psp.dwFlags = (PSP_DEFAULT | PSP_USECALLBACK);
  768. isps.psp.hInstance = MLGetHinst();
  769. isps.psp.pszTemplate = MAKEINTRESOURCE(DLG_INTERNET_SHORTCUT_PROP_SHEET);
  770. isps.psp.pfnDlgProc = &ISPS_DlgProc;
  771. isps.psp.pfnCallback = &ISPSCallback;
  772. isps.pintshcut = pintshcut;
  773. ASSERT(IS_VALID_STRUCT_PTR(&isps, CISPS));
  774. hpsp = CreatePropertySheetPage(&(isps.psp));
  775. if (hpsp)
  776. {
  777. if ((*pfnAddPage)(hpsp, lparam))
  778. {
  779. pintshcut->AddRef();
  780. hr = S_OK;
  781. TRACE_OUT(("AddISPS(): Added Internet Shortcut property sheet."));
  782. }
  783. else
  784. {
  785. DestroyPropertySheetPage(hpsp);
  786. hr = E_FAIL;
  787. WARNING_OUT(("AddISPS(): Callback to add property sheet failed."));
  788. }
  789. }
  790. else
  791. hr = E_OUTOFMEMORY;
  792. return(hr);
  793. }
  794. /****************************** Public Functions *****************************/
  795. PUBLIC_CODE void SetEditFocus(HWND hwnd)
  796. {
  797. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  798. SetFocus(hwnd);
  799. SendMessage(hwnd, EM_SETSEL, 0, -1);
  800. return;
  801. }
  802. PUBLIC_CODE BOOL ConstructMessageString(PCSTR pcszFormat, PSTR *ppszMsg,
  803. va_list *ArgList)
  804. {
  805. BOOL bResult;
  806. char rgchFormat[MAX_MSG_LEN];
  807. // ArgList may be any value.
  808. ASSERT(! HIWORD(pcszFormat) ||
  809. IS_VALID_STRING_PTR(pcszFormat, CSTR));
  810. ASSERT(IS_VALID_WRITE_PTR(ppszMsg, PSTR));
  811. if (IS_INTRESOURCE(pcszFormat))
  812. {
  813. MLLoadStringA(LOWORD(PtrToUlong(pcszFormat)), rgchFormat,
  814. sizeof(rgchFormat));
  815. pcszFormat = rgchFormat;
  816. }
  817. bResult = FormatMessage((FORMAT_MESSAGE_ALLOCATE_BUFFER |
  818. FORMAT_MESSAGE_FROM_STRING), pcszFormat, 0, 0,
  819. (PSTR)ppszMsg, 0, ArgList);
  820. ASSERT(! bResult ||
  821. IS_VALID_STRING_PTR(*ppszMsg, STR));
  822. return(bResult);
  823. }
  824. PUBLIC_CODE BOOL __cdecl MyMsgBox(HWND hwndParent, PCSTR pcszTitle,
  825. PCSTR pcszMsgFormat, DWORD dwMsgBoxFlags,
  826. PINT pnResult, ...)
  827. {
  828. BOOL bResult;
  829. va_list ArgList;
  830. PSTR pszMsg;
  831. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  832. ASSERT(IS_INTRESOURCE(pcszTitle) ||
  833. IS_VALID_STRING_PTR(pcszTitle, CSTR));
  834. ASSERT(IS_INTRESOURCE(pcszMsgFormat) ||
  835. IS_VALID_STRING_PTR(pcszMsgFormat, CSTR));
  836. ASSERT(FLAGS_ARE_VALID(dwMsgBoxFlags, ALL_MSG_BOX_FLAGS));
  837. ASSERT(IS_VALID_WRITE_PTR(pnResult, INT));
  838. *pnResult = 0;
  839. va_start(ArgList, pnResult);
  840. bResult = ConstructMessageString(pcszMsgFormat, &pszMsg, &ArgList);
  841. va_end(ArgList);
  842. if (bResult)
  843. {
  844. char rgchTitle[MAX_MSG_LEN];
  845. if (! HIWORD(pcszTitle))
  846. {
  847. MLLoadStringA(LOWORD(PtrToUlong(pcszTitle)), rgchTitle,
  848. sizeof(rgchTitle));
  849. pcszTitle = rgchTitle;
  850. }
  851. *pnResult = MessageBox(hwndParent, pszMsg, pcszTitle, dwMsgBoxFlags);
  852. bResult = (*pnResult != 0);
  853. LocalFree(pszMsg);
  854. pszMsg = NULL;
  855. }
  856. return(bResult);
  857. }
  858. PUBLIC_CODE HRESULT CopyDlgItemText(HWND hdlg, int nControlID, PSTR *ppszText)
  859. {
  860. HRESULT hr;
  861. HWND hwndControl;
  862. // nContolID may be any value.
  863. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  864. ASSERT(IS_VALID_WRITE_PTR(ppszText, PSTR));
  865. *ppszText = NULL;
  866. hwndControl = GetDlgItem(hdlg, nControlID);
  867. if (hwndControl)
  868. {
  869. int ncchTextLen;
  870. ncchTextLen = GetWindowTextLength(hwndControl);
  871. if (ncchTextLen > 0)
  872. {
  873. PSTR pszText;
  874. ASSERT(ncchTextLen < INT_MAX);
  875. ncchTextLen++;
  876. ASSERT(ncchTextLen > 0);
  877. pszText = new(char[ncchTextLen]);
  878. if (pszText)
  879. {
  880. int ncchCopiedLen;
  881. ncchCopiedLen = GetWindowText(hwndControl, pszText, ncchTextLen);
  882. ASSERT(ncchCopiedLen == ncchTextLen - 1);
  883. if (EVAL(ncchCopiedLen > 0))
  884. {
  885. if (AnyMeat(pszText))
  886. {
  887. *ppszText = pszText;
  888. hr = S_OK;
  889. }
  890. else
  891. hr = S_FALSE;
  892. }
  893. else
  894. hr = E_FAIL;
  895. if (hr != S_OK)
  896. {
  897. delete pszText;
  898. pszText = NULL;
  899. }
  900. }
  901. else
  902. hr = E_OUTOFMEMORY;
  903. }
  904. else
  905. // No text.
  906. hr = S_FALSE;
  907. }
  908. else
  909. hr = E_FAIL;
  910. return(hr);
  911. }
  912. PUBLIC_CODE BOOL RegisterGlobalHotkey(WORD wOldHotkey, WORD wNewHotkey,
  913. PCSTR pcszPath)
  914. {
  915. BOOL bResult;
  916. HWND hwndTray;
  917. ASSERT(! wOldHotkey ||
  918. IsValidHotkey(wOldHotkey));
  919. ASSERT(! wNewHotkey ||
  920. IsValidHotkey(wNewHotkey));
  921. ASSERT(IsValidPath(pcszPath));
  922. hwndTray = FindWindow(s_cszTrayNotificationClass, 0);
  923. if (hwndTray)
  924. {
  925. if (wOldHotkey)
  926. {
  927. SendMessage(hwndTray, WMTRAY_SCUNREGISTERHOTKEY, wOldHotkey, 0);
  928. TRACE_OUT(("RegisterGlobalHotkey(): Unregistered old hotkey %#04x for %s.",
  929. wOldHotkey,
  930. pcszPath));
  931. }
  932. if (wNewHotkey)
  933. {
  934. if (RUNNING_NT)
  935. {
  936. ATOM atom = GlobalAddAtom(pcszPath);
  937. ASSERT(atom);
  938. if (atom)
  939. {
  940. SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey, (LPARAM)atom);
  941. GlobalDeleteAtom(atom);
  942. }
  943. }
  944. else
  945. {
  946. SendMessage(hwndTray, WMTRAY_SCREGISTERHOTKEY, wNewHotkey,
  947. (LPARAM)pcszPath);
  948. }
  949. TRACE_OUT(("RegisterGlobalHotkey(): Registered new hotkey %#04x for %s.",
  950. wNewHotkey,
  951. pcszPath));
  952. }
  953. bResult = TRUE;
  954. }
  955. else
  956. {
  957. bResult = FALSE;
  958. WARNING_OUT(("RegisterGlobalHotkey(): Unable to find Tray window of class %s to notify.",
  959. s_cszTrayNotificationClass));
  960. }
  961. return(bResult);
  962. }
  963. /********************************** Methods **********************************/
  964. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  965. HRESULT STDMETHODCALLTYPE InternetShortcut::Initialize(
  966. PCITEMIDLIST pcidlFolder,
  967. PIDataObject pido,
  968. HKEY hkeyProgID)
  969. {
  970. HRESULT hr;
  971. FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  972. STGMEDIUM stgmed;
  973. DebugEntry(InternetShortcut::Initialize);
  974. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  975. ASSERT(! pcidlFolder ||
  976. IS_VALID_STRUCT_PTR(pcidlFolder, CITEMIDLIST));
  977. ASSERT(IS_VALID_INTERFACE_PTR(pido, IDataObject));
  978. ASSERT(IS_VALID_HANDLE(hkeyProgID, KEY));
  979. hr = pido->GetData(&fmtetc, &stgmed);
  980. if (hr == S_OK)
  981. {
  982. UINT ucbPathLen;
  983. PSTR pszFile;
  984. // (+ 1) for null terminator.
  985. ucbPathLen = DragQueryFile((HDROP)(stgmed.hGlobal), 0, NULL, 0) + 1;
  986. ASSERT(ucbPathLen > 0);
  987. pszFile = new(char[ucbPathLen]);
  988. if (pszFile)
  989. {
  990. EVAL(DragQueryFile((HDROP)(stgmed.hGlobal), 0, pszFile, ucbPathLen) == ucbPathLen - 1);
  991. ASSERT(IS_VALID_STRING_PTR(pszFile, STR));
  992. ASSERT((UINT)lstrlen(pszFile) == ucbPathLen - 1);
  993. hr = LoadFromFile(pszFile, TRUE);
  994. delete pszFile;
  995. pszFile = NULL;
  996. }
  997. else
  998. hr = E_OUTOFMEMORY;
  999. if (stgmed.tymed != TYMED_NULL)
  1000. MyReleaseStgMedium(&stgmed);
  1001. }
  1002. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1003. DebugExitHRESULT(InternetShortcut::Initialize, hr);
  1004. return(hr);
  1005. }
  1006. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  1007. HRESULT STDMETHODCALLTYPE InternetShortcut::AddPages(
  1008. LPFNADDPROPSHEETPAGE pfnAddPage,
  1009. LPARAM lparam)
  1010. {
  1011. HRESULT hr;
  1012. DebugEntry(InternetShortcut::AddPages);
  1013. // lparam may be any value.
  1014. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1015. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  1016. hr = AddISPS(this, pfnAddPage, lparam);
  1017. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1018. DebugExitHRESULT(InternetShortcut::AddPages, hr);
  1019. return(hr);
  1020. }
  1021. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  1022. HRESULT STDMETHODCALLTYPE InternetShortcut::ReplacePage(
  1023. UINT uPageID,
  1024. LPFNADDPROPSHEETPAGE pfnReplaceWith,
  1025. LPARAM lparam)
  1026. {
  1027. HRESULT hr;
  1028. DebugEntry(InternetShortcut::ReplacePage);
  1029. // lparam may be any value.
  1030. // uPageID may be any value.
  1031. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1032. ASSERT(IS_VALID_CODE_PTR(pfnReplaceWith, LPFNADDPROPSHEETPAGE));
  1033. hr = E_NOTIMPL;
  1034. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  1035. DebugExitHRESULT(InternetShortcut::ReplacePage, hr);
  1036. return(hr);
  1037. }
  1038. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */