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.

1802 lines
44 KiB

  1. /*
  2. * isprsht.cpp - IPropSheetExt implementation for URL class.
  3. */
  4. #include "priv.h"
  5. #include "ishcut.h"
  6. #include <limits.h>
  7. #include <trayp.h> // for WMTRAY_ messages
  8. #include <ntverp.h> // VER_XXX for FaultInFeature
  9. #include <webcheck.h> // ISubscriptionMgrPriv
  10. #include <mluisupp.h>
  11. #undef NO_HELP // for help.h
  12. #include "resource.h"
  13. #include <iehelpid.h>
  14. #ifndef UNIX
  15. const WCHAR c_szPropCrawlActualSize[] = L"ActualSizeKB";
  16. const WCHAR c_szPropStatusString[] = L"StatusString";
  17. const WCHAR c_szPropCompletionTime[] = L"CompletionTime";
  18. #else
  19. #include "unixstuff.h"
  20. #include "shalias.h"
  21. const LPCWSTR c_szPropCrawlActualSize = L"ActualSizeKB";
  22. const LPCWSTR c_szPropStatusString = L"StatusString";
  23. const LPCWSTR c_szPropCompletionTime = L"CompletionTime";
  24. #endif
  25. #include "apithk.h"
  26. /* stuff a point value packed in an LPARAM into a POINT */
  27. #define LPARAM_TO_POINT(lParam, pt) ((pt).x = GET_X_LPARAM(lParam), \
  28. (pt).y = GET_Y_LPARAM(lParam))
  29. #define ISF_STARTSUBSCRIBED 0x00010000 // URL was subscribed to start with
  30. #define ISF_NOWEBCHECK 0x00020000 // Webcheck is not installed
  31. #define ISF_DISABLEOFFLINE 0x00080000 // Disable "make available offline" menus/checkboxes
  32. #define ISF_SUMMARYEXTRACTED 0x00100000 // Has the summary been extracted
  33. #define ISF_HAVEINITED 0x00200000 // Has the subsmgr extension been inited?
  34. /* Internet Shortcut property sheet data */
  35. /*
  36. Mental note(tnoonan): this helper class should be shared with the context menu
  37. code soon.
  38. */
  39. class CSubsHelper
  40. {
  41. IUniformResourceLocatorW *m_pIURLW;
  42. ISubscriptionMgr2 *m_pSubsMgr2;
  43. HINSTANCE m_hinstWebcheck;
  44. HWND m_hwndParent;
  45. public:
  46. DWORD m_dwFlags;
  47. ~CSubsHelper()
  48. {
  49. if (NULL != m_pSubsMgr2)
  50. {
  51. m_pSubsMgr2->Release();
  52. }
  53. if (NULL != m_pIURLW)
  54. {
  55. m_pIURLW->Release();
  56. }
  57. if (NULL != m_hinstWebcheck)
  58. {
  59. FreeLibrary(m_hinstWebcheck);
  60. }
  61. }
  62. void SetParentHwnd(HWND hwndParent)
  63. {
  64. m_hwndParent = hwndParent;
  65. }
  66. void SetIURLW(IUniformResourceLocatorW *pIURLW)
  67. {
  68. if (NULL != m_pIURLW)
  69. {
  70. m_pIURLW->Release();
  71. }
  72. if (NULL != pIURLW)
  73. {
  74. pIURLW->AddRef();
  75. }
  76. m_pIURLW = pIURLW;
  77. }
  78. HRESULT GetIURLW(IUniformResourceLocatorW **ppIURLW)
  79. {
  80. HRESULT hr;
  81. ASSERT(NULL != ppIURLW);
  82. if (NULL != m_pIURLW)
  83. {
  84. m_pIURLW->AddRef();
  85. *ppIURLW = m_pIURLW;
  86. hr = S_OK;
  87. }
  88. else
  89. {
  90. *ppIURLW = NULL;
  91. hr = E_FAIL;
  92. }
  93. return hr;
  94. }
  95. HRESULT Init()
  96. {
  97. HRESULT hr;
  98. WCHAR *pwszURL;
  99. ASSERT(NULL != m_pIURLW);
  100. hr = m_pIURLW->GetURL(&pwszURL);
  101. if (SUCCEEDED(hr))
  102. {
  103. hr = LoadSubsMgr2(FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
  104. if (SUCCEEDED(hr))
  105. {
  106. BOOL bSubscribed;
  107. if (SUCCEEDED(m_pSubsMgr2->IsSubscribed(pwszURL, &bSubscribed)) &&
  108. (TRUE == bSubscribed))
  109. {
  110. m_dwFlags |= ISF_STARTSUBSCRIBED;
  111. }
  112. }
  113. if (m_dwFlags & ISF_STARTSUBSCRIBED)
  114. {
  115. if (SHRestricted2W(REST_NoRemovingSubscriptions, pwszURL, 0))
  116. {
  117. m_dwFlags |= ISF_DISABLEOFFLINE;
  118. }
  119. }
  120. else
  121. {
  122. if (SHRestricted2W(REST_NoAddingSubscriptions, pwszURL, 0))
  123. {
  124. m_dwFlags |= ISF_DISABLEOFFLINE;
  125. }
  126. }
  127. SHFree(pwszURL);
  128. }
  129. return hr;
  130. }
  131. HRESULT LoadSubsMgr2(DWORD dwFaultInFlags)
  132. {
  133. HRESULT hr;
  134. uCLSSPEC ucs;
  135. QUERYCONTEXT qc = { 0 };
  136. ucs.tyspec = TYSPEC_CLSID;
  137. ucs.tagged_union.clsid = CLSID_SubscriptionMgr;
  138. hr = FaultInIEFeature(m_hwndParent, &ucs, &qc, dwFaultInFlags);
  139. if (SUCCEEDED(hr))
  140. {
  141. m_dwFlags &= ~ISF_NOWEBCHECK;
  142. }
  143. else
  144. {
  145. m_dwFlags |= ISF_NOWEBCHECK;
  146. if (E_ACCESSDENIED == hr)
  147. {
  148. // Admin has disabled demand install
  149. m_dwFlags |= ISF_DISABLEOFFLINE;
  150. }
  151. }
  152. if (!(m_dwFlags & ISF_NOWEBCHECK))
  153. {
  154. ASSERT(NULL == m_pSubsMgr2)
  155. // HACKHACKHACK
  156. hr = CoInitialize(NULL);
  157. if (SUCCEEDED(hr))
  158. {
  159. m_hinstWebcheck = SHPinDllOfCLSID(&CLSID_SubscriptionMgr);
  160. if (NULL != m_hinstWebcheck)
  161. {
  162. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  163. IID_PPV_ARG(ISubscriptionMgr2, &m_pSubsMgr2));
  164. }
  165. else
  166. {
  167. m_dwFlags |= ISF_NOWEBCHECK;
  168. hr = E_FAIL;
  169. }
  170. // HACKHACKHACK
  171. CoUninitialize();
  172. }
  173. }
  174. return hr;
  175. }
  176. HRESULT GetSubsMgr2(ISubscriptionMgr2 **ppSubsMgr2, DWORD dwFaultInFlags)
  177. {
  178. HRESULT hr = E_FAIL;
  179. ASSERT(NULL != ppSubsMgr2);
  180. *ppSubsMgr2 = NULL;
  181. if ((NULL == m_pSubsMgr2) && (0xffffffff != dwFaultInFlags))
  182. {
  183. hr = LoadSubsMgr2(dwFaultInFlags);
  184. }
  185. if (NULL != m_pSubsMgr2)
  186. {
  187. m_pSubsMgr2->AddRef();
  188. *ppSubsMgr2 = m_pSubsMgr2;
  189. hr = S_OK;
  190. }
  191. return hr;
  192. }
  193. HRESULT DeleteSubscription()
  194. {
  195. HRESULT hr = S_FALSE;
  196. if (m_pSubsMgr2)
  197. {
  198. WCHAR *pwszURL;
  199. ASSERT(NULL != m_pIURLW);
  200. hr = m_pIURLW->GetURL(&pwszURL);
  201. if (SUCCEEDED(hr))
  202. {
  203. hr = m_pSubsMgr2->DeleteSubscription(pwszURL, NULL);
  204. SHFree(pwszURL);
  205. }
  206. }
  207. return hr;
  208. }
  209. HRESULT SaveSubscription()
  210. {
  211. HRESULT hr;
  212. #ifndef UNIX
  213. ISubscriptionMgrPriv *psmp;
  214. if (m_pSubsMgr2)
  215. {
  216. hr = m_pSubsMgr2->QueryInterface(IID_PPV_ARG(ISubscriptionMgrPriv, &psmp));
  217. if (SUCCEEDED(hr))
  218. {
  219. hr = psmp->SaveSubscription();
  220. psmp->Release();
  221. }
  222. }
  223. else
  224. #endif
  225. {
  226. hr = E_FAIL;
  227. }
  228. return hr;
  229. }
  230. HRESULT UpdateSubscription()
  231. {
  232. HRESULT hr;
  233. if (m_pSubsMgr2)
  234. {
  235. WCHAR *pwszURL;
  236. ASSERT(NULL != m_pIURLW);
  237. hr = m_pIURLW->GetURL(&pwszURL);
  238. if (SUCCEEDED(hr))
  239. {
  240. hr = m_pSubsMgr2->UpdateSubscription(pwszURL);
  241. SHFree(pwszURL);
  242. }
  243. }
  244. else
  245. {
  246. hr = E_FAIL;
  247. }
  248. return hr;
  249. }
  250. HRESULT DoShellExtInit(IDataObject *pdo)
  251. {
  252. HRESULT hr = E_FAIL;
  253. if (NULL != m_pSubsMgr2)
  254. {
  255. if (!(m_dwFlags & ISF_HAVEINITED))
  256. {
  257. IShellExtInit *psei;
  258. hr = m_pSubsMgr2->QueryInterface(IID_PPV_ARG(IShellExtInit, &psei));
  259. if (SUCCEEDED(hr))
  260. {
  261. hr = psei->Initialize(NULL, pdo, NULL);
  262. if (SUCCEEDED(hr))
  263. {
  264. m_dwFlags |= ISF_HAVEINITED;
  265. }
  266. psei->Release();
  267. }
  268. }
  269. else
  270. {
  271. hr = S_FALSE;
  272. }
  273. }
  274. return hr;
  275. }
  276. };
  277. struct ISDATA
  278. {
  279. private:
  280. Intshcut *m_pintshcut;
  281. public:
  282. TCHAR rgchIconFile[MAX_PATH];
  283. int niIcon;
  284. CSubsHelper SubsHelper;
  285. BOOL bUserEditedPage;
  286. inline void SetIntshcut(Intshcut *pintshcut)
  287. {
  288. IUniformResourceLocatorW *pIURLW;
  289. ASSERT(NULL == m_pintshcut);
  290. ASSERT(NULL != pintshcut);
  291. pintshcut->AddRef();
  292. if (SUCCEEDED(pintshcut->QueryInterface(IID_PPV_ARG(IUniformResourceLocatorW, &pIURLW))))
  293. {
  294. SubsHelper.SetIURLW(pIURLW);
  295. pIURLW->Release();
  296. }
  297. m_pintshcut = pintshcut;
  298. }
  299. inline Intshcut *GetIntshcut() const
  300. {
  301. ASSERT(NULL != m_pintshcut);
  302. return m_pintshcut;
  303. }
  304. ~ISDATA()
  305. {
  306. if (NULL != m_pintshcut)
  307. {
  308. m_pintshcut->Release();
  309. }
  310. }
  311. };
  312. typedef ISDATA *PISDATA;
  313. #ifdef DEBUG
  314. BOOL
  315. IsValidPISDATA(
  316. PISDATA pisdata)
  317. {
  318. return(IS_VALID_READ_PTR(pisdata, ISDATA) &&
  319. IS_VALID_STRUCT_PTR(pisdata->GetIntshcut(), CIntshcut) &&
  320. EVAL(IsValidIconIndex(*(pisdata->rgchIconFile) ? S_OK : S_FALSE, pisdata->rgchIconFile, SIZECHARS(pisdata->rgchIconFile), pisdata->niIcon)));
  321. }
  322. PISDATA ISPS_GetPISDATA(HWND hdlg)
  323. {
  324. PISDATA pd = (PISDATA) GetWindowLongPtr(hdlg, DWLP_USER);
  325. IS_VALID_STRUCT_PTR(pd, ISDATA);
  326. return pd;
  327. }
  328. Intshcut *ISPS_GetThisPtr(HWND hdlg)
  329. {
  330. Intshcut *pintshcut = ISPS_GetPISDATA(hdlg)->GetIntshcut();
  331. IS_VALID_STRUCT_PTR(pintshcut, CIntshcut);
  332. return pintshcut;
  333. }
  334. #else
  335. #define ISPS_GetPISDATA(hdlg) ((PISDATA)GetWindowLongPtr(hdlg, DWLP_USER))
  336. #define ISPS_GetThisPtr(hdlg) (ISPS_GetPISDATA(hdlg)->GetIntshcut())
  337. #endif
  338. // help files
  339. TCHAR const s_cszIEHelpFile[] = TEXT("iexplore.hlp");
  340. // help topics
  341. DWORD const c_rgdwHelpIDs[] =
  342. {
  343. IDC_ICON, IDH_FCAB_LINK_ICON,
  344. IDC_NAME, IDH_FCAB_LINK_NAME,
  345. IDC_URL_TEXT, IDH_SUBPROPS_SUBTAB_SUBSCRIBED_URL,
  346. IDC_URL, IDH_SUBPROPS_SUBTAB_SUBSCRIBED_URL,
  347. IDC_HOTKEY_TEXT, IDH_FCAB_LINK_HOTKEY,
  348. IDC_HOTKEY, IDH_FCAB_LINK_HOTKEY,
  349. IDC_CHANGE_ICON, IDH_FCAB_LINK_CHANGEICON,
  350. IDC_VISITS_TEXT, IDH_WEBDOC_VISITS,
  351. IDC_VISITS, IDH_WEBDOC_VISITS,
  352. IDC_MAKE_OFFLINE, IDH_MAKE_AVAIL_OFFLINE,
  353. IDC_SUMMARY, IDH_GROUPBOX,
  354. IDC_LAST_SYNC_TEXT, IDH_SUBPROPS_SUBTAB_LAST,
  355. IDC_LAST_SYNC, IDH_SUBPROPS_SUBTAB_LAST,
  356. IDC_DOWNLOAD_SIZE_TEXT, IDH_SUBPROPS_DLSIZE,
  357. IDC_DOWNLOAD_SIZE, IDH_SUBPROPS_DLSIZE,
  358. IDC_DOWNLOAD_RESULT_TEXT, IDH_SUBPROPS_SUBTAB_RESULT,
  359. IDC_DOWNLOAD_RESULT, IDH_SUBPROPS_SUBTAB_RESULT,
  360. 0, 0
  361. };
  362. /***************************** Private Functions *****************************/
  363. void SetEditFocus(HWND hwnd)
  364. {
  365. SetFocus(hwnd);
  366. Edit_SetSel(hwnd, 0, -1);
  367. }
  368. #define SetDlgCtlText SetDlgItemTextW
  369. UINT
  370. CALLBACK
  371. ISPSCallback(
  372. HWND hwnd,
  373. UINT uMsg,
  374. LPPROPSHEETPAGE ppsp)
  375. {
  376. UINT uResult = TRUE;
  377. PISDATA pisdata = (PISDATA)ppsp->lParam;
  378. // uMsg may be any value.
  379. ASSERT(! hwnd ||
  380. IS_VALID_HANDLE(hwnd, WND));
  381. switch (uMsg)
  382. {
  383. case PSPCB_CREATE:
  384. break;
  385. case PSPCB_RELEASE:
  386. TraceMsg(TF_INTSHCUT, "ISPSCallback(): Received PSPCB_RELEASE.");
  387. if (pisdata)
  388. {
  389. delete pisdata;
  390. }
  391. break;
  392. default:
  393. break;
  394. }
  395. return(uResult);
  396. }
  397. HRESULT
  398. CopyDlgItemText(
  399. HWND hdlg,
  400. int nControlID,
  401. TCHAR * UNALIGNED * ppszText)
  402. {
  403. HRESULT hr;
  404. HWND hwndControl;
  405. // nContolID may be any value.
  406. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  407. ASSERT(IS_VALID_WRITE_PTR(ppszText, PTSTR));
  408. *ppszText = NULL;
  409. hwndControl = GetDlgItem(hdlg, nControlID);
  410. if (hwndControl)
  411. {
  412. int cchTextLen;
  413. cchTextLen = GetWindowTextLength(hwndControl);
  414. if (cchTextLen > 0)
  415. {
  416. LPTSTR pszText;
  417. ASSERT(cchTextLen < INT_MAX);
  418. cchTextLen++;
  419. ASSERT(cchTextLen > 0);
  420. pszText = (LPTSTR)LocalAlloc(LPTR, CbFromCch(cchTextLen));
  421. if (pszText)
  422. {
  423. int ncchCopiedLen;
  424. ncchCopiedLen = GetWindowText(hwndControl, pszText, cchTextLen);
  425. ASSERT(ncchCopiedLen == cchTextLen - 1);
  426. if (EVAL(ncchCopiedLen > 0))
  427. {
  428. if (AnyMeat(pszText))
  429. {
  430. *ppszText = pszText;
  431. hr = S_OK;
  432. }
  433. else
  434. hr = S_FALSE;
  435. }
  436. else
  437. hr = E_FAIL;
  438. if (hr != S_OK)
  439. {
  440. LocalFree(pszText);
  441. pszText = NULL;
  442. }
  443. }
  444. else
  445. hr = E_OUTOFMEMORY;
  446. }
  447. else
  448. // No text.
  449. hr = S_FALSE;
  450. }
  451. else
  452. hr = E_FAIL;
  453. return(hr);
  454. }
  455. void
  456. SetISPSIcon(
  457. HWND hdlg,
  458. HICON hicon)
  459. {
  460. HICON hiconOld;
  461. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  462. ASSERT(IS_VALID_HANDLE(hicon, ICON));
  463. hiconOld = (HICON)SendDlgItemMessage(hdlg, IDC_ICON, STM_SETICON,
  464. (WPARAM)hicon, 0);
  465. if (hiconOld)
  466. DestroyIcon(hiconOld);
  467. TraceMsg(TF_INTSHCUT, "SetISPSIcon(): Set property sheet icon to %#lx.",
  468. hicon);
  469. return;
  470. }
  471. void
  472. SetISPSFileNameAndIcon(
  473. HWND hdlg)
  474. {
  475. HRESULT hr;
  476. PIntshcut pintshcut;
  477. TCHAR rgchFile[MAX_PATH];
  478. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  479. pintshcut = ISPS_GetThisPtr(hdlg);
  480. hr = pintshcut->GetCurFile(rgchFile, SIZECHARS(rgchFile));
  481. if (hr == S_OK)
  482. {
  483. SHFILEINFO shfi;
  484. DWORD_PTR dwResult;
  485. dwResult = SHGetFileInfo(rgchFile, 0, &shfi, SIZEOF(shfi),
  486. (SHGFI_DISPLAYNAME | SHGFI_ICON));
  487. if (dwResult)
  488. {
  489. LPTSTR pszFileName;
  490. pszFileName = (PTSTR)PathFindFileName(shfi.szDisplayName);
  491. EVAL(SetDlgItemText(hdlg, IDC_NAME, pszFileName));
  492. SetISPSIcon(hdlg, shfi.hIcon);
  493. }
  494. else
  495. {
  496. hr = E_FAIL;
  497. TraceMsg(TF_INTSHCUT, "SetISPSFileNameAndIcon(): SHGetFileInfo() failed, returning %lu.",
  498. dwResult);
  499. }
  500. }
  501. else
  502. TraceMsg(TF_INTSHCUT, "SetISPSFileNameAndIcon(): GetCurFile() failed, returning %s.",
  503. Dbg_GetHRESULTName(hr));
  504. if (hr != S_OK)
  505. EVAL(SetDlgItemText(hdlg, IDC_NAME, c_szNULL));
  506. return;
  507. }
  508. void
  509. SetISPSURL(
  510. HWND hdlg,
  511. BOOL *pbSubscribable)
  512. {
  513. PIntshcut pintshcut;
  514. HRESULT hr;
  515. PTSTR pszURL;
  516. *pbSubscribable = FALSE;
  517. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  518. pintshcut = ISPS_GetThisPtr(hdlg);
  519. hr = pintshcut->GetURL(&pszURL);
  520. if (hr == S_OK)
  521. {
  522. TCHAR szVisits[256];
  523. EVAL(SetDlgItemText(hdlg, IDC_URL, pszURL));
  524. TraceMsg(TF_INTSHCUT, "SetISPSURL(): Set property sheet URL to \"%s\".",
  525. pszURL);
  526. *pbSubscribable = IsSubscribable(pszURL);
  527. BYTE cei[MAX_CACHE_ENTRY_INFO_SIZE];
  528. LPINTERNET_CACHE_ENTRY_INFO pcei = (LPINTERNET_CACHE_ENTRY_INFO)cei;
  529. DWORD cbcei = MAX_CACHE_ENTRY_INFO_SIZE;
  530. #ifdef UNIX_FEATURE_ALIAS
  531. {
  532. HDPA aliasList = GetGlobalAliasList();
  533. if( aliasList )
  534. {
  535. #ifdef UNICODE
  536. // TODO :
  537. #else
  538. CHAR szAlias[ MAX_ALIAS_LENGTH ];
  539. if(FindAliasByURLA( aliasList, pszURL, szAlias, sizeof(szAlias) ) )
  540. SetDlgItemText(hdlg, IDC_ALIAS_NAME, szAlias);
  541. #endif
  542. }
  543. }
  544. #endif /* UNIX_FEATURE_ALIAS */
  545. if (GetUrlCacheEntryInfo(pszURL, pcei, &cbcei))
  546. {
  547. wnsprintf(szVisits, ARRAYSIZE(szVisits), TEXT("%d"), pcei->dwHitRate);
  548. }
  549. else
  550. {
  551. MLLoadString(IDS_VALUE_UNKNOWN, szVisits, ARRAYSIZE(szVisits));
  552. }
  553. EVAL(SetDlgItemText(hdlg, IDC_VISITS, szVisits));
  554. SHFree(pszURL);
  555. pszURL = NULL;
  556. }
  557. else
  558. EVAL(SetDlgItemText(hdlg, IDC_URL, c_szNULL));
  559. return;
  560. }
  561. void
  562. InitISPSHotkey(
  563. HWND hdlg)
  564. {
  565. PIntshcut pintshcut;
  566. WORD wHotkey;
  567. HRESULT hr;
  568. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  569. // Set hotkey combinations.
  570. SendDlgItemMessage(hdlg, IDC_HOTKEY, HKM_SETRULES,
  571. (HKCOMB_NONE | HKCOMB_A | HKCOMB_C | HKCOMB_S),
  572. (HOTKEYF_CONTROL | HOTKEYF_ALT));
  573. // Set current hotkey.
  574. pintshcut = ISPS_GetThisPtr(hdlg);
  575. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  576. hr = pintshcut->GetHotkey(&wHotkey);
  577. SendDlgItemMessage(hdlg, IDC_HOTKEY, HKM_SETHOTKEY, wHotkey, 0);
  578. return;
  579. }
  580. void ISPS_ShowOfflineSummary(HWND hdlg, BOOL bShow, PISDATA pisdata)
  581. {
  582. static const int offSumIDs[] =
  583. {
  584. IDC_SUMMARY,
  585. IDC_LAST_SYNC_TEXT,
  586. IDC_LAST_SYNC,
  587. IDC_DOWNLOAD_SIZE_TEXT,
  588. IDC_DOWNLOAD_SIZE,
  589. IDC_DOWNLOAD_RESULT,
  590. IDC_DOWNLOAD_RESULT_TEXT,
  591. IDC_FREESPACE_TEXT
  592. };
  593. if (bShow)
  594. {
  595. IUniformResourceLocatorW *pIURLW;
  596. TCHAR szLastSync[128];
  597. TCHAR szDownloadSize[128];
  598. TCHAR szDownloadResult[128];
  599. MLLoadString(IDS_VALUE_UNKNOWN, szLastSync, ARRAYSIZE(szLastSync));
  600. StrCpyN(szDownloadSize, szLastSync, ARRAYSIZE(szDownloadSize));
  601. StrCpyN(szDownloadResult, szLastSync, ARRAYSIZE(szDownloadResult));
  602. if (SUCCEEDED(pisdata->SubsHelper.GetIURLW(&pIURLW)))
  603. {
  604. WCHAR *pwszURL;
  605. if (SUCCEEDED(pIURLW->GetURL(&pwszURL)))
  606. {
  607. ISubscriptionMgr2 *pSubsMgr2;
  608. if (SUCCEEDED(pisdata->SubsHelper.GetSubsMgr2(&pSubsMgr2, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI)))
  609. {
  610. ISubscriptionItem *psi;
  611. if (SUCCEEDED(pSubsMgr2->GetItemFromURL(pwszURL, &psi)))
  612. {
  613. enum { spLastSync, spDownloadSize, spDownloadResult };
  614. static const LPCWSTR pProps[] =
  615. {
  616. c_szPropCompletionTime,
  617. c_szPropCrawlActualSize,
  618. c_szPropStatusString
  619. };
  620. VARIANT vars[ARRAYSIZE(pProps)];
  621. if (SUCCEEDED(psi->ReadProperties(ARRAYSIZE(pProps), pProps, vars)))
  622. {
  623. if (VT_DATE == vars[spLastSync].vt)
  624. {
  625. FILETIME ft, ft2;
  626. DWORD dwFlags = FDTF_DEFAULT;
  627. SYSTEMTIME st;
  628. if (VariantTimeToSystemTime(vars[spLastSync].date, &st))
  629. {
  630. SystemTimeToFileTime(&st, &ft);
  631. LocalFileTimeToFileTime(&ft, &ft2);
  632. SHFormatDateTime(&ft2, &dwFlags, szLastSync, ARRAYSIZE(szLastSync));
  633. }
  634. }
  635. if (VT_I4 == vars[spDownloadSize].vt)
  636. {
  637. StrFormatByteSize(vars[spDownloadSize].lVal * 1024,
  638. szDownloadSize, ARRAYSIZE(szDownloadSize));
  639. }
  640. if (VT_BSTR == vars[spDownloadResult].vt)
  641. {
  642. wnsprintf(szDownloadResult, ARRAYSIZE(szDownloadResult),
  643. TEXT("%s"), vars[spDownloadResult].bstrVal);
  644. }
  645. for (int i = 0; i < ARRAYSIZE(pProps); i++)
  646. {
  647. VariantClear(&vars[i]);
  648. }
  649. }
  650. psi->Release();
  651. }
  652. pSubsMgr2->Release();
  653. }
  654. SHFree(pwszURL);
  655. }
  656. pIURLW->Release();
  657. }
  658. EVAL(SetDlgItemText(hdlg, IDC_LAST_SYNC, szLastSync));
  659. EVAL(SetDlgItemText(hdlg, IDC_DOWNLOAD_SIZE, szDownloadSize));
  660. EVAL(SetDlgItemText(hdlg, IDC_DOWNLOAD_RESULT, szDownloadResult));
  661. }
  662. for (int i = 0; i < ARRAYSIZE(offSumIDs); i++)
  663. {
  664. ShowWindow(GetDlgItem(hdlg, offSumIDs[i]), bShow ? SW_SHOW : SW_HIDE);
  665. }
  666. }
  667. BOOL ISPS_AddSubsPropsCallback(HPROPSHEETPAGE hpage, LPARAM lParam)
  668. {
  669. return BOOLFROMPTR(PropSheet_AddPage((HWND)lParam, hpage));
  670. }
  671. STDMETHODIMP ISPS_AddSubsProps(HWND hdlg, ISubscriptionMgr2 *pSubsMgr2, PISDATA pisdata)
  672. {
  673. HRESULT hr = S_OK;
  674. IShellPropSheetExt *pspse;
  675. ASSERT(NULL != pisdata);
  676. ASSERT(NULL != pSubsMgr2);
  677. hr = pisdata->SubsHelper.DoShellExtInit(pisdata->GetIntshcut()->GetInitDataObject());
  678. if (SUCCEEDED(hr))
  679. {
  680. hr = pSubsMgr2->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
  681. if (SUCCEEDED(hr))
  682. {
  683. hr = pspse->AddPages(ISPS_AddSubsPropsCallback,
  684. (LPARAM)GetParent(hdlg)) ? S_OK : E_FAIL;
  685. pspse->Release();
  686. }
  687. }
  688. return hr;
  689. }
  690. STDMETHODIMP ISPS_RemoveSubsProps(HWND hdlg, ISubscriptionMgr2 *pSubsMgr2)
  691. {
  692. HRESULT hr;
  693. ISubscriptionMgrPriv *psmp;
  694. ASSERT(NULL != pSubsMgr2);
  695. #ifndef UNIX
  696. hr = pSubsMgr2->QueryInterface(IID_PPV_ARG(ISubscriptionMgrPriv, &psmp));
  697. if (SUCCEEDED(hr))
  698. {
  699. hr = psmp->RemovePages(GetParent(hdlg));
  700. psmp->Release();
  701. }
  702. #else
  703. hr = E_FAIL;
  704. #endif
  705. return hr;
  706. }
  707. HRESULT ISPS_OnMakeOfflineClicked(HWND hdlg)
  708. {
  709. #ifndef UNIX
  710. HRESULT hr;
  711. BOOL bChecked = IsDlgButtonChecked(hdlg, IDC_MAKE_OFFLINE);
  712. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  713. ISubscriptionMgr2 *pSubsMgr2;
  714. hr = pisdata->SubsHelper.GetSubsMgr2(&pSubsMgr2, FIEF_FLAG_FORCE_JITUI);
  715. ASSERT((SUCCEEDED(hr) && pSubsMgr2) || (FAILED(hr) && !pSubsMgr2));
  716. if (bChecked)
  717. {
  718. if (SUCCEEDED(hr))
  719. {
  720. ASSERT(NULL != pSubsMgr2);
  721. hr = ISPS_AddSubsProps(hdlg, pSubsMgr2, pisdata);
  722. }
  723. else
  724. {
  725. // Can't do this without subsmgr
  726. CheckDlgButton(hdlg, IDC_MAKE_OFFLINE, BST_UNCHECKED);
  727. bChecked = FALSE;
  728. }
  729. }
  730. else
  731. {
  732. if (SUCCEEDED(hr))
  733. {
  734. ASSERT(NULL != pSubsMgr2);
  735. hr = ISPS_RemoveSubsProps(hdlg, pSubsMgr2);
  736. }
  737. }
  738. if (NULL != pSubsMgr2)
  739. {
  740. pSubsMgr2->Release();
  741. }
  742. ISPS_ShowOfflineSummary(hdlg, bChecked, pisdata);
  743. return hr;
  744. #else
  745. // IEUNIX : ( MAKE_OFFLINE disabled )
  746. return E_FAIL;
  747. #endif
  748. }
  749. BOOL
  750. ISPS_InitDialog(
  751. HWND hdlg,
  752. WPARAM wParam,
  753. LPARAM lParam)
  754. {
  755. LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
  756. PIntshcut pintshcut;
  757. PISDATA pisdata;
  758. BOOL bSubscribable;
  759. // wParam may be any value.
  760. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  761. pisdata = (PISDATA)ppsp->lParam;
  762. ASSERT(IS_VALID_STRUCT_PTR(pisdata, ISDATA));
  763. SetWindowLongPtr(hdlg, DWLP_USER, ppsp->lParam);
  764. pintshcut = pisdata->GetIntshcut();
  765. pisdata->SubsHelper.SetParentHwnd(hdlg);
  766. // Cross-lang platform support
  767. SHSetDefaultDialogFont(hdlg, IDC_START_IN);
  768. SHSetDefaultDialogFont(hdlg, IDC_URL); // for intra-net
  769. // Initialize control contents.
  770. SetISPSFileNameAndIcon(hdlg);
  771. InitISPSHotkey(hdlg);
  772. SendDlgItemMessage(hdlg, IDC_URL, EM_LIMITTEXT, INTERNET_MAX_URL_LENGTH - 1, 0);
  773. SetISPSURL(hdlg, &bSubscribable);
  774. #ifndef UNIX
  775. // IEUNIX : ( MAKE_OFFLINE disabled )
  776. if (pisdata->SubsHelper.m_dwFlags & ISF_STARTSUBSCRIBED)
  777. {
  778. CheckDlgButton(hdlg, IDC_MAKE_OFFLINE, TRUE);
  779. }
  780. if (!bSubscribable)
  781. {
  782. pisdata->SubsHelper.m_dwFlags |= ISF_DISABLEOFFLINE;
  783. }
  784. if (pisdata->SubsHelper.m_dwFlags & ISF_DISABLEOFFLINE)
  785. {
  786. EnableWindow(GetDlgItem(hdlg, IDC_MAKE_OFFLINE), FALSE);
  787. }
  788. ISPS_ShowOfflineSummary(hdlg,
  789. pisdata->SubsHelper.m_dwFlags & ISF_STARTSUBSCRIBED,
  790. pisdata);
  791. #endif
  792. // since we just finished initing the dialog, set pisdata->bUserEditedPage to
  793. // FALSE. If the user messes with the page (eg clicks a button or types in an edit box),
  794. // we will set it to TRUE so we know that we actually have changes to apply.
  795. //
  796. // NOTE: this must come last since when we call SetDlgItemText above, we will
  797. // generate WM_COMMAND messages that cause us to set bUserEditedPage to TRUE.
  798. pisdata->bUserEditedPage = FALSE;
  799. return(TRUE);
  800. }
  801. BOOL
  802. ISPS_Destroy(
  803. HWND hdlg,
  804. WPARAM wParam,
  805. LPARAM lParam)
  806. {
  807. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  808. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  809. #ifndef UNIX
  810. // IEUNIX : ( MAKE_OFFLINE disabled )
  811. if ((!(pisdata->SubsHelper.m_dwFlags & ISF_STARTSUBSCRIBED)) &&
  812. IsDlgButtonChecked(hdlg, IDC_MAKE_OFFLINE))
  813. {
  814. pisdata->SubsHelper.UpdateSubscription();
  815. }
  816. #endif
  817. SetWindowLongPtr(hdlg, DWLP_USER, NULL);
  818. SHRemoveDefaultDialogFont(hdlg);
  819. return(TRUE);
  820. }
  821. void
  822. ISPSChanged(
  823. HWND hdlg)
  824. {
  825. PISDATA pisdata;
  826. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  827. pisdata = ISPS_GetPISDATA(hdlg);
  828. pisdata->bUserEditedPage = TRUE;
  829. PropSheet_Changed(GetParent(hdlg), hdlg);
  830. return;
  831. }
  832. HRESULT
  833. ChooseIcon(
  834. HWND hdlg)
  835. {
  836. HRESULT hr;
  837. PISDATA pisdata;
  838. PIntshcut pintshcut;
  839. TCHAR szPath[MAX_PATH], szExpandedPath[MAX_PATH];
  840. int niIcon;
  841. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  842. pisdata = ISPS_GetPISDATA(hdlg);
  843. pintshcut = pisdata->GetIntshcut();
  844. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  845. szPath[0] = TEXT('\0');
  846. hr = pintshcut->GetIconLocation(szPath, MAX_PATH, (int *)(&niIcon));
  847. if((FAILED(hr)) || (FALSE == PathFileExists(szPath)))
  848. {
  849. hr = GetGenericURLIcon(szPath, MAX_PATH, (int *)(&niIcon));
  850. if(FAILED(hr))
  851. {
  852. szPath[0] = '\0';
  853. niIcon = 0;
  854. }
  855. }
  856. ASSERT(lstrlen(szPath) < SIZECHARS(szPath));
  857. if (PickIconDlg(hdlg, szPath, SIZECHARS(szPath), &niIcon) &&
  858. SHExpandEnvironmentStrings(szPath, szExpandedPath, SIZECHARS(szExpandedPath)))
  859. {
  860. ASSERT(lstrlen(szExpandedPath) < SIZECHARS(pisdata->rgchIconFile));
  861. StrCpyN(pisdata->rgchIconFile, szExpandedPath, ARRAYSIZE(pisdata->rgchIconFile));
  862. pisdata->niIcon = niIcon;
  863. hr = S_OK;
  864. }
  865. else
  866. {
  867. hr = E_FAIL;
  868. TraceMsg(TF_INTSHCUT, "ChooseIcon(): PickIconDlg() failed.");
  869. }
  870. return(hr);
  871. }
  872. void
  873. UpdateISPSIcon(
  874. HWND hdlg)
  875. {
  876. PIntshcut pintshcut;
  877. PISDATA pisdata;
  878. HICON hicon;
  879. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  880. pisdata = ISPS_GetPISDATA(hdlg);
  881. pintshcut = pisdata->GetIntshcut();
  882. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  883. ASSERT(pisdata->rgchIconFile[0]);
  884. // This icon does not have the link arrow overlayed. shell32.dll's
  885. // Shortcut property sheet has the same bug.
  886. hicon = ExtractIcon(g_hinst, pisdata->rgchIconFile, pisdata->niIcon);
  887. if (hicon)
  888. SetISPSIcon(hdlg, hicon);
  889. else
  890. TraceMsg(TF_WARNING, "UpdateISPSIcon(): ExtractIcon() failed for icon %d in file %s.",
  891. pisdata->niIcon,
  892. pisdata->rgchIconFile);
  893. }
  894. BOOL
  895. ISPS_Command(
  896. HWND hdlg,
  897. WPARAM wParam,
  898. LPARAM lParam)
  899. {
  900. BOOL bMsgHandled = FALSE;
  901. WORD wCmd;
  902. // wParam may be any value.
  903. // lParam may be any value.
  904. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  905. wCmd = HIWORD(wParam);
  906. switch (LOWORD(wParam))
  907. {
  908. case IDC_URL:
  909. case IDC_HOTKEY:
  910. if (wCmd == EN_CHANGE)
  911. {
  912. ISPSChanged(hdlg);
  913. bMsgHandled = TRUE;
  914. }
  915. break;
  916. #ifndef UNIX
  917. // IEUNIX : ( MAKE_OFFLINE disabled )
  918. case IDC_MAKE_OFFLINE:
  919. if (wCmd == BN_CLICKED)
  920. {
  921. ISPS_OnMakeOfflineClicked(hdlg);
  922. ISPSChanged(hdlg);
  923. bMsgHandled = TRUE;
  924. }
  925. break;
  926. case IDC_CHANGE_ICON:
  927. // Ignore return value.
  928. if (ChooseIcon(hdlg) == S_OK)
  929. {
  930. UpdateISPSIcon(hdlg);
  931. ISPSChanged(hdlg);
  932. }
  933. bMsgHandled = TRUE;
  934. break;
  935. #endif
  936. default:
  937. break;
  938. }
  939. return(bMsgHandled);
  940. }
  941. HRESULT
  942. ComplainAboutURL(
  943. HWND hwndParent,
  944. LPCTSTR pcszURL,
  945. HRESULT hrError)
  946. {
  947. HRESULT hr;
  948. int nResult;
  949. // Validate hrError below.
  950. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  951. ASSERT(IS_VALID_STRING_PTR(pcszURL, -1));
  952. switch (hrError)
  953. {
  954. case URL_E_UNREGISTERED_PROTOCOL:
  955. {
  956. LPTSTR pszProtocol;
  957. hr = CopyURLProtocol(pcszURL, &pszProtocol, NULL);
  958. if (hr == S_OK)
  959. {
  960. nResult = MLShellMessageBox(
  961. hwndParent,
  962. MAKEINTRESOURCE(IDS_UNREGISTERED_PROTOCOL),
  963. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  964. (MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION),
  965. pszProtocol);
  966. if (-1 != nResult)
  967. {
  968. switch (nResult)
  969. {
  970. case IDYES:
  971. hr = S_OK;
  972. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Allowing URL %s despite unregistered protocol %s, by request.",
  973. pcszURL,
  974. pszProtocol);
  975. break;
  976. default:
  977. ASSERT(nResult == IDNO);
  978. hr = E_FAIL;
  979. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Not allowing URL %s because of unregistered protocol %s, as directed.",
  980. pcszURL,
  981. pszProtocol);
  982. break;
  983. }
  984. }
  985. LocalFree(pszProtocol);
  986. pszProtocol = NULL;
  987. }
  988. break;
  989. }
  990. default:
  991. ASSERT(hrError == URL_E_INVALID_SYNTAX);
  992. MLShellMessageBox(
  993. hwndParent,
  994. MAKEINTRESOURCE(IDS_INVALID_URL_SYNTAX),
  995. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  996. MB_OK | MB_ICONEXCLAMATION,
  997. pcszURL);
  998. hr = E_FAIL;
  999. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Not allowing URL %s because of invalid syntax.",
  1000. pcszURL);
  1001. break;
  1002. }
  1003. return(hr);
  1004. }
  1005. HRESULT
  1006. InjectISPSData(
  1007. HWND hdlg)
  1008. {
  1009. HRESULT hr;
  1010. PISDATA pisdata;
  1011. PIntshcut pintshcut;
  1012. PTSTR pszURL;
  1013. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1014. pisdata = ISPS_GetPISDATA(hdlg);
  1015. pintshcut = pisdata->GetIntshcut();
  1016. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  1017. // TODO: Inform the subsmgr of any URL changes! IE 4 didn't handle this...
  1018. hr = CopyDlgItemText(hdlg, IDC_URL, &pszURL);
  1019. if (SUCCEEDED(hr))
  1020. {
  1021. LPCTSTR pcszURLToUse;
  1022. TCHAR szURL[MAX_URL_STRING];
  1023. pcszURLToUse = pszURL;
  1024. if (hr == S_OK)
  1025. {
  1026. hr = IURLQualify(pszURL, UQF_DEFAULT, szURL, NULL, NULL);
  1027. if (SUCCEEDED(hr))
  1028. {
  1029. pcszURLToUse = szURL;
  1030. hr = ValidateURL(pcszURLToUse);
  1031. if (FAILED(hr))
  1032. {
  1033. hr = ComplainAboutURL(hdlg, pcszURLToUse, hr);
  1034. if (FAILED(hr))
  1035. SetEditFocus(GetDlgItem(hdlg, IDC_URL));
  1036. }
  1037. }
  1038. }
  1039. else
  1040. {
  1041. // A blank URL is not OK.
  1042. ASSERT(hr == S_FALSE);
  1043. hr = ComplainAboutURL(hdlg, TEXT(""), URL_E_INVALID_SYNTAX);
  1044. if (FAILED(hr))
  1045. SetEditFocus(GetDlgItem(hdlg, IDC_URL));
  1046. }
  1047. if (SUCCEEDED(hr))
  1048. {
  1049. hr = pintshcut->SetURL(pcszURLToUse, 0);
  1050. if (hr == S_OK)
  1051. {
  1052. WORD wHotkey;
  1053. WORD wOldHotkey;
  1054. BOOL bSubscribable;
  1055. // Refresh URL in case it was changed by IURLQualify().
  1056. SetISPSURL(hdlg, &bSubscribable);
  1057. #ifndef UNIX
  1058. // IEUNIX : ( MAKE_OFFLINE disabled )
  1059. if (!bSubscribable)
  1060. {
  1061. EnableWindow(GetDlgItem(hdlg, IDC_MAKE_OFFLINE), FALSE);
  1062. }
  1063. // IEUNIX : Hot key and working directory are N/A on UNIX.
  1064. wHotkey = (WORD)SendDlgItemMessage(hdlg, IDC_HOTKEY, HKM_GETHOTKEY, 0, 0);
  1065. hr = pintshcut->GetHotkey(&wOldHotkey);
  1066. if (hr == S_OK)
  1067. {
  1068. hr = pintshcut->SetHotkey(wHotkey);
  1069. if (hr == S_OK)
  1070. {
  1071. TCHAR szFile[MAX_PATH];
  1072. hr = pintshcut->GetCurFile(szFile, SIZECHARS(szFile));
  1073. if (hr == S_OK)
  1074. {
  1075. if (RegisterGlobalHotkey(wOldHotkey, wHotkey, szFile))
  1076. {
  1077. if (pisdata->rgchIconFile[0])
  1078. {
  1079. hr = pintshcut->SetIconLocation(pisdata->rgchIconFile, pisdata->niIcon);
  1080. }
  1081. }
  1082. else
  1083. {
  1084. hr = E_FAIL;
  1085. }
  1086. }
  1087. }
  1088. }
  1089. #endif //!UNIX
  1090. pintshcut->ChangeNotify(SHCNE_UPDATEITEM, 0);
  1091. }
  1092. }
  1093. if (pszURL)
  1094. {
  1095. LocalFree(pszURL);
  1096. pszURL = NULL;
  1097. }
  1098. }
  1099. if (hr == S_OK)
  1100. TraceMsg(TF_INTSHCUT, "InjectISPSData(): Injected property sheet data into Internet Shortcut successfully.");
  1101. else
  1102. TraceMsg(TF_WARNING, "InjectISPSData(): Failed to inject property sheet data into Internet Shortcut, returning %s.",
  1103. Dbg_GetHRESULTName(hr));
  1104. return(hr);
  1105. }
  1106. HRESULT
  1107. ISPSSave(
  1108. HWND hdlg)
  1109. {
  1110. HRESULT hr;
  1111. PIntshcut pintshcut;
  1112. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1113. pintshcut = ISPS_GetThisPtr(hdlg);
  1114. if (pintshcut->IsDirty() == S_OK)
  1115. {
  1116. hr = pintshcut->Save((LPCOLESTR)NULL, FALSE);
  1117. if (hr == S_OK)
  1118. {
  1119. TraceMsg(TF_INTSHCUT, "ISPSSave(): Saved Internet Shortcut successfully.");
  1120. }
  1121. else
  1122. {
  1123. TraceMsg(TF_WARNING, "ISPSSave(): Save() failed, returning %s.",
  1124. Dbg_GetHRESULTName(hr));
  1125. MLShellMessageBox(
  1126. hdlg,
  1127. MAKEINTRESOURCE(IDS_IS_APPLY_FAILED),
  1128. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  1129. (MB_OK | MB_ICONEXCLAMATION));
  1130. }
  1131. }
  1132. else
  1133. {
  1134. TraceMsg(TF_INTSHCUT, "ISPSSave(): Internet Shortcut unchanged. No save required.");
  1135. hr = S_OK;
  1136. }
  1137. return(hr);
  1138. }
  1139. BOOL
  1140. ISPS_Notify(
  1141. HWND hdlg,
  1142. WPARAM wParam,
  1143. LPARAM lParam)
  1144. {
  1145. BOOL bMsgHandled = FALSE;
  1146. // wParam may be any value.
  1147. // lParam may be any value.
  1148. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1149. switch (((NMHDR *)lParam)->code)
  1150. {
  1151. case PSN_APPLY:
  1152. {
  1153. #ifndef UNIX
  1154. // IEUNIX : ( MAKE_OFFLINE disabled )
  1155. BOOL bSubscribed = IsDlgButtonChecked(hdlg, IDC_MAKE_OFFLINE);
  1156. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  1157. if (!bSubscribed)
  1158. {
  1159. pisdata->SubsHelper.DeleteSubscription();
  1160. }
  1161. else
  1162. {
  1163. pisdata->SubsHelper.SaveSubscription();
  1164. }
  1165. #endif /* !UNIX */
  1166. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, ISPSSave(hdlg) == S_OK ?
  1167. PSNRET_NOERROR :
  1168. PSNRET_INVALID_NOCHANGEPAGE);
  1169. bMsgHandled = TRUE;
  1170. break;
  1171. }
  1172. case PSN_KILLACTIVE:
  1173. {
  1174. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  1175. if (pisdata->bUserEditedPage)
  1176. {
  1177. // only try to inject the data if the user actually changed something
  1178. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectISPSData(hdlg)));
  1179. }
  1180. bMsgHandled = TRUE;
  1181. break;
  1182. }
  1183. default:
  1184. break;
  1185. }
  1186. return(bMsgHandled);
  1187. }
  1188. LPCTSTR
  1189. ISPS_GetHelpFileFromControl(
  1190. HWND hwndControl)
  1191. {
  1192. LPCTSTR pcszHelpFile = NULL;
  1193. int nControlID = 0;
  1194. ASSERT(! hwndControl ||
  1195. IS_VALID_HANDLE(hwndControl, WND));
  1196. if (hwndControl)
  1197. {
  1198. nControlID = GetDlgCtrlID(hwndControl);
  1199. switch (nControlID)
  1200. {
  1201. default:
  1202. // URL help comes from the iexplore.hlp
  1203. pcszHelpFile = s_cszIEHelpFile;
  1204. break;
  1205. // Other help is borrowed from the default Win95 help file.
  1206. case IDC_ICON:
  1207. case IDC_NAME:
  1208. case IDC_HOTKEY_TEXT:
  1209. case IDC_HOTKEY:
  1210. case IDC_CHANGE_ICON:
  1211. break;
  1212. }
  1213. }
  1214. TraceMsg(TF_INTSHCUT, "ISPS_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx).",
  1215. pcszHelpFile ? pcszHelpFile : TEXT("default Win95 help file"),
  1216. nControlID,
  1217. hwndControl);
  1218. ASSERT(! pcszHelpFile ||
  1219. IS_VALID_STRING_PTR(pcszHelpFile, -1));
  1220. return(pcszHelpFile);
  1221. }
  1222. INT_PTR
  1223. CALLBACK
  1224. ISPS_DlgProc(
  1225. HWND hdlg,
  1226. UINT uMsg,
  1227. WPARAM wParam,
  1228. LPARAM lParam)
  1229. {
  1230. BOOL bMsgHandled = FALSE;
  1231. // uMsg may be any value.
  1232. // wParam may be any value.
  1233. // lParam may be any value.
  1234. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1235. switch (uMsg)
  1236. {
  1237. case WM_INITDIALOG:
  1238. bMsgHandled = ISPS_InitDialog(hdlg, wParam, lParam);
  1239. break;
  1240. case WM_DESTROY:
  1241. bMsgHandled = ISPS_Destroy(hdlg, wParam, lParam);
  1242. break;
  1243. case WM_COMMAND:
  1244. bMsgHandled = ISPS_Command(hdlg, wParam, lParam);
  1245. break;
  1246. case WM_NOTIFY:
  1247. bMsgHandled = ISPS_Notify(hdlg, wParam, lParam);
  1248. break;
  1249. case WM_HELP:
  1250. SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lParam)->hItemHandle),
  1251. ISPS_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
  1252. HELP_WM_HELP, (DWORD_PTR)(PVOID)c_rgdwHelpIDs);
  1253. bMsgHandled = TRUE;
  1254. break;
  1255. case WM_CONTEXTMENU:
  1256. {
  1257. HWND hwnd;
  1258. if (!IS_WM_CONTEXTMENU_KEYBOARD(lParam))
  1259. {
  1260. POINT pt;
  1261. LPARAM_TO_POINT(lParam, pt);
  1262. EVAL(ScreenToClient(hdlg, &pt));
  1263. hwnd = ChildWindowFromPoint(hdlg, pt);
  1264. }
  1265. else
  1266. {
  1267. // For some reason on the keyboard case we don't actually
  1268. // come to this WM_CONTEXTMENU handler -- someone somewhere
  1269. // else is popping up the menu at the cursor instead of on
  1270. // this hwnd...
  1271. //
  1272. hwnd = GetFocus();
  1273. }
  1274. SHWinHelpOnDemandWrap((HWND)wParam,
  1275. ISPS_GetHelpFileFromControl(hwnd),
  1276. HELP_CONTEXTMENU, (DWORD_PTR)(PVOID)c_rgdwHelpIDs);
  1277. bMsgHandled = TRUE;
  1278. break;
  1279. }
  1280. default:
  1281. break;
  1282. }
  1283. return(bMsgHandled);
  1284. }
  1285. HRESULT AddISPage(HPROPSHEETPAGE * phpsp,
  1286. PROPSHEETPAGE * ppsp,
  1287. LPFNADDPROPSHEETPAGE pfnAddPage,
  1288. LPARAM lParam)
  1289. {
  1290. HRESULT hres;
  1291. ASSERT(phpsp);
  1292. ASSERT(ppsp);
  1293. *phpsp = Whistler_CreatePropertySheetPageW(ppsp);
  1294. if (NULL == *phpsp)
  1295. {
  1296. hres = E_OUTOFMEMORY;
  1297. }
  1298. else
  1299. {
  1300. if ( !(*pfnAddPage)(*phpsp, lParam) )
  1301. {
  1302. DestroyPropertySheetPage(*phpsp);
  1303. *phpsp = NULL;
  1304. hres = E_OUTOFMEMORY;
  1305. }
  1306. else
  1307. {
  1308. hres = NO_ERROR;
  1309. }
  1310. }
  1311. return hres;
  1312. }
  1313. HRESULT AddISPS(PIntshcut pintshcut, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1314. {
  1315. HRESULT hr;
  1316. PISDATA pisdata;
  1317. // lParam may be any value.
  1318. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  1319. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  1320. // Initialize instance data between property pages
  1321. pisdata = new ISDATA;
  1322. if ( !pisdata )
  1323. {
  1324. hr = E_OUTOFMEMORY;
  1325. }
  1326. else
  1327. {
  1328. PROPSHEETPAGE psp;
  1329. HPROPSHEETPAGE hpsp;
  1330. WCHAR *pwszURL;
  1331. hr = pintshcut->GetURLW(&pwszURL);
  1332. if (SUCCEEDED(hr))
  1333. {
  1334. pisdata->SetIntshcut(pintshcut);
  1335. pisdata->SubsHelper.Init();
  1336. SHFree(pwszURL);
  1337. ASSERT(IS_VALID_STRUCT_PTR(pisdata, ISDATA));
  1338. // Add the Internet Shortcut page
  1339. ZeroMemory(&psp, SIZEOF(psp));
  1340. psp.dwSize = SIZEOF(psp);
  1341. psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
  1342. psp.hInstance = MLGetHinst();
  1343. psp.pszTemplate = MAKEINTRESOURCE(IDD_INTSHCUT_PROP);
  1344. psp.pfnDlgProc = &ISPS_DlgProc;
  1345. psp.lParam = (LPARAM)pisdata;
  1346. psp.pfnCallback = &ISPSCallback;
  1347. hr = AddISPage(&hpsp, &psp, pfnAddPage, lParam);
  1348. if (SUCCEEDED(hr) && (pisdata->SubsHelper.m_dwFlags & ISF_STARTSUBSCRIBED))
  1349. {
  1350. HRESULT hrTmp = pisdata->SubsHelper.DoShellExtInit(pisdata->GetIntshcut()->GetInitDataObject());
  1351. if (SUCCEEDED(hrTmp))
  1352. {
  1353. ISubscriptionMgr2 *pSubsMgr2;
  1354. hrTmp = pisdata->SubsHelper.GetSubsMgr2(&pSubsMgr2, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
  1355. if (SUCCEEDED(hrTmp))
  1356. {
  1357. IShellPropSheetExt *pspse;
  1358. hrTmp = pSubsMgr2->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
  1359. if (SUCCEEDED(hrTmp))
  1360. {
  1361. hrTmp = pspse->AddPages(pfnAddPage, lParam);
  1362. pspse->Release();
  1363. }
  1364. pSubsMgr2->Release();
  1365. }
  1366. }
  1367. }
  1368. }
  1369. if (FAILED(hr))
  1370. {
  1371. delete pisdata;
  1372. pisdata = NULL;
  1373. }
  1374. }
  1375. return hr;
  1376. }
  1377. // IShellExtInit::Initialize method for Intshcut
  1378. STDMETHODIMP Intshcut::Initialize(LPCITEMIDLIST pcidlFolder, IDataObject * pido, HKEY hkeyProgID)
  1379. {
  1380. HRESULT hr;
  1381. STGMEDIUM stgmed;
  1382. FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  1383. ASSERT(NULL != pido);
  1384. if (m_pInitDataObject)
  1385. {
  1386. m_pInitDataObject->Release();
  1387. }
  1388. m_pInitDataObject = pido;
  1389. m_pInitDataObject->AddRef();
  1390. hr = pido->GetData(&fmtetc, &stgmed);
  1391. if (hr == S_OK)
  1392. {
  1393. TCHAR szPath[MAX_PATH];
  1394. if (DragQueryFile((HDROP)stgmed.hGlobal, 0, szPath, SIZECHARS(szPath)))
  1395. {
  1396. m_fProbablyDefCM = TRUE;
  1397. hr = LoadFromFile(szPath);
  1398. }
  1399. ReleaseStgMedium(&stgmed);
  1400. }
  1401. return(hr);
  1402. }
  1403. // IShellPropSheetExt::AddPages method for Intshcut
  1404. STDMETHODIMP Intshcut::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1405. {
  1406. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  1407. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  1408. HRESULT hres = AddISPS(this, pfnAddPage, lParam);
  1409. if (SUCCEEDED(hres))
  1410. {
  1411. // Make the Internet Shortcut page be the default page
  1412. hres = ResultFromShort(1);
  1413. }
  1414. return hres;
  1415. }
  1416. STDMETHODIMP Intshcut::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplaceWith, LPARAM lParam)
  1417. {
  1418. return E_NOTIMPL;
  1419. }