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.

2028 lines
74 KiB

  1. #include "priv.h"
  2. #include <mstask.h>
  3. #include "favorite.h"
  4. #include "iehelpid.h"
  5. #ifdef UNIX
  6. #include "subsmgr.h"
  7. #else
  8. #include "webcheck.h"
  9. #endif
  10. #include "chanmgr.h"
  11. #include "chanmgrp.h"
  12. #include "resource.h"
  13. #include <platform.h>
  14. #include <mobsync.h>
  15. #include <mobsyncp.h>
  16. #include <mluisupp.h>
  17. #ifdef UNIX
  18. #include "unixstuff.h"
  19. #include "shalias.h"
  20. #endif
  21. UINT IE_ErrorMsgBox(IShellBrowser* psb,
  22. HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam,
  23. UINT idResource, UINT wFlags);
  24. void ReplaceTransplacedControls (HWND hDlgMaster, HWND hDlgTemplate);
  25. ///////////////////////////////////////////////////////////////////////
  26. // helper function for DoOrganizeFavDlgEx
  27. // the org favs dialog returns a list of null terminated strings containing
  28. // all the urls to update.
  29. void OrgFavSynchronize(HWND hwnd, VARIANT *pvarUrlsToSynch)
  30. {
  31. #ifndef DISABLE_SUBSCRIPTIONS
  32. ASSERT(pvarUrlsToSynch);
  33. //if there are no urls to update, it's an empty string so bail
  34. if ( (pvarUrlsToSynch->vt == VT_BSTR) && (pvarUrlsToSynch->bstrVal) &&
  35. *(pvarUrlsToSynch->bstrVal) )
  36. {
  37. PWSTR pwzUrls = pvarUrlsToSynch->bstrVal;
  38. ISubscriptionMgr *psm;
  39. if (SUCCEEDED(JITCoCreateInstance(CLSID_SubscriptionMgr, NULL,
  40. CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr,
  41. (void**)&psm, hwnd, FIEF_FLAG_FORCE_JITUI)))
  42. {
  43. //SysStringLen doesn't look at the string contents, just the cb of the alloc
  44. while (pwzUrls < (pvarUrlsToSynch->bstrVal + SysStringLen(pvarUrlsToSynch->bstrVal)))
  45. {
  46. psm->UpdateSubscription(pwzUrls);
  47. pwzUrls += lstrlenW(pwzUrls) + 1;
  48. }
  49. psm->Release();
  50. }
  51. }
  52. #endif /* !DISABLE_SUBSCRIPTIONS */
  53. }
  54. /*
  55. * DoOrganizeFavDlgEx
  56. *
  57. * HWND hwnd Owner window for the dialog.
  58. * LPWSTR pszInitDir Dir to use as root. if null, the user's favorites dir is used.
  59. *
  60. * Returns:
  61. * BOOL. TRUE if succeeds. FALSE otherwise.
  62. *
  63. */
  64. BOOL WINAPI DoOrganizeFavDlgEx(HWND hwnd, LPWSTR pszInitDir)
  65. {
  66. // The easy answer would be to add an about:OrganizeFavorites that
  67. // gets registered in our selfreg.inx file. Unfortunately, multilanguage
  68. // support requires us to generate the URL on the fly.
  69. WCHAR wszUrl[6 + MAX_PATH + 11 + 1]; // "res://MAX_PATH/orgfav.dlg"
  70. StrCpyNW(wszUrl, L"res://", 7);
  71. #ifndef UNIX
  72. GetModuleFileNameWrapW(MLGetHinst(), wszUrl+6, MAX_PATH);
  73. #else
  74. // IEUNIX : GetModuleFilename returns /vobs/...../libbrowseui.so
  75. // We need actual dllname here.
  76. StrCpyNW(wszUrl + 6, L"shdocvw.dll" , 12);
  77. #endif
  78. StrCatW(wszUrl, L"/orgfav.dlg");
  79. IMoniker *pmk;
  80. if (SUCCEEDED(CreateURLMoniker(NULL, wszUrl, &pmk)))
  81. {
  82. ASSERT(pmk);
  83. VARIANT varUrlsToSynch, varInitialDir;
  84. BSTR bstrInitDir;
  85. VariantInit(&varUrlsToSynch);
  86. VariantInit(&varInitialDir);
  87. if (pszInitDir)
  88. {
  89. bstrInitDir = SysAllocString(pszInitDir);
  90. if (bstrInitDir)
  91. {
  92. varInitialDir.vt = VT_BSTR;
  93. varInitialDir.bstrVal = bstrInitDir;
  94. }
  95. }
  96. ShowHTMLDialog(hwnd, pmk, &varInitialDir, L"Resizable=1", &varUrlsToSynch);
  97. OrgFavSynchronize(hwnd, &varUrlsToSynch);
  98. if (pszInitDir && bstrInitDir)
  99. SysFreeString(bstrInitDir);
  100. VariantClear(&varUrlsToSynch);
  101. pmk->Release();
  102. return TRUE;
  103. }
  104. else
  105. return FALSE;
  106. }
  107. /*
  108. * DoOrganizeFavDlg
  109. *
  110. * This API is exported so that it may be called by explorer and mshtml in
  111. * addition to being called internally by shdocvw.
  112. *
  113. * HWND hwndOwner Owner window for the dialog.
  114. * LPWSTR pszInitDir Dir to use as root. if null, the user's favorites dir is used.
  115. *
  116. * Returns:
  117. * BOOL. TRUE if succeeds. FALSE otherwise.
  118. *
  119. */
  120. BOOL WINAPI DoOrganizeFavDlg(HWND hwnd, LPSTR pszInitDir)
  121. {
  122. BOOL fRet;
  123. WCHAR szInitDir[MAX_PATH];
  124. if (pszInitDir)
  125. {
  126. SHAnsiToUnicode(pszInitDir, szInitDir, ARRAYSIZE(szInitDir));
  127. fRet = DoOrganizeFavDlgEx(hwnd, szInitDir);
  128. }
  129. else
  130. {
  131. fRet = DoOrganizeFavDlgEx(hwnd, NULL);
  132. }
  133. return fRet;
  134. }
  135. BOOL WINAPI DoOrganizeFavDlgW(HWND hwnd, LPWSTR pszInitDir)
  136. {
  137. return DoOrganizeFavDlgEx(hwnd, pszInitDir);
  138. }
  139. #define ADDTOFAVPROP TEXT("SHDOC_ATFPROP")
  140. typedef enum { ATF_FAVORITE,
  141. ATF_CHANNEL,
  142. ATF_CHANNEL_MODIFY,
  143. ATF_CHANNEL_SOFTDIST
  144. } FAVDLGTYPE;
  145. typedef struct _ADDTOFAV
  146. {
  147. PTSTR pszInitDir;
  148. UINT cchInitDir;
  149. PTSTR pszFile;
  150. UINT cchFile;
  151. LPITEMIDLIST pidl;
  152. LPITEMIDLIST pidlSelected;
  153. LPCITEMIDLIST pidlFavorite;
  154. FAVDLGTYPE iDlgType;
  155. SUBSCRIPTIONINFO siSubsInProg;
  156. SUBSCRIPTIONTYPE subsType;
  157. BOOL bIsSoftdist;
  158. BOOL bStartSubscribed;
  159. BOOL bSubscribed;
  160. } ADDTOFAV;
  161. BOOL IsSubscribed(ADDTOFAV *patf);
  162. typedef struct _BFFFavSubStruct
  163. {
  164. WNDPROC lpfnOldWndProc;
  165. HWND hwndNew;
  166. HWND hwndTV;
  167. HWND hwndSave;
  168. HWND hTemplateWnd;
  169. ADDTOFAV * patf;
  170. RECT rcRestored;
  171. } BFFFAVSUBSTRUCT;
  172. BOOL_PTR CALLBACK NewFavDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  173. {
  174. switch (uMsg)
  175. {
  176. case WM_INITDIALOG:
  177. {
  178. HWND hwnd;
  179. ASSERT(lParam);
  180. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  181. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  182. // cross-lang platform support
  183. SHSetDefaultDialogFont(hDlg, IDD_NAME);
  184. hwnd = GetDlgItem(hDlg, IDD_NAME);
  185. #ifndef UNIX
  186. SendMessage(hwnd, EM_LIMITTEXT, MAX_PATH - 1, 0);
  187. #else
  188. // IEUNIX : file/dir name on unix is limited to _MAX_FNAME.
  189. SendMessage(hwnd, EM_LIMITTEXT, (WPARAM)(_MAX_FNAME - 1), (LPARAM)0);
  190. #endif
  191. EnableOKButtonFromID(hDlg, IDD_NAME);
  192. break;
  193. }
  194. case WM_DESTROY:
  195. SHRemoveDefaultDialogFont(hDlg);
  196. return FALSE;
  197. case WM_COMMAND:
  198. switch (GET_WM_COMMAND_ID(wParam, lParam))
  199. {
  200. case IDD_NAME:
  201. {
  202. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_UPDATE)
  203. {
  204. LPTSTR lpstrName = (LPTSTR) GetWindowLongPtr(hDlg, DWLP_USER);
  205. EnableOKButtonFromID(hDlg, IDD_NAME);
  206. GetDlgItemText(hDlg, IDD_NAME, lpstrName, MAX_PATH);
  207. }
  208. break;
  209. }
  210. case IDOK:
  211. {
  212. TCHAR szTmp[MAX_PATH];
  213. StrCpyN(szTmp, (LPTSTR)GetWindowLongPtr(hDlg, DWLP_USER), ARRAYSIZE(szTmp));
  214. if (PathCleanupSpec(NULL,szTmp))
  215. {
  216. HWND hwnd;
  217. MLShellMessageBox(
  218. hDlg,
  219. MAKEINTRESOURCE(IDS_FAVS_INVALIDFN),
  220. MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
  221. MB_OK | MB_ICONHAND);
  222. hwnd = GetDlgItem(hDlg, IDD_NAME);
  223. SetWindowText(hwnd, TEXT('\0'));
  224. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  225. SetFocus(hwnd);
  226. break;
  227. }
  228. }
  229. // fall through
  230. case IDCANCEL:
  231. EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
  232. break;
  233. default:
  234. return FALSE;
  235. }
  236. break;
  237. default:
  238. return FALSE;
  239. }
  240. return TRUE;
  241. }
  242. // BOGUS - these id's stolen from SHBrowseForFolder implementation
  243. #define IDD_FOLDERLIST 0x3741
  244. #define IDD_BROWSETITLE 0x3742
  245. #define IDD_BROWSESTATUS 0x3743
  246. const static DWORD aAddToFavHelpIDs[] = { // Context Help IDs
  247. IDC_FAVORITE_DESC, NO_HELP,
  248. IDD_BROWSETITLE, NO_HELP,
  249. IDD_BROWSESTATUS, NO_HELP,
  250. IDC_FAVORITE_ICON, NO_HELP,
  251. IDC_NAMESTATIC, IDH_NAMEEDIT,
  252. IDC_FOLDERLISTSTATIC, IDH_BROWSELIST,
  253. IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER, IDH_BROWSELIST,
  254. IDC_FAVORITE_NEWFOLDER, IDH_CREATEIN,
  255. IDC_SUBSCRIBE_CUSTOMIZE, IDH_CHANNEL_SUBSCR_CUST_BUTTON,
  256. IDC_FAVORITE_CREATEIN, IDH_NEWFOLDER,
  257. IDC_FAVORITE_NAME, IDH_NAMEEDIT,
  258. IDC_MAKE_OFFLINE, IDH_MAKE_AVAIL_OFFLINE,
  259. 0, 0
  260. };
  261. const static DWORD aAddToChanHelpIDs[] = { // Context Help IDs
  262. IDC_FAVORITE_DESC, NO_HELP,
  263. IDD_BROWSETITLE, NO_HELP,
  264. IDD_BROWSESTATUS, NO_HELP,
  265. IDC_FAVORITE_ICON, NO_HELP,
  266. IDC_NAMESTATIC, IDH_NAMEEDIT,
  267. IDC_FOLDERLISTSTATIC, IDH_BROWSELIST,
  268. IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER, IDH_BROWSELIST,
  269. IDC_FAVORITE_NEWFOLDER, IDH_CREATEIN,
  270. IDC_SUBSCRIBE_CUSTOMIZE, IDH_CHANNEL_SUBSCR_CUST_BUTTON,
  271. IDC_FAVORITE_CREATEIN, IDH_NEWFOLDER,
  272. IDC_FAVORITE_NAME, IDH_NAMEEDIT,
  273. IDC_MAKE_OFFLINE, IDH_MAKE_AVAIL_OFFLINE,
  274. 0, 0
  275. };
  276. /*
  277. * Makes sure the item being added to favorites doesn't already exist. If it does,
  278. * puts up a message box to have the user confirm whether they want to overwrite
  279. * the old favorite or not.
  280. */
  281. BOOL ConfirmAddToFavorites(HWND hwndOwner, ADDTOFAV * patf)
  282. {
  283. BOOL fRet = FALSE;
  284. BOOL fExists;
  285. int iPromptString = 0;
  286. if (patf->subsType == SUBSTYPE_CHANNEL)
  287. {
  288. //patf->pszInitDir now contains the path with a .url on the end; the channel
  289. //will be stored in a directory of that name without .url. Strip it.
  290. TCHAR szPath[MAX_PATH];
  291. StrCpyN(szPath, patf->pszInitDir, ARRAYSIZE(szPath));
  292. PathRemoveExtension (szPath);
  293. fExists = PathFileExists(szPath);
  294. iPromptString = IDS_CHANNELS_FILEEXISTS;
  295. }
  296. else
  297. {
  298. fExists = PathFileExists(patf->pszInitDir);
  299. iPromptString = IDS_FAVS_FILEEXISTS;
  300. }
  301. fRet = ! fExists ||
  302. (MLShellMessageBox(
  303. hwndOwner,
  304. MAKEINTRESOURCE(iPromptString),
  305. NULL, //use owner's title
  306. MB_ICONQUESTION | MB_YESNO) == IDYES);
  307. return fRet;
  308. }
  309. //
  310. // Get the localized date and time
  311. //
  312. typedef HRESULT (*PFVARIANTTIMETOSYSTEMTIME)(DOUBLE, LPSYSTEMTIME);
  313. //
  314. // Subscribe to the current site.
  315. //
  316. HRESULT SubscribeToSite(HWND hwnd, LPCTSTR pszFile, LPCITEMIDLIST pidl, DWORD dwFlags,
  317. SUBSCRIPTIONINFO* pSubs, SUBSCRIPTIONTYPE subsType)
  318. {
  319. #ifndef DISABLE_SUBSCRIPTIONS
  320. TCHAR szURL[MAX_URL_STRING];
  321. ISubscriptionMgr *pISubscriptionMgr;
  322. //
  323. // Get a displayable URL.
  324. //
  325. IEGetDisplayName(pidl, szURL, SHGDN_FORPARSING);
  326. //
  327. // Get a pointer to the subscription manager.
  328. //
  329. HRESULT hr = JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  330. IID_ISubscriptionMgr,
  331. (void**)&pISubscriptionMgr, hwnd, FIEF_FLAG_FORCE_JITUI);
  332. if (SUCCEEDED(hr))
  333. {
  334. //
  335. // Create a default subscription.
  336. //
  337. BSTR bstrURL = SysAllocStringT(szURL);
  338. if (bstrURL)
  339. {
  340. BSTR bstrName = SysAllocStringT(pszFile);
  341. if (bstrName)
  342. {
  343. hr = pISubscriptionMgr->CreateSubscription(hwnd,
  344. bstrURL, bstrName, dwFlags, subsType, pSubs);
  345. SysFreeString(bstrName);
  346. }
  347. SysFreeString(bstrURL);
  348. }
  349. //
  350. // Clean up.
  351. //
  352. pISubscriptionMgr->Release();
  353. }
  354. return hr;
  355. #else /* !DISABLE_SUBSCRIPTIONS */
  356. return E_FAIL;
  357. #endif /* !DISABLE_SUBSCRIPTIONS */
  358. }
  359. //
  360. // Create in-memory subscription, but only optionally save it to subscription manager
  361. //
  362. BOOL StartSiteSubscription (HWND hwnd, ADDTOFAV* patf, BOOL bFinalize)
  363. {
  364. #ifndef DISABLE_SUBCRIPTIONS
  365. //update the changes-only flag (radio buttons here are, effectively, direct access to this flag)
  366. if (patf->subsType == SUBSTYPE_CHANNEL || patf->subsType == SUBSTYPE_DESKTOPCHANNEL)
  367. {
  368. //if set, leave alone; otherwise, put to full download
  369. if (!(patf->siSubsInProg.fChannelFlags & CHANNEL_AGENT_PRECACHE_SOME))
  370. patf->siSubsInProg.fChannelFlags |= CHANNEL_AGENT_PRECACHE_ALL;
  371. patf->siSubsInProg.fUpdateFlags |= SUBSINFO_CHANNELFLAGS | SUBSINFO_SCHEDULE;
  372. }
  373. if (S_OK != SubscribeToSite(hwnd, patf->pszFile, patf->pidlFavorite,
  374. bFinalize ? CREATESUBS_NOUI | CREATESUBS_FROMFAVORITES : CREATESUBS_NOSAVE,
  375. &patf->siSubsInProg, patf->subsType))
  376. {
  377. return FALSE;
  378. }
  379. return TRUE;
  380. #else /* !DISABLE_SUBSCRIPTIONS */
  381. return FALSE;
  382. #endif /* !DISABLE_SUBSCRIPTIONS */
  383. }
  384. /*
  385. Combines the path and the filename of the favorite
  386. and puts it into patf->pszInitDir, so that it has the fully qualified pathname.
  387. */
  388. #define SZ_URLEXT TEXT(".url")
  389. #define CCH_URLEXT SIZECHARS(SZ_URLEXT)
  390. BOOL QualifyFileName(ADDTOFAV *patf)
  391. {
  392. TCHAR szTemp[MAX_PATH];
  393. BOOL fRet = FALSE;
  394. LPTSTR pstr;
  395. // Can we safely add the extension to this?
  396. if (lstrlen(patf->pszFile) < (int)(patf->cchFile - CCH_URLEXT))
  397. {
  398. //Add extension .url if its not already there
  399. //This is to prevent strings like "com" in "www.microsoft.com" from being interpreted as extensions
  400. pstr = PathFindExtension(patf->pszFile);
  401. if (!pstr || (pstr && StrCmpI(pstr, SZ_URLEXT)))// && StrCmpI(pstr, SZ_CDFEXT)))
  402. StrCatBuff(patf->pszFile, SZ_URLEXT, patf->cchFile);
  403. // Is there a folder associated with the filename?
  404. if (patf->pidlSelected && SHGetPathFromIDList(patf->pidlSelected, szTemp))
  405. {
  406. // Yes
  407. if (PathCombine(szTemp, szTemp, patf->pszFile))
  408. {
  409. if ((UINT)lstrlen(szTemp) < patf->cchInitDir)
  410. {
  411. StrCpyN(patf->pszInitDir, szTemp, patf->cchInitDir);
  412. fRet = TRUE;
  413. }
  414. }
  415. }
  416. }
  417. return fRet;
  418. }
  419. BOOL SubscriptionFailsChannelAuthentication (HWND hDlg, SUBSCRIPTIONINFO* psi)
  420. {
  421. #ifndef DISABLE_SUBSCRIPTIONS
  422. if (psi->bNeedPassword && !(psi->bstrPassword && psi->bstrPassword[0]
  423. && psi->bstrUserName && psi->bstrUserName[0]))
  424. { //password would be required
  425. if (IsDlgButtonChecked (hDlg, IDC_MAKE_OFFLINE))
  426. { //they're trying to subscribe... WRONG!
  427. MLShellMessageBox(
  428. hDlg,
  429. MAKEINTRESOURCE(IDS_NEED_CHANNEL_PASSWORD),
  430. NULL,
  431. MB_ICONINFORMATION | MB_OK);
  432. return TRUE;
  433. }
  434. }
  435. return FALSE;
  436. #else /* !DISABLE_SUBSCRIPTIONS */
  437. return FALSE;
  438. #endif /* !DISABLE_SUBSCRIPTIONS */
  439. }
  440. LRESULT CALLBACK BFFFavSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  441. {
  442. BFFFAVSUBSTRUCT * pbffFS = (BFFFAVSUBSTRUCT *)GetProp(hwnd, ADDTOFAVPROP);
  443. WNDPROC lpfnOldWndProc = pbffFS->lpfnOldWndProc;
  444. RECT rc;
  445. switch (uMsg) {
  446. case WM_COMMAND:
  447. // Intercept the command for the New Folder button we hacked into
  448. // the SHBrowseForFolder dialog.
  449. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  450. case IDC_FAVORITE_NAME:
  451. {
  452. HWND hwndedit;
  453. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
  454. EnableOKButtonFromID(hwnd, IDC_FAVORITE_NAME);
  455. hwndedit = GetDlgItem(hwnd, IDC_FAVORITE_NAME);
  456. SendMessage(hwndedit, EM_LIMITTEXT, MAX_PATH - 1, 0);
  457. break;
  458. }
  459. #ifndef UNIX
  460. // IEUNIX (OFFLINE) : No offline ability
  461. case IDC_MAKE_OFFLINE:
  462. EnableWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE),
  463. IsDlgButtonChecked(hwnd, IDC_MAKE_OFFLINE));
  464. break;
  465. case IDC_SUBSCRIBE_CUSTOMIZE:
  466. //need to create -- but not store -- subscription
  467. if (StartSiteSubscription (hwnd, pbffFS->patf, FALSE))
  468. SendMessage (hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDOK), TRUE);
  469. break;
  470. #endif
  471. case IDC_FAVORITE_NEWFOLDER:
  472. TCHAR szPath[MAX_PATH];
  473. TCHAR szName[MAX_PATH];
  474. HWND hwndTV;
  475. TV_ITEM tv_item;
  476. // Bring up the Create New Folder dialog
  477. if ((DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_NEWFOLDER), hwnd,
  478. NewFavDlgProc, (LPARAM)szName) == IDOK) &&
  479. (SHGetPathFromIDList(pbffFS->patf->pidlSelected, szPath)) &&
  480. ((lstrlen(szPath) + lstrlen(szName) + 1) < MAX_PATH))
  481. {
  482. PathCombine(szPath, szPath, szName);
  483. BOOL bSuccess = FALSE;
  484. #ifdef CREATEFOLDERSINCHANNELSDIR
  485. if (pbffFS->patf->subsType == SUBSTYPE_CHANNEL)
  486. {
  487. ASSERT(0); //should not be possible in this release
  488. //(I removed this button in the .rc dialogs for channels)
  489. //Note: to make this work in a future release, reenable this code -- it's
  490. //functional. But the folders created here show up ugly in the channel bar
  491. //(just a default folder icon) and if you click on them, you get a shell
  492. //Explorer window instead of a theater-mode browser window. The reason
  493. //for this second happening is that the desktop.ini file created in the new
  494. //folder has no URL=. To remedy this: AddCategory() has to be fixed so it
  495. //doesn't interpret the pszURL argument as a UNC name (I was using a resouce moniker
  496. //pointing into cdfview.dll for the html target), and the OC hosted by the default
  497. //html pages has to learn how to be hosted from a html page without a path -- or we
  498. //actually have to create an html page in the new directory, which is messy.
  499. IChannelMgr* pChanMgr;
  500. HRESULT hr;
  501. hr = JITCoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
  502. IID_IChannelMgr, (void**)&pChanMgr,
  503. hwnd, FIEF_FLAG_FORCE_JITUI);
  504. if (SUCCEEDED(hr))
  505. {
  506. IChannelMgrPriv* pChanMgrPriv;
  507. hr = pChanMgr->QueryInterface (IID_IChannelMgrPriv, (void**)&pChanMgrPriv);
  508. if (SUCCEEDED(hr))
  509. {
  510. char szCFPath[MAX_PATH];
  511. WCHAR wszFolder[MAX_PATH];
  512. IChannelMgrPriv::CHANNELFOLDERLOCATION cflLocation =
  513. (pbffFS->patf->iDlgType == ATF_CHANNEL_SOFTDIST ?
  514. IChannelMgrPriv::CF_SOFTWAREUPDATE :
  515. IChannelMgrPriv::CF_CHANNEL);
  516. hr = pChanMgrPriv->GetChannelFolderPath (szCFPath, ARRAYSIZE(szCFPath), cflLocation);
  517. int cchCommon = PathCommonPrefix (szPath, szCFPath, NULL);
  518. AnsiToUnicode (szPath + cchCommon, wszFolder, ARRAYSIZE(wszFolder));
  519. CHANNELCATEGORYINFO info = {0};
  520. info.cbSize = sizeof(info);
  521. info.pszTitle = wszFolder;
  522. bSuccess = SUCCEEDED (pChanMgr->AddCategory (&info));
  523. pChanMgrPriv->Release();
  524. }
  525. pChanMgr->Release();
  526. }
  527. }
  528. else
  529. #endif
  530. {
  531. bSuccess = CreateDirectory(szPath, NULL);
  532. }
  533. if (bSuccess)
  534. {
  535. // This code assumes the layout of SHBrowseForFolder!
  536. // directory successfully created, must notify registered shell components.
  537. SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, szPath, NULL);
  538. // Get the TreeView control
  539. hwndTV = GetDlgItem(hwnd, IDD_FOLDERLIST);
  540. if (hwndTV) {
  541. HTREEITEM hti = TreeView_GetSelection(hwndTV);
  542. // Take the selected item and reset it, then reexpand it so
  543. // that it shows the new directory we just created.
  544. tv_item.mask = TVIF_CHILDREN;
  545. tv_item.hItem = hti;
  546. tv_item.cChildren = -1;
  547. TreeView_SetItem(hwndTV, &tv_item);
  548. TreeView_Expand(hwndTV, hti, TVE_COLLAPSE | TVE_COLLAPSERESET);
  549. TreeView_Expand(hwndTV, hti, TVE_EXPAND);
  550. // Find the new directory we just created and select it by
  551. // walking the tree from the selected item down.
  552. if (hti = TreeView_GetChild(hwndTV, hti)) {
  553. tv_item.mask = TVIF_TEXT;
  554. tv_item.pszText = szPath;
  555. tv_item.cchTextMax = MAX_PATH;
  556. do {
  557. tv_item.hItem = hti;
  558. TreeView_GetItem(hwndTV, &tv_item);
  559. if (StrCmp(szName, szPath) == 0) {
  560. TreeView_Select(hwndTV, hti, TVGN_CARET);
  561. break;
  562. }
  563. } while (hti = TreeView_GetNextSibling(hwndTV, hti));
  564. }
  565. SetFocus(hwndTV);
  566. }
  567. } else {
  568. LPVOID lpMsgBuf;
  569. FormatMessage(
  570. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  571. NULL,
  572. GetLastError(),
  573. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  574. (LPTSTR) &lpMsgBuf,
  575. 0,
  576. NULL
  577. );
  578. MLShellMessageBox(
  579. hwnd,
  580. (LPCTSTR)lpMsgBuf,
  581. MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
  582. MB_ICONINFORMATION | MB_OK);
  583. // Free the buffer.
  584. LocalFree( lpMsgBuf );
  585. lpMsgBuf = NULL;
  586. }
  587. }
  588. break;
  589. case IDOK:
  590. // first, make sure they're not trying to subscribe to an authenticated
  591. // channel without entering a password.
  592. if (SubscriptionFailsChannelAuthentication (hwnd, &pbffFS->patf->siSubsInProg))
  593. return FALSE;
  594. // Retrieve the text from the Name edit control.
  595. GetDlgItemText(hwnd, IDC_FAVORITE_NAME, pbffFS->patf->pszFile, pbffFS->patf->cchFile);
  596. { // Just a block to declare variables
  597. BOOL fTooBig = TRUE; // assume failure
  598. TCHAR szTmp[MAX_PATH];
  599. if (lstrlen(pbffFS->patf->pszFile) < MAX_PATH)
  600. {
  601. StrCpyN(szTmp, pbffFS->patf->pszFile, ARRAYSIZE(szTmp));
  602. // PathCleanupSpec deals with MAX_PATH buffers, so we should be fine
  603. if (PathCleanupSpec(NULL, szTmp))
  604. {
  605. MLShellMessageBox(
  606. hwnd,
  607. MAKEINTRESOURCE(IDS_FAVS_INVALIDFN),
  608. MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
  609. MB_OK | MB_ICONHAND);
  610. return FALSE;
  611. }
  612. // Make sure the name is unique and if not, that the user has
  613. // specified that it is OK to override.
  614. if (QualifyFileName(pbffFS->patf))
  615. {
  616. if (!ConfirmAddToFavorites(hwnd, pbffFS->patf))
  617. return FALSE;
  618. // Bogus hack since the ATF stuff is only half done
  619. // Depending on which dlg is shown, look for the appropriate
  620. // check.
  621. if (IsDlgButtonChecked (hwnd, IDC_MAKE_OFFLINE))
  622. {
  623. //they want to subscribe! save subscription we already have in memory
  624. //trouble is, pbffFS->patf->pszFile ends in a bogus .url
  625. TCHAR* pszTemp = pbffFS->patf->pszFile;
  626. TCHAR szNoExt[MAX_PATH];
  627. StrCpyN(szNoExt, pbffFS->patf->pszFile, ARRAYSIZE(szNoExt));
  628. pbffFS->patf->pszFile = szNoExt;
  629. PathRemoveExtension (szNoExt);
  630. pbffFS->patf->bSubscribed =
  631. StartSiteSubscription (hwnd, pbffFS->patf, TRUE);
  632. pbffFS->patf->pszFile = pszTemp;
  633. }
  634. else if (pbffFS->patf->bStartSubscribed)
  635. {
  636. // If we started subscribed and they unchecked make available
  637. // offline, then delete the subscription.
  638. ISubscriptionMgr* pSubsMgr;
  639. if (SUCCEEDED (CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  640. IID_ISubscriptionMgr, (void**)&pSubsMgr)))
  641. {
  642. //url is in patf->pidlFavorite
  643. WCHAR wszURL[MAX_URL_STRING];
  644. IEGetDisplayName(pbffFS->patf->pidlFavorite, wszURL, SHGDN_FORPARSING);
  645. pSubsMgr->DeleteSubscription(wszURL, NULL);
  646. pSubsMgr->Release();
  647. }
  648. }
  649. // Enable and set focus to the tree view so that it is sure to
  650. // be selected so that SHBrowseForFolder will return a pidl.
  651. EnableWindow(pbffFS->hwndTV, TRUE);
  652. SetFocus(pbffFS->hwndTV);
  653. fTooBig = FALSE;
  654. }
  655. }
  656. #ifdef UNIX_FEATURE_ALIAS
  657. if( !fTooBig )
  658. {
  659. TCHAR alias[MAX_ALIAS_LENGTH];
  660. TCHAR szThisURL[MAX_URL_STRING];
  661. HDPA aliasList = GetGlobalAliasList();
  662. if( aliasList )
  663. {
  664. #ifdef UNICODE
  665. // TODO :
  666. #else
  667. // Retrieve the text from the Alias edit control.
  668. GetDlgItemText(hwnd, IDC_ALIAS_NAME, alias, MAX_ALIAS_LENGTH-1);
  669. IEGetDisplayName(pbffFS->patf->pidlFavorite,
  670. szThisURL, SHGDN_FORPARSING);
  671. if(AddAliasToListA( aliasList, alias, szThisURL, hwnd ))
  672. SaveAliases(aliasList);
  673. #endif
  674. }
  675. }
  676. #endif /* UNIX_FEATURE_ALIAS */
  677. if (fTooBig)
  678. {
  679. MLShellMessageBox(
  680. hwnd,
  681. MAKEINTRESOURCE(IDS_FAVS_FNTOOLONG),
  682. MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
  683. MB_OK | MB_ICONHAND);
  684. return FALSE;
  685. }
  686. }
  687. break;
  688. case IDC_FAVORITE_CREATEIN:
  689. // The advanced button has been clicked. Enable/disable the tree view
  690. // and New button, set focus to the tree view or ok button, disable the advanced
  691. // button and then resize the dialog.
  692. {
  693. BOOL fExpanding = !IsWindowEnabled(GetDlgItem(hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER)); //random control that gets enabled when dialog expanded
  694. TCHAR szBuffer[100];
  695. EnableWindow(pbffFS->hwndTV, fExpanding);
  696. //don't show New Folder button for channels in the channels folder,
  697. // see code for case IDC_FAVORITE_NEWFOLDER for why
  698. if (fExpanding && pbffFS->patf->subsType == SUBSTYPE_CHANNEL)
  699. {
  700. LPITEMIDLIST pidlFavs = NULL;
  701. TCHAR tzFavsPath[MAX_PATH];
  702. if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_FAVORITES, &pidlFavs))
  703. && SUCCEEDED(SHGetNameAndFlags(pidlFavs, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, tzFavsPath, SIZECHARS(tzFavsPath), NULL))
  704. && StrCmpNI(tzFavsPath, pbffFS->patf->pszInitDir, ARRAYSIZE(tzFavsPath))==0)
  705. {
  706. EnableWindow(pbffFS->hwndNew, TRUE);
  707. }
  708. if(pidlFavs)
  709. ILFree(pidlFavs);
  710. }
  711. else
  712. EnableWindow(pbffFS->hwndNew, fExpanding);
  713. GetWindowRect(hwnd, &rc);
  714. if (fExpanding)
  715. {
  716. int lRet = MLLoadString(IDS_FAVS_ADVANCED_COLLAPSE, szBuffer, ARRAYSIZE(szBuffer));
  717. ASSERT(lRet);
  718. SetFocus(pbffFS->hwndTV);
  719. MoveWindow(hwnd, rc.left, rc.top,
  720. pbffFS->rcRestored.right - pbffFS->rcRestored.left,
  721. pbffFS->rcRestored.bottom - pbffFS->rcRestored.top, TRUE);
  722. }
  723. else
  724. {
  725. int lRet = MLLoadString(IDS_FAVS_ADVANCED_EXPAND, szBuffer, ARRAYSIZE(szBuffer));
  726. ASSERT(lRet);
  727. SetFocus(GetDlgItem(hwnd, IDC_FAVORITE_NAME));
  728. MoveWindow(hwnd, rc.left, rc.top,
  729. pbffFS->rcRestored.right - pbffFS->rcRestored.left,
  730. pbffFS->rcRestored.bottom - pbffFS->rcRestored.top, TRUE);
  731. // hide the bottom part of the dialog
  732. int cx, cy;
  733. RECT rc;
  734. GetWindowRect (GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), &rc);
  735. cy = rc.top;
  736. GetWindowRect (hwnd, &rc);
  737. cx = rc.right - rc.left;
  738. cy = cy /*top of ctrl*/ - rc.top; /*top of window*/
  739. SetWindowPos (hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
  740. }
  741. SetWindowText(GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN), szBuffer);
  742. break;
  743. }
  744. }
  745. break;
  746. case WM_DESTROY:
  747. {
  748. DWORD dwValue = IsWindowEnabled(GetDlgItem(hwnd, IDC_FAVORITE_NEWFOLDER)); //random control that gets enabled when dialog expanded
  749. SHRegSetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("AddToFavoritesExpanded"),
  750. REG_DWORD, &dwValue, 4, SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  751. ReplaceTransplacedControls (hwnd, pbffFS->hTemplateWnd);
  752. DestroyWindow (pbffFS->hTemplateWnd);
  753. SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) lpfnOldWndProc);
  754. RemoveProp(hwnd, ADDTOFAVPROP);
  755. SHRemoveDefaultDialogFont(hwnd);
  756. ILFree(pbffFS->patf->pidlSelected);
  757. LocalFree((HLOCAL)pbffFS);
  758. pbffFS = NULL;
  759. break;
  760. }
  761. case WM_HELP:
  762. SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  763. HELP_WM_HELP, (DWORD_PTR)(LPTSTR) (pbffFS->patf->iDlgType == ATF_FAVORITE
  764. ? aAddToFavHelpIDs : aAddToChanHelpIDs));
  765. return TRUE;
  766. break;
  767. case WM_CONTEXTMENU:
  768. SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
  769. (DWORD_PTR)(LPVOID) (pbffFS->patf->iDlgType == ATF_FAVORITE
  770. ? aAddToFavHelpIDs : aAddToChanHelpIDs));
  771. return TRUE;
  772. break;
  773. }
  774. return CallWindowProc(lpfnOldWndProc, hwnd, uMsg, wParam, lParam);
  775. }
  776. static const TCHAR szTransplacedProp[] = TEXT("tp");
  777. void ReplaceTransplacedControls (HWND hDlgMaster, HWND hDlgTemplate)
  778. {
  779. /*
  780. * This function moves the controls that we moved from our temporary
  781. * dialog over to SHBrowseForFolder's dialog, back to their original
  782. * home, before they get destroyed. This is because otherwise we have
  783. * problems when destroying the template dialog -- specifically, we get
  784. * a GP fault in user.exe when destroying the edit control, because it
  785. * looks to its parent window to figure out where its data segment is.
  786. *
  787. * Solution: (for safety) -- put everything back where it came from.
  788. * Other possibilities: just move the edit control (by ID) back, or
  789. * move all edit controls back, or use DS_LOCALEDIT for edit controls
  790. * (but this is documented only for use with multiline edits.)
  791. * Or modify SHBrowseForFolder to allow other dialog templates...
  792. * but that's over in shell32.
  793. */
  794. HWND hCtrl = GetWindow (hDlgMaster, GW_CHILD);
  795. while (hCtrl)
  796. {
  797. HWND hNext = GetWindow (hCtrl, GW_HWNDNEXT);
  798. if (GetProp (hCtrl, szTransplacedProp) != NULL)
  799. {
  800. RemoveProp (hCtrl, szTransplacedProp);
  801. SetParent (hCtrl, hDlgTemplate);
  802. }
  803. hCtrl = hNext;
  804. }
  805. }
  806. #define szOriginalWND TEXT("WorkaroundOrigWndProc")
  807. INT_PTR CALLBACK MergeFavoritesDialogControls(HWND hDlgTemplate, UINT uMsg, WPARAM wParam, LPARAM lParam)
  808. {
  809. switch (uMsg)
  810. {
  811. case WM_INITDIALOG:
  812. {
  813. HWND hDlgMaster = (HWND)lParam;
  814. ASSERT (IsWindow (hDlgMaster));
  815. TCHAR szT[200];
  816. RECT rc;
  817. //resize master like us
  818. GetWindowText (hDlgTemplate, szT, ARRAYSIZE(szT));
  819. SetWindowText (hDlgMaster, szT);
  820. GetClientRect (hDlgTemplate, &rc);
  821. AdjustWindowRect (&rc, GetWindowLong (hDlgMaster, GWL_STYLE), FALSE);
  822. SetWindowPos (hDlgMaster, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
  823. SWP_NOMOVE | SWP_NOZORDER);
  824. // a-msadek; If the owned window is mirrored, a dialog with specifed
  825. // coordinates, the dialog get moved to the worng direction
  826. HWND hWndOwner = GetWindow(hDlgMaster, GW_OWNER);
  827. if(IS_WINDOW_RTL_MIRRORED(hWndOwner))
  828. {
  829. RECT rcOwner, rcDlg;
  830. GetWindowRect(hWndOwner, &rcOwner);
  831. GetWindowRect(hDlgMaster, &rcDlg);
  832. SetWindowPos(hDlgMaster, NULL, rcDlg.left - (rcDlg.right - rcOwner.right), rcDlg.top, 0 ,0,
  833. SWP_NOSIZE | SWP_NOZORDER);
  834. }
  835. #if 0 //now we do this as part of the "move controls from template to master" process,
  836. //if we notice that a ctrl with that id already exists. This way we pick up the
  837. //tab order too. If someone decides my hack (SetParent) to change tab order is
  838. //broken, then that code can be nuked and this reenabled.
  839. //position already-existing controls in master like us
  840. int ID_PREEXIST_CTRLS[] = { IDOK_PLACEHOLDER, IDCANCEL_PLACEHOLDER,
  841. IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER };
  842. for (int iCtrl = 0; iCtrl < ARRAYSIZE(ID_PREEXIST_CTRLS); iCtrl++)
  843. {
  844. GetWindowRect (GetDlgItem (hDlgTemplate, ID_PREEXIST_CTRLS[iCtrl]), &rc);
  845. MapWindowPoints (NULL, hDlgTemplate, (LPPOINT)&rc, 2);
  846. MoveWindow (GetDlgItem (hDlgMaster, ID_PREEXIST_CTRLS[iCtrl]),
  847. rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
  848. DestroyWindow (GetDlgItem (hDlgTemplate, ID_PREEXIST_CTRLS[iCtrl]));
  849. }
  850. #endif
  851. //copy other controls from us to master
  852. //find last child
  853. HWND hCtrlTemplate = NULL;
  854. HWND hNextCtrl = GetWindow (hDlgTemplate, GW_CHILD);
  855. if (hNextCtrl) //can't see how this would fail, but...
  856. hCtrlTemplate = GetWindow (hNextCtrl, GW_HWNDLAST);
  857. //have last window in hCtrlTemplate
  858. //now move controls over in reverse order -- they'll end up stacking up in original order from template
  859. while (hCtrlTemplate)
  860. {
  861. hNextCtrl = GetWindow (hCtrlTemplate, GW_HWNDPREV);
  862. DWORD id = GetWindowLong (hCtrlTemplate, GWL_ID);
  863. HWND hCtrlExisting;
  864. if (id != (USHORT)IDC_STATIC && NULL != (hCtrlExisting = GetDlgItem (hDlgMaster, id)))
  865. //it's one of the controls pre-created by SHBrowseForFolder
  866. { //so don't move this one over -- adjust existing control for size, position, tab order
  867. RECT rc;
  868. GetWindowRect (hCtrlTemplate, &rc);
  869. MapWindowPoints (NULL, hDlgTemplate, (LPPOINT)&rc, 2);
  870. SetWindowPos (hCtrlExisting, NULL, rc.left, rc.top,
  871. rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
  872. DestroyWindow (hCtrlTemplate);
  873. //REVIEW
  874. //hack -- send control to end of tab order
  875. SetParent (hCtrlExisting, hDlgTemplate);
  876. SetParent (hCtrlExisting, hDlgMaster);
  877. }
  878. else //we should move this control from template to master
  879. {
  880. SetProp (hCtrlTemplate, szTransplacedProp, (HANDLE)TRUE); //anything -- it's the existence of the prop that we check for
  881. SetParent (hCtrlTemplate, hDlgMaster); //to know to move this control back later
  882. }
  883. hCtrlTemplate = hNextCtrl;
  884. }
  885. // Let Template know about the child so that it can forward WM_COMMAND notifications to it
  886. // to work around the fact that edit controls cache their parent pointers and ignore SetParents
  887. // when it comes to sending parent notifications
  888. SetProp(hDlgTemplate, szOriginalWND, hDlgMaster);
  889. }
  890. break;
  891. case WM_COMMAND:
  892. // Workaround for above bug
  893. SendMessage((HWND)GetProp(hDlgTemplate, szOriginalWND), uMsg, wParam, lParam);
  894. break;
  895. }
  896. return FALSE;
  897. }
  898. int CALLBACK BFFFavCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  899. {
  900. switch (uMsg)
  901. {
  902. case BFFM_INITIALIZED:
  903. {
  904. ADDTOFAV* patf = (ADDTOFAV*)lpData;
  905. ASSERT (patf);
  906. HWND hDlgTemp = CreateDialogParam(MLGetHinst(),
  907. MAKEINTRESOURCE(IDD_ADDTOFAVORITES_TEMPLATE),
  908. NULL, MergeFavoritesDialogControls, (LPARAM)hwnd);
  909. //this results in all the controls being copied over
  910. //if successful, make our other modifications
  911. BFFFAVSUBSTRUCT * pbffFavSubStruct;
  912. if ((IsWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE))) //verify existence of randomly-selected control
  913. && (pbffFavSubStruct = (BFFFAVSUBSTRUCT *) LocalAlloc(LPTR, sizeof(BFFFAVSUBSTRUCT))))
  914. {
  915. //done with template, but don't destroy it:
  916. //see MSKB Q84190, owner/owned vs parent/child -- the children
  917. // of template are now children of master, but still OWNED
  918. // by template, and are destroyed when template is destroyed...
  919. // but we'll just keep template around
  920. // invisibly.
  921. //we'll take care of it when we go away
  922. //Do we need to do SetDefaultDialogFont stuff for localization still, since it all comes from the .rc?
  923. //set up window stuff for subclass:
  924. // Get the TreeView control so we can muck with the style bits and move it down
  925. HWND hwndT;
  926. if (hwndT = GetDlgItem(hwnd, IDD_FOLDERLIST))
  927. {
  928. DWORD dwStyle = GetWindowLong(hwndT, GWL_STYLE);
  929. dwStyle |= TVS_SHOWSELALWAYS;
  930. dwStyle &= ~TVS_LINESATROOT;
  931. SetWindowLong(hwndT, GWL_STYLE, dwStyle);
  932. }
  933. // don't allow subscriptions if the URL is not "http:" protocol, or if already subscribed
  934. TCHAR szURL[MAX_URL_STRING];
  935. if (!patf->pidlFavorite ||
  936. FAILED(IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING)) ||
  937. SHRestricted2(REST_NoAddingSubscriptions, szURL, 0) ||
  938. !IsSubscribable(szURL) ||
  939. !IsFeaturePotentiallyAvailable(CLSID_SubscriptionMgr) ||
  940. !IsBrowserFrameOptionsPidlSet(patf->pidlFavorite, BFO_USE_IE_OFFLINE_SUPPORT))
  941. {
  942. CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 0);
  943. EnableWindow(GetDlgItem (hwnd, IDC_MAKE_OFFLINE), FALSE);
  944. EnableWindow(GetDlgItem (hwnd, IDC_SUBSCRIBE_CUSTOMIZE), FALSE);
  945. }
  946. else if (IsSubscribed(patf))
  947. {
  948. patf->bStartSubscribed = TRUE;
  949. CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 1);
  950. }
  951. else if (patf->bIsSoftdist)
  952. {
  953. CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 1);
  954. }
  955. EnableWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE),
  956. IsDlgButtonChecked(hwnd, IDC_MAKE_OFFLINE));
  957. //set the name
  958. Edit_LimitText(GetDlgItem(hwnd, IDC_FAVORITE_NAME), MAX_PATH - 1);
  959. // Use URL if title string is not displayable
  960. if (SHIsDisplayable(patf->pszFile, g_fRunOnFE, g_bRunOnNT5))
  961. {
  962. SetDlgItemText(hwnd, IDC_FAVORITE_NAME, patf->pszFile);
  963. }
  964. else
  965. {
  966. TCHAR szUrlTemp[MAX_URL_STRING];
  967. IEGetDisplayName(patf->pidlFavorite, szUrlTemp, SHGDN_FORPARSING);
  968. SetDlgItemText(hwnd, IDC_FAVORITE_NAME, szUrlTemp);
  969. }
  970. EnableOKButtonFromID(hwnd, IDC_FAVORITE_NAME);
  971. // hide the (empty) SHBrowseForFolder prompt control
  972. ShowWindow(GetDlgItem (hwnd, IDD_BROWSETITLE), SW_HIDE);
  973. // Fill out the structure and set it as a property so that our subclass
  974. // proc can get to this data.
  975. pbffFavSubStruct->lpfnOldWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)BFFFavSubclass);
  976. pbffFavSubStruct->hwndNew = GetDlgItem(hwnd, IDC_FAVORITE_NEWFOLDER);
  977. pbffFavSubStruct->patf = patf;
  978. pbffFavSubStruct->hwndTV = GetDlgItem(hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER);
  979. pbffFavSubStruct->hwndSave = GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN);
  980. pbffFavSubStruct->hTemplateWnd = hDlgTemp; //save for explicit destruction later
  981. GetWindowRect(hwnd, &(pbffFavSubStruct->rcRestored));
  982. SetProp(hwnd, ADDTOFAVPROP, (HANDLE)pbffFavSubStruct);
  983. patf->pidlSelected = ILClone(patf->pidl);
  984. DWORD dwType, dwValue = 0, dwcData = sizeof(dwValue);
  985. TCHAR szBuffer[100];
  986. SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("AddToFavoritesExpanded"),
  987. &dwType, &dwValue, &dwcData, 0, NULL, sizeof(dwValue));
  988. if (dwValue == 0)
  989. {
  990. int lRet = MLLoadString(IDS_FAVS_ADVANCED_EXPAND, szBuffer, ARRAYSIZE(szBuffer));
  991. ASSERT(lRet);
  992. // Disable the tree view and new button so that we can't tab to them.
  993. EnableWindow(GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), FALSE);
  994. EnableWindow(GetDlgItem (hwnd, IDC_FAVORITE_NEWFOLDER), FALSE);
  995. // hide the bottom part of the dialog
  996. int cx, cy;
  997. RECT rc;
  998. GetWindowRect (GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), &rc);
  999. cy = rc.top;
  1000. GetWindowRect (hwnd, &rc);
  1001. cx = rc.right - rc.left;
  1002. cy = cy /*top of ctrl*/ - rc.top; /*top of window*/
  1003. SetWindowPos (hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
  1004. }
  1005. else
  1006. {
  1007. //don't show New Folder button for channels in the channels folder,
  1008. // see code for case IDC_FAVORITE_NEWFOLDER for why
  1009. if (patf->subsType == SUBSTYPE_CHANNEL)
  1010. {
  1011. LPITEMIDLIST pidlFavs = NULL;
  1012. TCHAR tzFavsPath[MAX_PATH];
  1013. if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_FAVORITES, &pidlFavs))
  1014. && SUCCEEDED(SHGetNameAndFlags(pidlFavs, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, tzFavsPath, SIZECHARS(tzFavsPath), NULL))
  1015. && 0 == StrCmpNI(tzFavsPath, patf->pszInitDir, ARRAYSIZE(tzFavsPath)))
  1016. {
  1017. EnableWindow(pbffFavSubStruct->hwndNew, TRUE);
  1018. }
  1019. else
  1020. EnableWindow(pbffFavSubStruct->hwndNew, FALSE);
  1021. if(pidlFavs)
  1022. ILFree(pidlFavs);
  1023. }
  1024. else
  1025. EnableWindow(pbffFavSubStruct->hwndNew, TRUE);
  1026. int lRet = MLLoadString(IDS_FAVS_ADVANCED_COLLAPSE, szBuffer, ARRAYSIZE(szBuffer));
  1027. ASSERT(lRet);
  1028. }
  1029. SetWindowText(GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN), szBuffer);
  1030. }
  1031. else
  1032. {
  1033. EndDialog(hwnd, IDCANCEL);
  1034. }
  1035. break;
  1036. }
  1037. case BFFM_SELCHANGED:
  1038. {
  1039. //the first of these comes during BFFM_INITIALIZED, so ignore it
  1040. if (((ADDTOFAV *)lpData)->pidlSelected != NULL)
  1041. {
  1042. ILFree(((ADDTOFAV *)lpData)->pidlSelected);
  1043. ((ADDTOFAV *)lpData)->pidlSelected = ILClone((LPITEMIDLIST)lParam);
  1044. }
  1045. break;
  1046. }
  1047. }
  1048. return 0;
  1049. }
  1050. // This API is not exported. See below (DoAddToFavDlg) for the exported version
  1051. //
  1052. // hwnd parent window for the dialog.
  1053. // pszInitDir input: initial path
  1054. // output: fully qualified path and filename
  1055. // chInitDir Length of pszInitDir buffer
  1056. // pszFile initial (default) filename for shortcut
  1057. // cchFile Length of pszFile buffer
  1058. // pidlBrowse associated with pszInitDir
  1059. //
  1060. // Returns:
  1061. // TRUE if a directory and filename were selected by user, and no error
  1062. // occurs. In this case pszInitDir contains the new destination directory
  1063. // and filename, pszFile contains the new file name.
  1064. //
  1065. // FALSE if an error occurs or the user selects CANCEL.
  1066. STDAPI_(BOOL) DoAddToFavDlgEx(HWND hwnd,
  1067. TCHAR *pszInitDir, UINT cchInitDir,
  1068. TCHAR *pszFile, UINT cchFile,
  1069. LPITEMIDLIST pidlBrowse,
  1070. LPCITEMIDLIST pidlFavorite,
  1071. FAVDLGTYPE atfDlgType,
  1072. SUBSCRIPTIONINFO* pInfo)
  1073. {
  1074. ADDTOFAV atf = {pszInitDir, cchInitDir - 1, pszFile, cchFile - 1, pidlBrowse, NULL,
  1075. pidlFavorite, atfDlgType, {sizeof(SUBSCRIPTIONINFO), 0}, SUBSTYPE_URL };
  1076. TCHAR szTemp[1]; //NOTE: we're not using SHBrowseForFolder's prompt string (see below)
  1077. TCHAR szDisplayName[MAX_PATH];
  1078. BROWSEINFO bi = {
  1079. hwnd,
  1080. pidlBrowse,
  1081. szDisplayName,
  1082. szTemp,
  1083. BIF_RETURNONLYFSDIRS,
  1084. // (BFFCALLBACK)
  1085. BFFFavCallback,
  1086. (LPARAM)&atf,
  1087. 0
  1088. };
  1089. LPITEMIDLIST pidl;
  1090. if (pInfo)
  1091. atf.siSubsInProg = *pInfo;
  1092. switch (atfDlgType)
  1093. {
  1094. case ATF_CHANNEL_SOFTDIST:
  1095. atf.bIsSoftdist = TRUE;
  1096. // fall through
  1097. case ATF_CHANNEL:
  1098. atf.subsType = SUBSTYPE_CHANNEL;
  1099. break;
  1100. //default:
  1101. // set in initialize to SUBSTYPE_URL
  1102. }
  1103. //this string is now in the template dialog in the .rc
  1104. //REVIEW -- do we want to do it this way (we're hiding SHBrowse...'s control)? then the template dialog looks more like the finished product...
  1105. szTemp[0] = 0;
  1106. //init native font control, otherwise dialog may fail to initialize
  1107. {
  1108. INITCOMMONCONTROLSEX icc;
  1109. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  1110. icc.dwICC = ICC_NATIVEFNTCTL_CLASS;
  1111. InitCommonControlsEx(&icc);
  1112. }
  1113. pidl = SHBrowseForFolder(&bi);
  1114. if (pidl)
  1115. {
  1116. ILFree(pidl);
  1117. }
  1118. // If the user created a new subscription, start a download.
  1119. if (atf.bSubscribed && !atf.bStartSubscribed)
  1120. {
  1121. ISubscriptionMgr* pSubsMgr;
  1122. if (SUCCEEDED (CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  1123. IID_ISubscriptionMgr, (void**)&pSubsMgr)))
  1124. {
  1125. WCHAR wszURL[MAX_URL_STRING];
  1126. IEGetDisplayName(atf.pidlFavorite, wszURL, SHGDN_FORPARSING);
  1127. pSubsMgr->UpdateSubscription(wszURL);
  1128. pSubsMgr->Release();
  1129. }
  1130. }
  1131. return (pidl != NULL);
  1132. }
  1133. STDAPI_(BOOL) DoSafeAddToFavDlgEx(HWND hwnd,
  1134. TCHAR *pszInitDir, UINT cchInitDir,
  1135. TCHAR *pszFile, UINT cchFile,
  1136. LPITEMIDLIST pidlBrowse,
  1137. LPCITEMIDLIST pidlFavorite,
  1138. FAVDLGTYPE atfDlgType,
  1139. SUBSCRIPTIONINFO* pInfo)
  1140. {
  1141. BOOL fRet;
  1142. if (IEIsLinkSafe(hwnd, pidlFavorite, ILS_ADDTOFAV))
  1143. {
  1144. fRet = DoAddToFavDlgEx(hwnd, pszInitDir, cchInitDir, pszFile, cchFile,
  1145. pidlBrowse, pidlFavorite, atfDlgType, pInfo);
  1146. }
  1147. else
  1148. {
  1149. fRet = FALSE;
  1150. }
  1151. return fRet;
  1152. }
  1153. // This API is exported so that it may be called by explorer and mshtml (and MSNVIEWR.EXE)
  1154. // in addition to being called internally by shdocvw.
  1155. // THEREFORE YOU MUST NOT CHANGE THE SIGNATURE OF THIS API
  1156. //
  1157. STDAPI_(BOOL) DoAddToFavDlg(HWND hwnd,
  1158. CHAR *pszInitDir, UINT cchInitDir,
  1159. CHAR *pszFile, UINT cchFile,
  1160. LPITEMIDLIST pidlBrowse)
  1161. {
  1162. BOOL fRet;
  1163. WCHAR szInitDir[MAX_PATH];
  1164. WCHAR szFile[MAX_PATH];
  1165. SHAnsiToUnicode(pszInitDir, szInitDir, ARRAYSIZE(szInitDir));
  1166. SHAnsiToUnicode(pszFile, szFile, ARRAYSIZE(szFile));
  1167. fRet = DoSafeAddToFavDlgEx(hwnd, szInitDir, ARRAYSIZE(szInitDir), szFile, ARRAYSIZE(szFile), pidlBrowse, NULL, ATF_FAVORITE, NULL);
  1168. SHUnicodeToAnsi(szInitDir, pszInitDir, cchInitDir);
  1169. SHUnicodeToAnsi(szFile, pszFile, cchFile);
  1170. return fRet;
  1171. }
  1172. STDAPI_(BOOL) DoAddToFavDlgW(HWND hwnd,
  1173. WCHAR *pszInitDir, UINT cchInitDir,
  1174. WCHAR *pszFile, UINT cchFile,
  1175. LPITEMIDLIST pidlBrowse)
  1176. {
  1177. return DoSafeAddToFavDlgEx(hwnd, pszInitDir, cchInitDir, pszFile, cchFile, pidlBrowse, NULL, ATF_FAVORITE, NULL);
  1178. }
  1179. STDAPI AddToFavoritesEx(HWND hwnd, LPCITEMIDLIST pidlCur, LPCTSTR pszTitle, DWORD dwFlags,
  1180. SUBSCRIPTIONINFO *pInfo, IOleCommandTarget *pCommandTarget, IHTMLDocument2 *pDoc);
  1181. STDAPI AddToChannelsEx (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, LPCWSTR pwszURL,
  1182. DWORD dwFlags, SUBSCRIPTIONINFO* pInfo);
  1183. STDAPI SubscribeFromFavorites (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, DWORD dwFlags,
  1184. SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo);
  1185. // This API is exported privately, and is called by ISubscriptionMgr::CreateSubscription.
  1186. // shuioc uses it too.
  1187. STDAPI SHAddSubscribeFavoriteEx (
  1188. HWND hwnd,
  1189. LPCWSTR pwszURL,
  1190. LPCWSTR pwszName,
  1191. DWORD dwFlags,
  1192. SUBSCRIPTIONTYPE subsType,
  1193. SUBSCRIPTIONINFO* pInfo,
  1194. IOleCommandTarget *pcmdt,
  1195. IHTMLDocument2 *pDoc)
  1196. {
  1197. TCHAR szName[MAX_PATH];
  1198. LPITEMIDLIST pidl = NULL;
  1199. HRESULT hr;
  1200. if (pwszURL==NULL || pwszName == NULL)
  1201. return E_INVALIDARG;
  1202. //
  1203. // Need to put pwszName into a buffer because it comes in const
  1204. // but gets modified in SubscribeFromFavorites.
  1205. //
  1206. StrCpyN(szName, pwszName, ARRAYSIZE(szName));
  1207. hr = IECreateFromPath(pwszURL, &pidl);
  1208. if (SUCCEEDED(hr))
  1209. {
  1210. ASSERT (pidl);
  1211. if (dwFlags & CREATESUBS_FROMFAVORITES)
  1212. {
  1213. if (subsType != SUBSTYPE_URL && subsType != SUBSTYPE_CHANNEL)
  1214. {
  1215. ASSERT(0);
  1216. hr = E_INVALIDARG;
  1217. }
  1218. else
  1219. {
  1220. hr = SubscribeFromFavorites (hwnd, pidl, szName, dwFlags, subsType, pInfo);
  1221. }
  1222. }
  1223. else
  1224. {
  1225. if (subsType == SUBSTYPE_URL)
  1226. {
  1227. hr = AddToFavoritesEx (hwnd, pidl, szName, dwFlags, pInfo, pcmdt, pDoc);
  1228. }
  1229. else if (subsType == SUBSTYPE_CHANNEL && !SHIsRestricted2W(hwnd, REST_NoChannelUI, NULL, 0))
  1230. {
  1231. hr = AddToChannelsEx (hwnd, pidl, szName, pwszURL, dwFlags, pInfo);
  1232. }
  1233. else
  1234. {
  1235. ASSERT (0);
  1236. hr = E_INVALIDARG;
  1237. }
  1238. }
  1239. ILFree(pidl);
  1240. }
  1241. return hr;
  1242. }
  1243. STDAPI SHAddSubscribeFavorite (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszName, DWORD dwFlags,
  1244. SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO* pInfo)
  1245. {
  1246. return SHAddSubscribeFavoriteEx ( hwnd, pwszURL, pwszName, dwFlags,
  1247. subsType, pInfo, NULL, NULL);
  1248. }
  1249. // this API is also exported via the .def
  1250. // Use for backward compatibility only -- note that it is only for URL's (not channels)
  1251. // and doesn't know how to subscribe.
  1252. STDAPI AddUrlToFavorites(HWND hwnd, LPWSTR pszUrlW, LPWSTR pszTitleW, BOOL fDisplayUI)
  1253. {
  1254. return SHAddSubscribeFavorite (hwnd, pszUrlW, pszTitleW,
  1255. fDisplayUI ? CREATESUBS_NOUI : 0, SUBSTYPE_URL, NULL);
  1256. }
  1257. // this API is in the .h and is used elsewhere in shdocvw, but is not exported
  1258. // Backward compatibility only -- only for URL's (not channels) and can subscribe, but can't
  1259. // pass in subscriptioninfo starter.
  1260. STDAPI AddToFavorites(
  1261. HWND hwnd,
  1262. LPCITEMIDLIST pidlCur,
  1263. LPCTSTR pszTitle,
  1264. BOOL fDisplayUI,
  1265. IOleCommandTarget *pCommandTarget,
  1266. IHTMLDocument2 *pDoc)
  1267. {
  1268. return AddToFavoritesEx (hwnd, pidlCur, pszTitle,
  1269. fDisplayUI ? 0 : CREATESUBS_NOUI, NULL, pCommandTarget, pDoc);
  1270. }
  1271. //helper function to create one column in a ListView control, add one item to that column,
  1272. //size the column to the width of the control, and color the control like a static...
  1273. //basically, like SetWindowText for a ListView. Because we use a lot of ListViews to display
  1274. //urls that would otherwise be truncated... the ListView gives us automatic ellipsis and ToolTip.
  1275. void SetListViewToString (HWND hLV, LPCTSTR pszString)
  1276. {
  1277. ASSERT(hLV);
  1278. LV_COLUMN lvc = {0};
  1279. RECT lvRect;
  1280. GetClientRect (hLV, &lvRect);
  1281. lvc.mask = LVCF_WIDTH;
  1282. lvc.cx = lvRect.right - lvRect.left;
  1283. if (-1 == ListView_InsertColumn(hLV, 0, &lvc)) {
  1284. ASSERT(0);
  1285. }
  1286. SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_INFOTIP, LVS_EX_INFOTIP);
  1287. LV_ITEM lvi = {0};
  1288. lvi.iSubItem = 0;
  1289. lvi.pszText = (LPTSTR)pszString;
  1290. lvi.mask = LVIF_TEXT;
  1291. ListView_InsertItem(hLV, &lvi);
  1292. ListView_EnsureVisible(hLV, 0, TRUE);
  1293. ListView_SetBkColor(hLV, GetSysColor(COLOR_BTNFACE));
  1294. ListView_SetTextBkColor(hLV, GetSysColor(COLOR_BTNFACE));
  1295. }
  1296. INT_PTR CALLBACK SubscribeFavoriteDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1297. {
  1298. ADDTOFAV * patf = (ADDTOFAV*)GetProp(hDlg, ADDTOFAVPROP);
  1299. switch (uMsg)
  1300. {
  1301. case WM_INITDIALOG:
  1302. {
  1303. TCHAR szURL[MAX_URL_STRING];
  1304. patf = (ADDTOFAV*)lParam;
  1305. SetProp(hDlg, ADDTOFAVPROP, (HANDLE)patf);
  1306. //set up name and url displays
  1307. SetDlgItemText (hDlg, IDC_CHANNEL_NAME, patf->pszFile);
  1308. //url is in patf->pidlFavorite
  1309. IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING);
  1310. SetListViewToString (GetDlgItem (hDlg, IDC_CHANNEL_URL), szURL);
  1311. //now the tricky part... this is for modifying the subscription associated with
  1312. //an existing ChannelBar shortcut. We need to find out if they are subscribed --
  1313. //if so, load the existing subscription into memory so it can be modified in the
  1314. //wizard. If not, leave the information that was passed up because it's got the
  1315. //schedule extracted from the CDF. In either case, check the radio button that
  1316. //corresponds to their current subscription level.
  1317. ISubscriptionMgr* pSubsMgr;
  1318. BOOL bSubs = FALSE;
  1319. HRESULT hr = JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  1320. IID_ISubscriptionMgr, (void**)&pSubsMgr,
  1321. hDlg, FIEF_FLAG_FORCE_JITUI | FIEF_FLAG_PEEK);
  1322. if (SUCCEEDED(hr))
  1323. {
  1324. pSubsMgr->IsSubscribed(szURL, &bSubs);
  1325. patf->bStartSubscribed = bSubs;
  1326. pSubsMgr->Release();
  1327. }
  1328. else if ((E_ACCESSDENIED == hr) || !IsBrowserFrameOptionsPidlSet(patf->pidlFavorite, BFO_USE_IE_OFFLINE_SUPPORT))
  1329. {
  1330. EnableWindow(GetDlgItem(hDlg, IDC_MAKE_OFFLINE), FALSE);
  1331. }
  1332. if (!bSubs && patf->bIsSoftdist)
  1333. {
  1334. bSubs = TRUE;
  1335. }
  1336. CheckDlgButton(hDlg, IDC_MAKE_OFFLINE, bSubs ? 1 : 0);
  1337. EnableWindow(GetDlgItem (hDlg, IDC_SUBSCRIBE_CUSTOMIZE), bSubs);
  1338. }
  1339. break;
  1340. case WM_DESTROY:
  1341. RemoveProp (hDlg, ADDTOFAVPROP);
  1342. break;
  1343. case WM_HELP:
  1344. SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  1345. HELP_WM_HELP, (DWORD_PTR)(LPTSTR) (patf->iDlgType == ATF_FAVORITE
  1346. ? aAddToFavHelpIDs : aAddToChanHelpIDs));
  1347. return TRUE;
  1348. break;
  1349. case WM_CONTEXTMENU:
  1350. SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
  1351. (DWORD_PTR)(LPVOID) (patf->iDlgType == ATF_FAVORITE
  1352. ? aAddToFavHelpIDs : aAddToChanHelpIDs));
  1353. return TRUE;
  1354. break;
  1355. case WM_COMMAND:
  1356. ASSERT (patf);
  1357. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1358. {
  1359. case IDCANCEL:
  1360. EndDialog(hDlg, IDCANCEL);
  1361. break;
  1362. case IDOK:
  1363. // first, make sure they're not trying to subscribe to an authenticated
  1364. // channel without entering a password.
  1365. if (SubscriptionFailsChannelAuthentication (hDlg, &patf->siSubsInProg))
  1366. return FALSE;
  1367. //find out whether they WERE subscribed, so if they click OK and they
  1368. //were already subscribed, we delete that subscription -- and either leave it
  1369. //deleted if "No subs" was the choice, or create the new one.
  1370. ISubscriptionMgr* pSubsMgr;
  1371. if (SUCCEEDED (JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  1372. IID_ISubscriptionMgr, (void**)&pSubsMgr,
  1373. hDlg, FIEF_FLAG_FORCE_JITUI)))
  1374. {
  1375. //url is in patf->pidlFavorite
  1376. TCHAR szURL[MAX_URL_STRING];
  1377. IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING);
  1378. BOOL bAlreadySubs;
  1379. if (SUCCEEDED (pSubsMgr->IsSubscribed (szURL, &bAlreadySubs)) && bAlreadySubs)
  1380. {
  1381. pSubsMgr->DeleteSubscription(szURL, NULL);
  1382. }
  1383. pSubsMgr->Release();
  1384. }
  1385. if (IsDlgButtonChecked (hDlg, IDC_MAKE_OFFLINE))
  1386. {
  1387. //they want to subscribe! save subscription we already have in memory
  1388. patf->bSubscribed = StartSiteSubscription (hDlg, patf, TRUE);
  1389. }
  1390. EndDialog(hDlg, IDOK);
  1391. break;
  1392. // common code with ATF dialog
  1393. case IDC_SUBSCRIBE_CUSTOMIZE:
  1394. //need to create -- but not store -- subscription
  1395. //need to (temporarily) trash patf->pidlFavorite so that we can go through the
  1396. //wizard without colliding with an existing subscription. When we actually create
  1397. //the subscription, we'll use the real name.
  1398. LPCITEMIDLIST pidlSave = patf->pidlFavorite;
  1399. TCHAR szUrlTemp[MAX_URL_STRING+1];
  1400. IEGetDisplayName(patf->pidlFavorite, szUrlTemp, SHGDN_FORPARSING);
  1401. StrCat (szUrlTemp, TEXT(".")); //just put something nearly invisible on the end
  1402. if (SUCCEEDED (IECreateFromPath(szUrlTemp, (LPITEMIDLIST*)&patf->pidlFavorite)))
  1403. {
  1404. if (StartSiteSubscription (hDlg, patf, FALSE))
  1405. SendMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE);
  1406. ILFree ((LPITEMIDLIST)patf->pidlFavorite);
  1407. }
  1408. patf->pidlFavorite = pidlSave;
  1409. break;
  1410. }
  1411. break;
  1412. }
  1413. return FALSE;
  1414. }
  1415. static const int CREATESUBS_ACTIVATE = 0x8000; //hidden flag meaning channel is already on system
  1416. STDAPI SubscribeFromFavorites (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, DWORD dwFlags,
  1417. SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo)
  1418. {
  1419. //used to subscribe to a channel that's already in the Favorites
  1420. //or a URL that's already a Favorite
  1421. //flags are same as ISubscriptionMgr::CreateSubscription
  1422. //display our part of the fav's dialog -- no need to go through SHBrowseForFolder
  1423. //or any of that, just our radio buttons in a fixed-size dialog with our own DlgProc
  1424. INT_PTR iDlgResult;
  1425. HRESULT hr = S_OK;
  1426. ADDTOFAV atf = {0};
  1427. atf.pszFile = pszName;
  1428. atf.siSubsInProg.cbSize = sizeof(SUBSCRIPTIONINFO);
  1429. if (pInfo && pInfo->cbSize == sizeof(SUBSCRIPTIONINFO))
  1430. atf.siSubsInProg = *pInfo;
  1431. atf.subsType = subsType;
  1432. //figure out what dialog to use
  1433. atf.iDlgType = (subsType == SUBSTYPE_URL ? ATF_FAVORITE :
  1434. (dwFlags & CREATESUBS_ACTIVATE ? ATF_CHANNEL_MODIFY : ATF_CHANNEL));
  1435. // Do we potentially need ANOTHER dialog type for softdist channels?
  1436. if (dwFlags & CREATESUBS_SOFTWAREUPDATE)
  1437. {
  1438. atf.bIsSoftdist = TRUE;
  1439. }
  1440. atf.pidlFavorite = pidlUrl;
  1441. #ifdef OLD_FAVORITES
  1442. int iTemplate;
  1443. switch (atf.iDlgType)
  1444. {
  1445. case ATF_CHANNEL_SOFTDIST: // Inappropriate, but it doesn't currently get used
  1446. case ATF_CHANNEL:
  1447. iTemplate = IDD_SUBSCRIBE_FAV_CHANNEL;
  1448. break;
  1449. case ATF_CHANNEL_MODIFY:
  1450. iTemplate = IDD_ACTIVATE_PLATINUM_CHANNEL;
  1451. break;
  1452. case ATF_FAVORITE:
  1453. iTemplate = IDD_SUBSCRIBE_FAVORITE;
  1454. break;
  1455. }
  1456. iDlgResult = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(iTemplate), hwnd,
  1457. SubscribeFavoriteDlgProc, (LPARAM)&atf);
  1458. #endif
  1459. iDlgResult = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_ADDTOFAVORITES_TEMPLATE), hwnd,
  1460. SubscribeFavoriteDlgProc, (LPARAM)&atf);
  1461. switch (iDlgResult)
  1462. {
  1463. case -1:
  1464. hr = E_FAIL;
  1465. break;
  1466. case IDCANCEL:
  1467. hr = S_FALSE;
  1468. break;
  1469. default:
  1470. if (pInfo && (pInfo->cbSize == sizeof(SUBSCRIPTIONINFO))
  1471. && (dwFlags & CREATESUBS_NOSAVE))
  1472. *pInfo = atf.siSubsInProg;
  1473. hr = S_OK;
  1474. break;
  1475. }
  1476. return hr;
  1477. }
  1478. STDAPI AddToChannelsEx (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, LPCWSTR pwszURL,
  1479. DWORD dwFlags, SUBSCRIPTIONINFO* pInfo)
  1480. {
  1481. HRESULT hr = S_OK;
  1482. IChannelMgrPriv* pIChannelMgrPriv;
  1483. hr = JITCoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
  1484. IID_IChannelMgrPriv, (void**)&pIChannelMgrPriv,
  1485. hwnd, FIEF_FLAG_FORCE_JITUI);
  1486. if (SUCCEEDED(hr))
  1487. {
  1488. if (S_OK == pIChannelMgrPriv->IsChannelInstalled (pwszURL))
  1489. {
  1490. hr = SubscribeFromFavorites (hwnd, pidlUrl, pszName, dwFlags | CREATESUBS_ACTIVATE,
  1491. SUBSTYPE_CHANNEL, pInfo);
  1492. }
  1493. else
  1494. {
  1495. LPITEMIDLIST pidlChannelFolder;
  1496. TCHAR szPath[MAX_PATH];
  1497. TCHAR szCFPath[MAX_PATH];
  1498. ASSERT(pIChannelMgrPriv);
  1499. IChannelMgrPriv::CHANNELFOLDERLOCATION cflLocation =
  1500. ((dwFlags & CREATESUBS_SOFTWAREUPDATE) ?
  1501. IChannelMgrPriv::CF_SOFTWAREUPDATE :
  1502. IChannelMgrPriv::CF_CHANNEL);
  1503. hr = pIChannelMgrPriv->GetChannelFolder(&pidlChannelFolder, cflLocation);
  1504. if (SUCCEEDED (hr))
  1505. {
  1506. //
  1507. // Change IChannelMgrPriv to unicode! This has to get fixed to
  1508. // support a unicode "Channels" name. (edwardp)
  1509. //
  1510. CHAR szBuff[MAX_PATH];
  1511. hr = pIChannelMgrPriv->GetChannelFolderPath (szBuff, ARRAYSIZE(szBuff), cflLocation);
  1512. if (SUCCEEDED(hr))
  1513. SHAnsiToUnicode(szBuff, szCFPath, ARRAYSIZE(szCFPath));
  1514. if (SUCCEEDED (hr))
  1515. {
  1516. TCHAR szDspName[MAX_URL_STRING];
  1517. DWORD cchDspName = ARRAYSIZE(szDspName);
  1518. StrCpyN(szPath, szCFPath, ARRAYSIZE(szPath));
  1519. // When we create a short cut for the URL, we have to make sure it's readable for
  1520. // the end user. PrepareURLForDisplay() will unescape the string if it's escaped.
  1521. if (!UrlIs(pszName, URLIS_URL) ||
  1522. !PrepareURLForDisplay(pszName, szDspName, &cchDspName))
  1523. {
  1524. // Unescaping wasn't wanted or didn't work.
  1525. StrCpyN(szDspName, pszName, ARRAYSIZE(szDspName));
  1526. }
  1527. PathCleanupSpec(szPath, szDspName);
  1528. FAVDLGTYPE iDlgType = (dwFlags & CREATESUBS_SOFTWAREUPDATE ? ATF_CHANNEL_SOFTDIST : ATF_CHANNEL);
  1529. if ((dwFlags & CREATESUBS_NOUI) ||
  1530. DoSafeAddToFavDlgEx(hwnd, szPath, ARRAYSIZE(szPath),
  1531. szDspName, ARRAYSIZE(szDspName), pidlChannelFolder,
  1532. pidlUrl, iDlgType, pInfo))
  1533. {
  1534. //we create the channelbar entry here, instead of cdfview, because here
  1535. //we know where in the channels folder the user wants it to go.
  1536. IChannelMgr* pChannelMgr = NULL;
  1537. hr = pIChannelMgrPriv->QueryInterface (IID_IChannelMgr, (void**)&pChannelMgr);
  1538. if (SUCCEEDED (hr))
  1539. {
  1540. //prepare strings
  1541. PathRemoveExtension(szPath);
  1542. //strip off absolute part of folder path, and convert to Unicode
  1543. int cchCommon = PathCommonPrefix (szPath, szCFPath, NULL);
  1544. //pack in the info we have
  1545. CHANNELSHORTCUTINFO csiChannel = {0};
  1546. csiChannel.cbSize = sizeof(csiChannel);
  1547. csiChannel.pszTitle = szPath + cchCommon;
  1548. csiChannel.pszURL = (LPWSTR)pwszURL;
  1549. csiChannel.bIsSoftware = (dwFlags & CREATESUBS_SOFTWAREUPDATE) ? TRUE : FALSE;
  1550. //and tell the channel mgr to add the channel
  1551. hr = pChannelMgr->AddChannelShortcut (&csiChannel);
  1552. pChannelMgr->Release();
  1553. }
  1554. }
  1555. else
  1556. {
  1557. hr = S_FALSE; //no failure, but no add
  1558. }
  1559. }
  1560. ILFree (pidlChannelFolder);
  1561. }
  1562. }
  1563. pIChannelMgrPriv->Release();
  1564. }
  1565. return hr;
  1566. }
  1567. STDAPI AddToFavoritesEx(
  1568. HWND hwnd,
  1569. LPCITEMIDLIST pidlCur,
  1570. LPCTSTR pszTitle,
  1571. DWORD dwFlags,
  1572. SUBSCRIPTIONINFO *pInfo,
  1573. IOleCommandTarget *pCommandTarget,
  1574. IHTMLDocument2 *pDoc)
  1575. {
  1576. HRESULT hres = S_FALSE;
  1577. HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1578. if (pidlCur)
  1579. {
  1580. TCHAR szName[MAX_URL_STRING];
  1581. TCHAR szPath[MAX_PATH];
  1582. if (pszTitle)
  1583. {
  1584. StrCpyN(szName, pszTitle, ARRAYSIZE(szName));
  1585. }
  1586. else
  1587. {
  1588. szName[0] = 0;
  1589. IEGetNameAndFlags(pidlCur, SHGDN_INFOLDER | SHGDN_NORMAL, szName, SIZECHARS(szName), NULL);
  1590. }
  1591. LPITEMIDLIST pidlFavorites;
  1592. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE) &&
  1593. (pidlFavorites = SHCloneSpecialIDList(NULL, CSIDL_FAVORITES, TRUE)))
  1594. {
  1595. TCHAR szDspName[MAX_PATH];
  1596. DWORD cchDspName = ARRAYSIZE(szDspName);
  1597. // When we create a short cut for the URL, we have to make sure it's readable for
  1598. // the end user. PrepareURLForDisplay() will unescape the string if it's escaped.
  1599. if (!UrlIs(szName, URLIS_URL) ||
  1600. !PrepareURLForDisplay(szName, szDspName, &cchDspName))
  1601. {
  1602. // Unescaping wasn't wanted or didn't work.
  1603. StrCpyN(szDspName, szName, ARRAYSIZE(szDspName));
  1604. }
  1605. PathCleanupSpec(szPath, szDspName);
  1606. // if left with spaces only, use the filename friendly version of the url instead.
  1607. StrTrim(szDspName, L" ");
  1608. if (szDspName[0] == 0)
  1609. {
  1610. if (SUCCEEDED(IEGetNameAndFlags(pidlCur, SHGDN_FORPARSING, szDspName, ARRAYSIZE(szDspName), NULL)))
  1611. PathCleanupSpec(szPath, szDspName);
  1612. }
  1613. BOOL fDisplayUI = (dwFlags & CREATESUBS_NOUI) ? FALSE : TRUE;
  1614. if (!fDisplayUI ||
  1615. DoSafeAddToFavDlgEx(hwnd, szPath, ARRAYSIZE(szPath),
  1616. szDspName, ARRAYSIZE(szDspName), pidlFavorites,
  1617. pidlCur, ATF_FAVORITE, NULL))
  1618. {
  1619. if (fDisplayUI)
  1620. PathRemoveFileSpec(szPath);
  1621. ISHCUT_PARAMS ShCutParams = {0};
  1622. PathRemoveExtension(szDspName);
  1623. ShCutParams.pidlTarget = pidlCur;
  1624. ShCutParams.pszTitle = PathFindFileName(szDspName);
  1625. ShCutParams.pszDir = szPath;
  1626. ShCutParams.pszOut = NULL;
  1627. ShCutParams.bUpdateProperties = FALSE;
  1628. ShCutParams.bUniqueName = FALSE;
  1629. ShCutParams.bUpdateIcon = TRUE;
  1630. ShCutParams.pCommand = pCommandTarget;
  1631. ShCutParams.pDoc = pDoc;
  1632. hres = CreateShortcutInDirEx(&ShCutParams);
  1633. if (fDisplayUI && FAILED(hres))
  1634. {
  1635. IE_ErrorMsgBox(NULL, hwnd, GetLastError(), NULL, szDspName, IDS_FAV_UNABLETOCREATE, MB_OK| MB_ICONSTOP);
  1636. }
  1637. }
  1638. else
  1639. {
  1640. hres = S_FALSE;
  1641. }
  1642. ILFree(pidlFavorites);
  1643. }
  1644. }
  1645. SetCursor(hCursorOld);
  1646. return hres;
  1647. }
  1648. BOOL IsSubscribed(ADDTOFAV *patf)
  1649. {
  1650. BOOL bSubscribed = FALSE;
  1651. TCHAR szURL[MAX_URL_STRING];
  1652. if (SUCCEEDED(IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING)))
  1653. {
  1654. ISubscriptionMgr *pSubscriptionMgr;
  1655. if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr,
  1656. NULL, CLSCTX_INPROC_SERVER,
  1657. IID_ISubscriptionMgr,
  1658. (void**)&pSubscriptionMgr)))
  1659. {
  1660. BSTR bstrURL = SysAllocStringT(szURL);
  1661. if (bstrURL)
  1662. {
  1663. if (SUCCEEDED(pSubscriptionMgr->IsSubscribed(bstrURL, &bSubscribed)) &&
  1664. bSubscribed)
  1665. {
  1666. patf->siSubsInProg.fUpdateFlags = SUBSINFO_ALLFLAGS;
  1667. pSubscriptionMgr->GetSubscriptionInfo(bstrURL, &patf->siSubsInProg);
  1668. }
  1669. SysFreeString(bstrURL);
  1670. }
  1671. pSubscriptionMgr->Release();
  1672. }
  1673. }
  1674. return bSubscribed;
  1675. }
  1676. BOOL IsSubscribed(LPCITEMIDLIST pidl)
  1677. {
  1678. BOOL bSubscribed = FALSE;
  1679. TCHAR szURL[MAX_URL_STRING];
  1680. if (FAILED(IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szURL, SIZEOF(szURL), NULL)))
  1681. return FALSE;
  1682. bSubscribed = IsSubscribed(szURL);
  1683. return bSubscribed;
  1684. }
  1685. BOOL IsSubscribed(LPWSTR pwzUrl)
  1686. {
  1687. #ifndef DISABLE_SUBSCRIPTIONS
  1688. BOOL bSubscribed = FALSE;
  1689. ISubscriptionMgr * pSubscriptionMgr;
  1690. if (FAILED(CoCreateInstance(CLSID_SubscriptionMgr,
  1691. NULL,
  1692. CLSCTX_INPROC_SERVER,
  1693. IID_ISubscriptionMgr,
  1694. (void**)&pSubscriptionMgr)))
  1695. {
  1696. return FALSE;
  1697. }
  1698. pSubscriptionMgr->IsSubscribed(pwzUrl, &bSubscribed);
  1699. pSubscriptionMgr->Release();
  1700. return bSubscribed;
  1701. #else /* !DISABLE_SUBSCRIPTIONS */
  1702. return FALSE;
  1703. #endif /* !DISABLE_SUBSCRIPTIONS */
  1704. }