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.

1801 lines
46 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. hr = StringCchCopy(pisdata->rgchIconFile, ARRAYSIZE(pisdata->rgchIconFile), szExpandedPath);
  862. pisdata->niIcon = niIcon;
  863. }
  864. else
  865. {
  866. hr = E_FAIL;
  867. TraceMsg(TF_INTSHCUT, "ChooseIcon(): PickIconDlg() failed.");
  868. }
  869. return(hr);
  870. }
  871. void
  872. UpdateISPSIcon(
  873. HWND hdlg)
  874. {
  875. PIntshcut pintshcut;
  876. PISDATA pisdata;
  877. HICON hicon;
  878. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  879. pisdata = ISPS_GetPISDATA(hdlg);
  880. pintshcut = pisdata->GetIntshcut();
  881. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  882. ASSERT(pisdata->rgchIconFile[0]);
  883. // This icon does not have the link arrow overlayed. shell32.dll's
  884. // Shortcut property sheet has the same bug.
  885. hicon = ExtractIcon(g_hinst, pisdata->rgchIconFile, pisdata->niIcon);
  886. if (hicon)
  887. SetISPSIcon(hdlg, hicon);
  888. else
  889. TraceMsg(TF_WARNING, "UpdateISPSIcon(): ExtractIcon() failed for icon %d in file %s.",
  890. pisdata->niIcon,
  891. pisdata->rgchIconFile);
  892. }
  893. BOOL
  894. ISPS_Command(
  895. HWND hdlg,
  896. WPARAM wParam,
  897. LPARAM lParam)
  898. {
  899. BOOL bMsgHandled = FALSE;
  900. WORD wCmd;
  901. // wParam may be any value.
  902. // lParam may be any value.
  903. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  904. wCmd = HIWORD(wParam);
  905. switch (LOWORD(wParam))
  906. {
  907. case IDC_URL:
  908. case IDC_HOTKEY:
  909. if (wCmd == EN_CHANGE)
  910. {
  911. ISPSChanged(hdlg);
  912. bMsgHandled = TRUE;
  913. }
  914. break;
  915. #ifndef UNIX
  916. // IEUNIX : ( MAKE_OFFLINE disabled )
  917. case IDC_MAKE_OFFLINE:
  918. if (wCmd == BN_CLICKED)
  919. {
  920. ISPS_OnMakeOfflineClicked(hdlg);
  921. ISPSChanged(hdlg);
  922. bMsgHandled = TRUE;
  923. }
  924. break;
  925. case IDC_CHANGE_ICON:
  926. // Ignore return value.
  927. if (ChooseIcon(hdlg) == S_OK)
  928. {
  929. UpdateISPSIcon(hdlg);
  930. ISPSChanged(hdlg);
  931. }
  932. bMsgHandled = TRUE;
  933. break;
  934. #endif
  935. default:
  936. break;
  937. }
  938. return(bMsgHandled);
  939. }
  940. HRESULT
  941. ComplainAboutURL(
  942. HWND hwndParent,
  943. LPCTSTR pcszURL,
  944. HRESULT hrError)
  945. {
  946. HRESULT hr;
  947. int nResult;
  948. // Validate hrError below.
  949. ASSERT(IS_VALID_HANDLE(hwndParent, WND));
  950. ASSERT(IS_VALID_STRING_PTR(pcszURL, -1));
  951. switch (hrError)
  952. {
  953. case URL_E_UNREGISTERED_PROTOCOL:
  954. {
  955. LPTSTR pszProtocol;
  956. hr = CopyURLProtocol(pcszURL, &pszProtocol, NULL);
  957. if (hr == S_OK)
  958. {
  959. nResult = MLShellMessageBox(
  960. hwndParent,
  961. MAKEINTRESOURCE(IDS_UNREGISTERED_PROTOCOL),
  962. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  963. (MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION),
  964. pszProtocol);
  965. if (-1 != nResult)
  966. {
  967. switch (nResult)
  968. {
  969. case IDYES:
  970. hr = S_OK;
  971. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Allowing URL %s despite unregistered protocol %s, by request.",
  972. pcszURL,
  973. pszProtocol);
  974. break;
  975. default:
  976. ASSERT(nResult == IDNO);
  977. hr = E_FAIL;
  978. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Not allowing URL %s because of unregistered protocol %s, as directed.",
  979. pcszURL,
  980. pszProtocol);
  981. break;
  982. }
  983. }
  984. LocalFree(pszProtocol);
  985. pszProtocol = NULL;
  986. }
  987. break;
  988. }
  989. default:
  990. ASSERT(hrError == URL_E_INVALID_SYNTAX);
  991. MLShellMessageBox(
  992. hwndParent,
  993. MAKEINTRESOURCE(IDS_INVALID_URL_SYNTAX),
  994. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  995. MB_OK | MB_ICONEXCLAMATION,
  996. pcszURL);
  997. hr = E_FAIL;
  998. TraceMsg(TF_INTSHCUT, "ComplainAboutURL(): Not allowing URL %s because of invalid syntax.",
  999. pcszURL);
  1000. break;
  1001. }
  1002. return(hr);
  1003. }
  1004. HRESULT
  1005. InjectISPSData(
  1006. HWND hdlg)
  1007. {
  1008. HRESULT hr;
  1009. PISDATA pisdata;
  1010. PIntshcut pintshcut;
  1011. PTSTR pszURL;
  1012. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1013. pisdata = ISPS_GetPISDATA(hdlg);
  1014. pintshcut = pisdata->GetIntshcut();
  1015. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  1016. // TODO: Inform the subsmgr of any URL changes! IE 4 didn't handle this...
  1017. hr = CopyDlgItemText(hdlg, IDC_URL, &pszURL);
  1018. if (SUCCEEDED(hr))
  1019. {
  1020. LPCTSTR pcszURLToUse;
  1021. TCHAR szURL[MAX_URL_STRING];
  1022. pcszURLToUse = pszURL;
  1023. if (hr == S_OK)
  1024. {
  1025. hr = IURLQualify(pszURL, UQF_DEFAULT, szURL, NULL, NULL);
  1026. if (SUCCEEDED(hr))
  1027. {
  1028. pcszURLToUse = szURL;
  1029. hr = ValidateURL(pcszURLToUse);
  1030. if (FAILED(hr))
  1031. {
  1032. hr = ComplainAboutURL(hdlg, pcszURLToUse, hr);
  1033. if (FAILED(hr))
  1034. SetEditFocus(GetDlgItem(hdlg, IDC_URL));
  1035. }
  1036. }
  1037. }
  1038. else
  1039. {
  1040. // A blank URL is not OK.
  1041. ASSERT(hr == S_FALSE);
  1042. hr = ComplainAboutURL(hdlg, TEXT(""), URL_E_INVALID_SYNTAX);
  1043. if (FAILED(hr))
  1044. SetEditFocus(GetDlgItem(hdlg, IDC_URL));
  1045. }
  1046. if (SUCCEEDED(hr))
  1047. {
  1048. hr = pintshcut->SetURL(pcszURLToUse, 0);
  1049. if (hr == S_OK)
  1050. {
  1051. WORD wHotkey;
  1052. WORD wOldHotkey;
  1053. BOOL bSubscribable;
  1054. // Refresh URL in case it was changed by IURLQualify().
  1055. SetISPSURL(hdlg, &bSubscribable);
  1056. #ifndef UNIX
  1057. // IEUNIX : ( MAKE_OFFLINE disabled )
  1058. if (!bSubscribable)
  1059. {
  1060. EnableWindow(GetDlgItem(hdlg, IDC_MAKE_OFFLINE), FALSE);
  1061. }
  1062. // IEUNIX : Hot key and working directory are N/A on UNIX.
  1063. wHotkey = (WORD)SendDlgItemMessage(hdlg, IDC_HOTKEY, HKM_GETHOTKEY, 0, 0);
  1064. hr = pintshcut->GetHotkey(&wOldHotkey);
  1065. if (hr == S_OK)
  1066. {
  1067. hr = pintshcut->SetHotkey(wHotkey);
  1068. if (hr == S_OK)
  1069. {
  1070. TCHAR szFile[MAX_PATH];
  1071. hr = pintshcut->GetCurFile(szFile, SIZECHARS(szFile));
  1072. if (hr == S_OK)
  1073. {
  1074. if (RegisterGlobalHotkey(wOldHotkey, wHotkey, szFile))
  1075. {
  1076. if (pisdata->rgchIconFile[0])
  1077. {
  1078. hr = pintshcut->SetIconLocation(pisdata->rgchIconFile, pisdata->niIcon);
  1079. }
  1080. }
  1081. else
  1082. {
  1083. hr = E_FAIL;
  1084. }
  1085. }
  1086. }
  1087. }
  1088. #endif //!UNIX
  1089. pintshcut->ChangeNotify(SHCNE_UPDATEITEM, 0);
  1090. }
  1091. }
  1092. if (pszURL)
  1093. {
  1094. LocalFree(pszURL);
  1095. pszURL = NULL;
  1096. }
  1097. }
  1098. if (hr == S_OK)
  1099. TraceMsg(TF_INTSHCUT, "InjectISPSData(): Injected property sheet data into Internet Shortcut successfully.");
  1100. else
  1101. TraceMsg(TF_WARNING, "InjectISPSData(): Failed to inject property sheet data into Internet Shortcut, returning %s.",
  1102. Dbg_GetHRESULTName(hr));
  1103. return(hr);
  1104. }
  1105. HRESULT
  1106. ISPSSave(
  1107. HWND hdlg)
  1108. {
  1109. HRESULT hr;
  1110. PIntshcut pintshcut;
  1111. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1112. pintshcut = ISPS_GetThisPtr(hdlg);
  1113. if (pintshcut->IsDirty() == S_OK)
  1114. {
  1115. hr = pintshcut->Save((LPCOLESTR)NULL, FALSE);
  1116. if (hr == S_OK)
  1117. {
  1118. TraceMsg(TF_INTSHCUT, "ISPSSave(): Saved Internet Shortcut successfully.");
  1119. }
  1120. else
  1121. {
  1122. TraceMsg(TF_WARNING, "ISPSSave(): Save() failed, returning %s.",
  1123. Dbg_GetHRESULTName(hr));
  1124. MLShellMessageBox(
  1125. hdlg,
  1126. MAKEINTRESOURCE(IDS_IS_APPLY_FAILED),
  1127. MAKEINTRESOURCE(IDS_SHORTCUT_ERROR_TITLE),
  1128. (MB_OK | MB_ICONEXCLAMATION));
  1129. }
  1130. }
  1131. else
  1132. {
  1133. TraceMsg(TF_INTSHCUT, "ISPSSave(): Internet Shortcut unchanged. No save required.");
  1134. hr = S_OK;
  1135. }
  1136. return(hr);
  1137. }
  1138. BOOL
  1139. ISPS_Notify(
  1140. HWND hdlg,
  1141. WPARAM wParam,
  1142. LPARAM lParam)
  1143. {
  1144. BOOL bMsgHandled = FALSE;
  1145. // wParam may be any value.
  1146. // lParam may be any value.
  1147. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1148. switch (((NMHDR *)lParam)->code)
  1149. {
  1150. case PSN_APPLY:
  1151. {
  1152. #ifndef UNIX
  1153. // IEUNIX : ( MAKE_OFFLINE disabled )
  1154. BOOL bSubscribed = IsDlgButtonChecked(hdlg, IDC_MAKE_OFFLINE);
  1155. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  1156. if (!bSubscribed)
  1157. {
  1158. pisdata->SubsHelper.DeleteSubscription();
  1159. }
  1160. else
  1161. {
  1162. pisdata->SubsHelper.SaveSubscription();
  1163. }
  1164. #endif /* !UNIX */
  1165. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, ISPSSave(hdlg) == S_OK ?
  1166. PSNRET_NOERROR :
  1167. PSNRET_INVALID_NOCHANGEPAGE);
  1168. bMsgHandled = TRUE;
  1169. break;
  1170. }
  1171. case PSN_KILLACTIVE:
  1172. {
  1173. PISDATA pisdata = ISPS_GetPISDATA(hdlg);
  1174. if (pisdata->bUserEditedPage)
  1175. {
  1176. // only try to inject the data if the user actually changed something
  1177. SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FAILED(InjectISPSData(hdlg)));
  1178. }
  1179. bMsgHandled = TRUE;
  1180. break;
  1181. }
  1182. default:
  1183. break;
  1184. }
  1185. return(bMsgHandled);
  1186. }
  1187. LPCTSTR
  1188. ISPS_GetHelpFileFromControl(
  1189. HWND hwndControl)
  1190. {
  1191. LPCTSTR pcszHelpFile = NULL;
  1192. int nControlID = 0;
  1193. ASSERT(! hwndControl ||
  1194. IS_VALID_HANDLE(hwndControl, WND));
  1195. if (hwndControl)
  1196. {
  1197. nControlID = GetDlgCtrlID(hwndControl);
  1198. switch (nControlID)
  1199. {
  1200. default:
  1201. // URL help comes from the iexplore.hlp
  1202. pcszHelpFile = s_cszIEHelpFile;
  1203. break;
  1204. // Other help is borrowed from the default Win95 help file.
  1205. case IDC_ICON:
  1206. case IDC_NAME:
  1207. case IDC_HOTKEY_TEXT:
  1208. case IDC_HOTKEY:
  1209. case IDC_CHANGE_ICON:
  1210. break;
  1211. }
  1212. }
  1213. TraceMsg(TF_INTSHCUT, "ISPS_GetHelpFileFromControl(): Using %s for control %d (HWND %#lx).",
  1214. pcszHelpFile ? pcszHelpFile : TEXT("default Win95 help file"),
  1215. nControlID,
  1216. hwndControl);
  1217. ASSERT(! pcszHelpFile ||
  1218. IS_VALID_STRING_PTR(pcszHelpFile, -1));
  1219. return(pcszHelpFile);
  1220. }
  1221. INT_PTR
  1222. CALLBACK
  1223. ISPS_DlgProc(
  1224. HWND hdlg,
  1225. UINT uMsg,
  1226. WPARAM wParam,
  1227. LPARAM lParam)
  1228. {
  1229. BOOL bMsgHandled = FALSE;
  1230. // uMsg may be any value.
  1231. // wParam may be any value.
  1232. // lParam may be any value.
  1233. ASSERT(IS_VALID_HANDLE(hdlg, WND));
  1234. switch (uMsg)
  1235. {
  1236. case WM_INITDIALOG:
  1237. bMsgHandled = ISPS_InitDialog(hdlg, wParam, lParam);
  1238. break;
  1239. case WM_DESTROY:
  1240. bMsgHandled = ISPS_Destroy(hdlg, wParam, lParam);
  1241. break;
  1242. case WM_COMMAND:
  1243. bMsgHandled = ISPS_Command(hdlg, wParam, lParam);
  1244. break;
  1245. case WM_NOTIFY:
  1246. bMsgHandled = ISPS_Notify(hdlg, wParam, lParam);
  1247. break;
  1248. case WM_HELP:
  1249. SHWinHelpOnDemandWrap((HWND)(((LPHELPINFO)lParam)->hItemHandle),
  1250. ISPS_GetHelpFileFromControl((HWND)(((LPHELPINFO)lParam)->hItemHandle)),
  1251. HELP_WM_HELP, (DWORD_PTR)(PVOID)c_rgdwHelpIDs);
  1252. bMsgHandled = TRUE;
  1253. break;
  1254. case WM_CONTEXTMENU:
  1255. {
  1256. HWND hwnd;
  1257. if (!IS_WM_CONTEXTMENU_KEYBOARD(lParam))
  1258. {
  1259. POINT pt;
  1260. LPARAM_TO_POINT(lParam, pt);
  1261. EVAL(ScreenToClient(hdlg, &pt));
  1262. hwnd = ChildWindowFromPoint(hdlg, pt);
  1263. }
  1264. else
  1265. {
  1266. // For some reason on the keyboard case we don't actually
  1267. // come to this WM_CONTEXTMENU handler -- someone somewhere
  1268. // else is popping up the menu at the cursor instead of on
  1269. // this hwnd...
  1270. //
  1271. hwnd = GetFocus();
  1272. }
  1273. SHWinHelpOnDemandWrap((HWND)wParam,
  1274. ISPS_GetHelpFileFromControl(hwnd),
  1275. HELP_CONTEXTMENU, (DWORD_PTR)(PVOID)c_rgdwHelpIDs);
  1276. bMsgHandled = TRUE;
  1277. break;
  1278. }
  1279. default:
  1280. break;
  1281. }
  1282. return(bMsgHandled);
  1283. }
  1284. HRESULT AddISPage(HPROPSHEETPAGE * phpsp,
  1285. PROPSHEETPAGE * ppsp,
  1286. LPFNADDPROPSHEETPAGE pfnAddPage,
  1287. LPARAM lParam)
  1288. {
  1289. HRESULT hres;
  1290. ASSERT(phpsp);
  1291. ASSERT(ppsp);
  1292. *phpsp = Whistler_CreatePropertySheetPageW(ppsp);
  1293. if (NULL == *phpsp)
  1294. {
  1295. hres = E_OUTOFMEMORY;
  1296. }
  1297. else
  1298. {
  1299. if ( !(*pfnAddPage)(*phpsp, lParam) )
  1300. {
  1301. DestroyPropertySheetPage(*phpsp);
  1302. *phpsp = NULL;
  1303. hres = E_OUTOFMEMORY;
  1304. }
  1305. else
  1306. {
  1307. hres = NO_ERROR;
  1308. }
  1309. }
  1310. return hres;
  1311. }
  1312. HRESULT AddISPS(PIntshcut pintshcut, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1313. {
  1314. HRESULT hr;
  1315. PISDATA pisdata;
  1316. // lParam may be any value.
  1317. ASSERT(IS_VALID_STRUCT_PTR(pintshcut, CIntshcut));
  1318. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  1319. // Initialize instance data between property pages
  1320. pisdata = new ISDATA;
  1321. if ( !pisdata )
  1322. {
  1323. hr = E_OUTOFMEMORY;
  1324. }
  1325. else
  1326. {
  1327. PROPSHEETPAGE psp;
  1328. HPROPSHEETPAGE hpsp;
  1329. WCHAR *pwszURL;
  1330. hr = pintshcut->GetURLW(&pwszURL);
  1331. if (SUCCEEDED(hr))
  1332. {
  1333. pisdata->SetIntshcut(pintshcut);
  1334. pisdata->SubsHelper.Init();
  1335. SHFree(pwszURL);
  1336. ASSERT(IS_VALID_STRUCT_PTR(pisdata, ISDATA));
  1337. // Add the Internet Shortcut page
  1338. ZeroMemory(&psp, SIZEOF(psp));
  1339. psp.dwSize = SIZEOF(psp);
  1340. psp.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
  1341. psp.hInstance = MLGetHinst();
  1342. psp.pszTemplate = MAKEINTRESOURCE(IDD_INTSHCUT_PROP);
  1343. psp.pfnDlgProc = &ISPS_DlgProc;
  1344. psp.lParam = (LPARAM)pisdata;
  1345. psp.pfnCallback = &ISPSCallback;
  1346. hr = AddISPage(&hpsp, &psp, pfnAddPage, lParam);
  1347. if (SUCCEEDED(hr) && (pisdata->SubsHelper.m_dwFlags & ISF_STARTSUBSCRIBED))
  1348. {
  1349. HRESULT hrTmp = pisdata->SubsHelper.DoShellExtInit(pisdata->GetIntshcut()->GetInitDataObject());
  1350. if (SUCCEEDED(hrTmp))
  1351. {
  1352. ISubscriptionMgr2 *pSubsMgr2;
  1353. hrTmp = pisdata->SubsHelper.GetSubsMgr2(&pSubsMgr2, FIEF_FLAG_PEEK | FIEF_FLAG_FORCE_JITUI);
  1354. if (SUCCEEDED(hrTmp))
  1355. {
  1356. IShellPropSheetExt *pspse;
  1357. hrTmp = pSubsMgr2->QueryInterface(IID_PPV_ARG(IShellPropSheetExt, &pspse));
  1358. if (SUCCEEDED(hrTmp))
  1359. {
  1360. hrTmp = pspse->AddPages(pfnAddPage, lParam);
  1361. pspse->Release();
  1362. }
  1363. pSubsMgr2->Release();
  1364. }
  1365. }
  1366. }
  1367. }
  1368. if (FAILED(hr))
  1369. {
  1370. delete pisdata;
  1371. pisdata = NULL;
  1372. }
  1373. }
  1374. return hr;
  1375. }
  1376. // IShellExtInit::Initialize method for Intshcut
  1377. STDMETHODIMP Intshcut::Initialize(LPCITEMIDLIST pcidlFolder, IDataObject * pido, HKEY hkeyProgID)
  1378. {
  1379. HRESULT hr;
  1380. STGMEDIUM stgmed;
  1381. FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  1382. ASSERT(NULL != pido);
  1383. if (m_pInitDataObject)
  1384. {
  1385. m_pInitDataObject->Release();
  1386. }
  1387. m_pInitDataObject = pido;
  1388. m_pInitDataObject->AddRef();
  1389. hr = pido->GetData(&fmtetc, &stgmed);
  1390. if (hr == S_OK)
  1391. {
  1392. TCHAR szPath[MAX_PATH];
  1393. if (DragQueryFile((HDROP)stgmed.hGlobal, 0, szPath, SIZECHARS(szPath)))
  1394. {
  1395. m_fProbablyDefCM = TRUE;
  1396. hr = LoadFromFile(szPath);
  1397. }
  1398. ReleaseStgMedium(&stgmed);
  1399. }
  1400. return(hr);
  1401. }
  1402. // IShellPropSheetExt::AddPages method for Intshcut
  1403. STDMETHODIMP Intshcut::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
  1404. {
  1405. ASSERT(IS_VALID_STRUCT_PTR(this, CIntshcut));
  1406. ASSERT(IS_VALID_CODE_PTR(pfnAddPage, LPFNADDPROPSHEETPAGE));
  1407. HRESULT hres = AddISPS(this, pfnAddPage, lParam);
  1408. if (SUCCEEDED(hres))
  1409. {
  1410. // Make the Internet Shortcut page be the default page
  1411. hres = ResultFromShort(1);
  1412. }
  1413. return hres;
  1414. }
  1415. STDMETHODIMP Intshcut::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplaceWith, LPARAM lParam)
  1416. {
  1417. return E_NOTIMPL;
  1418. }