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.

2017 lines
76 KiB

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