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.

1142 lines
41 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997
  5. //
  6. // File: admin.cpp
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "private.h"
  18. #include "shguidp.h"
  19. #include "chanmgr.h"
  20. #include "chanmgrp.h"
  21. #include "winineti.h"
  22. #include <mluisupp.h>
  23. // Infodelivery Policies registry locations
  24. #define INFODELIVERY_POLICIES TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Infodelivery")
  25. // const TCHAR c_szRegKeyRestrictions[] = INFODELIVERY_POLICIES TEXT("\\Restrictions");
  26. const TCHAR c_szRegKeyModifications[] = INFODELIVERY_POLICIES TEXT("\\Modifications");
  27. const TCHAR c_szRegKeyCompletedMods[] = INFODELIVERY_POLICIES TEXT("\\CompletedModifications");
  28. const TCHAR c_szRegKeyIESetup[] = TEXT("Software\\Microsoft\\IE4\\Setup");
  29. // Wininet cache preload directory
  30. const TCHAR c_szRegKeyCachePreload[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Preload");
  31. // Registry key names of supported Modifications
  32. const TCHAR c_szAddChannels[] = TEXT("AddChannels");
  33. const TCHAR c_szRemoveChannels[] = TEXT("RemoveChannels");
  34. const TCHAR c_szRemoveAllChannels[] = TEXT("RemoveAllChannels");
  35. const TCHAR c_szAddSubscriptions[] = TEXT("AddSubscriptions");
  36. const TCHAR c_szRemoveSubscriptions[] = TEXT("RemoveSubscriptions");
  37. const TCHAR c_szAddScheduleGroups[] = TEXT("AddScheduleGroups");
  38. const TCHAR c_szRemoveScheduleGroups[] = TEXT("RemoveScheduleGroups");
  39. const TCHAR c_szAddDesktopComponents[] = TEXT("AddDesktopComponents");
  40. const TCHAR c_szRemoveDesktopComponents[] = TEXT("RemoveDesktopComponents");
  41. // Registry value names of supported Modifications
  42. const TCHAR c_szURL[] = TEXT("URL");
  43. const TCHAR c_szTitle[] = TEXT("Title");
  44. const TCHAR c_szLogo[] = TEXT("Logo");
  45. const TCHAR c_szWideLogo[] = TEXT("WideLogo");
  46. const TCHAR c_szIcon[] = TEXT("Icon");
  47. const TCHAR c_szCategory[] = TEXT("Category");
  48. const TCHAR c_szChannelGuide[] = TEXT("ChannelGuide"); // DO NOTE CHANGE THIS STRING WITHOUT UPDATING CDFVIEW!!!
  49. const TCHAR c_szPreloadURL[] = TEXT("PreloadURL");
  50. const TCHAR c_szLCID[] = TEXT("LangId"); // This must be an LCID despite its name
  51. const TCHAR c_szSoftware[] = TEXT("Software");
  52. const TCHAR c_szSubscriptionType[] = TEXT("SubscriptionType");
  53. const TCHAR c_szScheduleGroup[] = TEXT("ScheduleGroup");
  54. const TCHAR c_szEarliestTime[] = TEXT("EarliestTime");
  55. const TCHAR c_szIntervalTime[] = TEXT("IntervalTime");
  56. const TCHAR c_szLatestTime[] = TEXT("LatestTime");
  57. const TCHAR c_szComponentType[] = TEXT("DesktopComponentType");
  58. const TCHAR c_szUsername[] = TEXT("Username");
  59. const TCHAR c_szPassword[] = TEXT("Password");
  60. const TCHAR c_szOldIEVersion[] = TEXT("OldIEVersion");
  61. const TCHAR c_szNonActive[] = TEXT("NonActive");
  62. const TCHAR c_szOffline[] = TEXT("Offline");
  63. const TCHAR c_szSynchronize[] = TEXT("Synchronize");
  64. // Names of reserved schedule groups that we support even in localized version
  65. const WCHAR c_szScheduleAuto[] = L"Auto";
  66. const WCHAR c_szScheduleDaily[] = L"Daily";
  67. const WCHAR c_szScheduleWeekly[] = L"Weekly";
  68. const WCHAR c_szScheduleManual[] = L"Manual";
  69. // Function prototypes for Modification handlers
  70. HRESULT ProcessAddChannels(HKEY hkey);
  71. HRESULT ProcessRemoveChannels(HKEY hkey);
  72. HRESULT ProcessRemoveAllChannels(HKEY hkey);
  73. HRESULT ProcessAddSubscriptions(HKEY hkey);
  74. HRESULT ProcessRemoveSubscriptions(HKEY hkey);
  75. HRESULT ProcessRemoveDesktopComponents(HKEY hkey);
  76. HRESULT Channel_GetBasePath(LPTSTR pszPath, int cch);
  77. // Helper functions
  78. void ShowChannelDirectories(BOOL fShow);
  79. // Table of supported Actions and corresponding functions
  80. // NOTE: The table must be ordered appropriately (RemoveAll must come before Add)
  81. typedef HRESULT (*PFNACTION)(HKEY);
  82. typedef struct { LPCTSTR szAction; PFNACTION pfnAction; } ACTIONTABLE;
  83. ACTIONTABLE rgActionTable[] = {
  84. { c_szRemoveAllChannels, &ProcessRemoveAllChannels },
  85. { c_szRemoveSubscriptions, &ProcessRemoveSubscriptions },
  86. { c_szRemoveChannels, &ProcessRemoveChannels },
  87. { c_szRemoveDesktopComponents, &ProcessRemoveDesktopComponents },
  88. { c_szAddChannels, &ProcessAddChannels },
  89. { c_szAddSubscriptions, &ProcessAddSubscriptions }
  90. };
  91. #define ACTIONTABLECOUNT (sizeof(rgActionTable) / sizeof(ACTIONTABLE))
  92. #define ACTIONTABLE_ADDCHANNELS 5
  93. // Helper class to manipulate registry keys
  94. class CRegKey
  95. {
  96. HKEY m_hkey;
  97. DWORD dwIndex;
  98. public:
  99. CRegKey(void)
  100. {
  101. m_hkey = NULL;
  102. dwIndex = 0;
  103. }
  104. ~CRegKey(void)
  105. {
  106. if (m_hkey)
  107. {
  108. LONG lRet = RegCloseKey(m_hkey);
  109. ASSERT(ERROR_SUCCESS == lRet);
  110. m_hkey = NULL;
  111. }
  112. }
  113. void SetKey(HKEY hkey)
  114. {
  115. m_hkey = hkey;
  116. }
  117. HKEY GetKey(void)
  118. {
  119. return m_hkey;
  120. }
  121. HRESULT OpenForRead(HKEY hkey, LPCTSTR szSubKey)
  122. {
  123. ASSERT(NULL == m_hkey);
  124. LONG lRet = RegOpenKeyEx(hkey, szSubKey, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &m_hkey);
  125. ASSERT((ERROR_SUCCESS == lRet) || !m_hkey);
  126. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  127. }
  128. HRESULT CreateForWrite(HKEY hkey, LPCTSTR szSubKey)
  129. {
  130. ASSERT(NULL == m_hkey);
  131. DWORD dwDisp;
  132. LONG lRet = RegCreateKeyEx(hkey, szSubKey, 0, TEXT(""), 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &m_hkey, &dwDisp);
  133. ASSERT(ERROR_SUCCESS == lRet);
  134. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  135. }
  136. HRESULT GetSubKeyCount(PDWORD pdwKeys)
  137. {
  138. ASSERT(NULL != m_hkey);
  139. LONG lRet = RegQueryInfoKey(m_hkey, NULL, NULL, NULL, pdwKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  140. ASSERT(ERROR_SUCCESS == lRet);
  141. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  142. }
  143. HRESULT Next(LPTSTR szSubKey)
  144. {
  145. ASSERT(NULL != m_hkey);
  146. DWORD dwLen = MAX_PATH; // Assumes size of incoming buffer.
  147. LONG lRet = RegEnumKeyEx(m_hkey, dwIndex, szSubKey, &dwLen, NULL, NULL, NULL, NULL);
  148. dwIndex++;
  149. if (ERROR_SUCCESS == lRet)
  150. return S_OK;
  151. else if (ERROR_NO_MORE_ITEMS == lRet)
  152. return S_FALSE;
  153. else
  154. {
  155. ASSERT(FALSE);
  156. return E_FAIL;
  157. }
  158. }
  159. HRESULT Reset(void)
  160. {
  161. dwIndex = 0;
  162. return S_OK;
  163. }
  164. HRESULT SetValue(LPCTSTR szValueName, DWORD dwValue)
  165. {
  166. ASSERT(m_hkey);
  167. LONG lRet = RegSetValueEx(m_hkey, szValueName, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
  168. ASSERT(ERROR_SUCCESS == lRet);
  169. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  170. }
  171. HRESULT GetValue(LPCTSTR szValueName, DWORD *pdwValue)
  172. {
  173. ASSERT(m_hkey);
  174. DWORD dwType = REG_DWORD;
  175. DWORD dwLen = sizeof(DWORD);
  176. LONG lRet = RegQueryValueEx(m_hkey, szValueName, 0, &dwType, (LPBYTE)pdwValue, &dwLen);
  177. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  178. }
  179. HRESULT GetStringValue(LPCTSTR szValueName, LPTSTR szValue, DWORD cbValue)
  180. {
  181. ASSERT(m_hkey);
  182. return SHRegGetValue(m_hkey, NULL, szValueName, SRRF_RT_REG_SZ | SRRF_NOEXPAND, NULL, szValue, &cbValue) == ERROR_SUCCESS
  183. ? S_OK
  184. : E_FAIL;
  185. }
  186. HRESULT SetBSTRValue(LPCTSTR szValueName, BSTR bstr)
  187. {
  188. ASSERT(m_hkey);
  189. TCHAR szValue[INTERNET_MAX_URL_LENGTH];
  190. MyOleStrToStrN(szValue, ARRAYSIZE(szValue), bstr);
  191. LONG lRet = RegSetValueEx(m_hkey, szValueName, 0, REG_SZ, (LPBYTE)szValue, lstrlen(szValue) + 1);
  192. ASSERT(ERROR_SUCCESS == lRet);
  193. return (ERROR_SUCCESS == lRet)?(S_OK):(E_FAIL);
  194. }
  195. HRESULT GetBSTRValue(LPCTSTR szValueName, BSTR *pbstr)
  196. {
  197. ASSERT(m_hkey);
  198. TCHAR szValue[INTERNET_MAX_URL_LENGTH];
  199. DWORD cbValue = sizeof(szValue);
  200. HRESULT hr;
  201. *pbstr = NULL;
  202. LONG lRet = SHRegGetValue(m_hkey, NULL, szValueName, SRRF_RT_REG_SZ | SRRF_NOEXPAND, NULL, szValue, &cbValue);
  203. if (ERROR_SUCCESS == lRet)
  204. {
  205. DWORD cchValue = cbValue / sizeof(TCHAR);
  206. *pbstr = SysAllocStringLen(NULL, cchValue); // cchValue includes null terminator
  207. if (*pbstr)
  208. {
  209. MyStrToOleStrN(*pbstr, cchValue, szValue);
  210. hr = S_OK;
  211. }
  212. else
  213. {
  214. hr = E_OUTOFMEMORY;
  215. }
  216. }
  217. else
  218. {
  219. hr = HRESULT_FROM_WIN32(lRet);
  220. }
  221. return hr;
  222. }
  223. };
  224. // Helper class to manage Dynamic Pointer Arrays of HKEYs.
  225. class CRegKeyDPA
  226. {
  227. HDPA m_hdpa;
  228. int m_count;
  229. public:
  230. CRegKeyDPA(void)
  231. {
  232. m_hdpa = NULL;
  233. m_count = 0;
  234. }
  235. ~CRegKeyDPA(void)
  236. {
  237. if (m_hdpa)
  238. {
  239. ASSERT(m_count);
  240. int i;
  241. for (i = 0; i < m_count; i++)
  242. RegCloseKey(GetKey(i));
  243. DPA_Destroy(m_hdpa);
  244. }
  245. }
  246. int GetCount(void)
  247. {
  248. return m_count;
  249. }
  250. HKEY GetKey(int i)
  251. {
  252. ASSERT(i >= 0 && i < m_count);
  253. return (HKEY)DPA_GetPtr(m_hdpa, i);
  254. }
  255. HRESULT Add(HKEY hkey, LPCTSTR szSubKey)
  256. {
  257. if (!m_hdpa)
  258. {
  259. m_hdpa = DPA_CreateEx(5, NULL); // Choose arbitrary growth value
  260. if (!m_hdpa)
  261. return E_FAIL;
  262. }
  263. HKEY hkeyNew;
  264. LONG lRet = RegOpenKeyEx(hkey, szSubKey, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hkeyNew);
  265. if (ERROR_SUCCESS != lRet)
  266. return E_FAIL;
  267. if (-1 == DPA_InsertPtr(m_hdpa, DPA_APPEND, hkeyNew))
  268. {
  269. RegCloseKey(hkeyNew);
  270. return E_FAIL;
  271. }
  272. m_count++;
  273. return S_OK;
  274. }
  275. };
  276. //
  277. // 8/18/98 darrenmi
  278. // Copied (and butchered) from shdocvw\util.cpp so we don't have to load it at startup
  279. //
  280. DWORD WCRestricted2W(BROWSER_RESTRICTIONS rest, LPCWSTR pwzUrl, DWORD dwReserved)
  281. {
  282. DWORD dwType, dw = 0, dwSize = sizeof(DWORD);
  283. // we only handle NoChannelUI restriction
  284. if(rest != REST_NoChannelUI)
  285. {
  286. return 0;
  287. }
  288. // read registry setting
  289. SHGetValue(HKEY_CURRENT_USER,
  290. TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Infodelivery\\Restrictions"),
  291. TEXT("NoChannelUI"),
  292. &dwType, &dw, &dwSize);
  293. return dw;
  294. }
  295. // ProcessInfodeliveryPolicies
  296. //
  297. // This is the main Admin API for Infodelivery. It returns E_FAIL for errors,
  298. // S_FALSE for nothing to process, and S_OK for correctly processed items.
  299. //
  300. // Reg key organization [Modifications] - the key to process
  301. // [GUID1] - group of actions
  302. // [AddChannels] - sample action
  303. // [Channel1] - element of an action
  304. //
  305. HRESULT ProcessInfodeliveryPolicies(void)
  306. {
  307. HRESULT hr;
  308. CRegKey regModifications;
  309. TCHAR szGUID[MAX_PATH];
  310. // Check if channels should be hidden.
  311. if (WCRestricted2W(REST_NoChannelUI, NULL, 0))
  312. {
  313. ShowChannelDirectories(FALSE);
  314. }
  315. else
  316. {
  317. ShowChannelDirectories(TRUE);
  318. }
  319. // Bail out quickly if there are no Modifications to perform. (Return S_FALSE)
  320. hr = regModifications.OpenForRead(HKEY_CURRENT_USER, c_szRegKeyModifications);
  321. if (FAILED(hr))
  322. return S_FALSE;
  323. // Prepare to use the CompletedModifications key.
  324. CRegKey regCompletedMods;
  325. hr = regCompletedMods.CreateForWrite(HKEY_CURRENT_USER, c_szRegKeyCompletedMods);
  326. if (FAILED(hr))
  327. return hr;
  328. hr = CoInitialize(NULL);
  329. if (FAILED(hr))
  330. return hr;
  331. // Prepare queues of registry keys to actions
  332. CRegKeyDPA rgKeyQueue[ACTIONTABLECOUNT];
  333. // Enumerate the GUID keys, skipping the completed ones.
  334. // Enumerate the Actions beneath them and add them to queues.
  335. // ignoring errors here too.
  336. while (S_OK == regModifications.Next(szGUID))
  337. {
  338. DWORD dwValue;
  339. if (FAILED(regCompletedMods.GetValue(szGUID, &dwValue)))
  340. {
  341. CRegKey regGUID;
  342. TCHAR szAction[MAX_PATH];
  343. hr = regGUID.OpenForRead(regModifications.GetKey(), szGUID);
  344. while (S_OK == regGUID.Next(szAction))
  345. {
  346. // Search the table to see if it's a key we understand.
  347. // If so, add it to the queue.
  348. int i;
  349. for (i = 0; i < ACTIONTABLECOUNT; i++)
  350. {
  351. if (!StrCmpI(rgActionTable[i].szAction, szAction))
  352. {
  353. rgKeyQueue[i].Add(regGUID.GetKey(), szAction);
  354. break;
  355. }
  356. }
  357. }
  358. }
  359. }
  360. // Process all the keys we've accumulated. (Correct order is assumed.)
  361. int i;
  362. for (i = 0; i < ACTIONTABLECOUNT; i++)
  363. {
  364. if (rgKeyQueue[i].GetCount())
  365. {
  366. int iKey;
  367. for (iKey = 0; iKey < rgKeyQueue[i].GetCount(); iKey++)
  368. {
  369. (rgActionTable[i].pfnAction)(rgKeyQueue[i].GetKey(iKey));
  370. }
  371. }
  372. }
  373. // Walk the GUIDs we've processed and mark them completed with the time.
  374. // Updating ones we skipped as well will help with garbage collection.
  375. regModifications.Reset();
  376. while (S_OK == regModifications.Next(szGUID))
  377. {
  378. SYSTEMTIME st;
  379. FILETIME ft;
  380. GetSystemTime(&st);
  381. SystemTimeToFileTime(&st, &ft);
  382. regCompletedMods.SetValue(szGUID, ft.dwHighDateTime);
  383. }
  384. // Delete the Actions. NOTE: NT's RegDeleteKey() doesn't delete sub-keys.
  385. // This shlwapi API uses KEY_ALL_ACCESS.
  386. // We probably have to close all the keys here.
  387. SHDeleteKey(HKEY_CURRENT_USER, c_szRegKeyModifications);
  388. // If any channels were processed, tell the cache to reload.
  389. // We should only do this for default channels.
  390. if (rgKeyQueue[ACTIONTABLE_ADDCHANNELS].GetCount())
  391. {
  392. ASSERT(!StrCmpI(rgActionTable[ACTIONTABLE_ADDCHANNELS].szAction, c_szAddChannels));
  393. LoadUrlCacheContent();
  394. }
  395. CoUninitialize();
  396. return S_OK;
  397. }
  398. //
  399. // ProcessAddChannels_SortCallback - sort in reverse order
  400. //
  401. int ProcessAddChannels_SortCallback(PVOID p1, PVOID p2, LPARAM lparam)
  402. {
  403. return StrCmpI((LPTSTR)p2, (LPTSTR)p1);
  404. }
  405. //
  406. // ProcessAddChannels
  407. //
  408. HRESULT ProcessAddChannels(HKEY hkey)
  409. {
  410. // Enumerate the channels in the AddChannels key
  411. HRESULT hr;
  412. DWORD dwChannels;
  413. CRegKey regAdd;
  414. regAdd.SetKey(hkey);
  415. hr = regAdd.GetSubKeyCount(&dwChannels);
  416. if (SUCCEEDED(hr) && dwChannels)
  417. {
  418. // Check if the channels are the same code page as the system default.
  419. BOOL bCodePageMatch = TRUE;
  420. LCID lcidChannel = 0;
  421. if (SUCCEEDED(regAdd.GetValue(c_szLCID, &lcidChannel)))
  422. {
  423. TCHAR szCodePageSystem[8];
  424. TCHAR szCodePageChannel[8];
  425. szCodePageChannel[0] = 0; // Init in case there's no locale info
  426. GetLocaleInfo(lcidChannel, LOCALE_IDEFAULTANSICODEPAGE, szCodePageChannel, ARRAYSIZE(szCodePageChannel));
  427. int iRet = GetLocaleInfo(GetSystemDefaultLCID(), LOCALE_IDEFAULTANSICODEPAGE, szCodePageSystem, ARRAYSIZE(szCodePageSystem));
  428. ASSERT(iRet);
  429. if (StrCmpI(szCodePageSystem, szCodePageChannel))
  430. bCodePageMatch = FALSE;
  431. }
  432. hr = E_FAIL;
  433. TCHAR *pch = (TCHAR *)MemAlloc(LMEM_FIXED, dwChannels * MAX_PATH * sizeof(TCHAR));
  434. if (pch)
  435. {
  436. HDPA hdpa = DPA_Create(dwChannels);
  437. if (hdpa)
  438. {
  439. DWORD i;
  440. TCHAR *pchCur = pch;
  441. for (i = 0; i < dwChannels; i++)
  442. {
  443. if ((S_OK != regAdd.Next(pchCur)) || (-1 == DPA_InsertPtr(hdpa, DPA_APPEND, pchCur)))
  444. break;
  445. pchCur += MAX_PATH;
  446. }
  447. if (i >= dwChannels)
  448. {
  449. // Sort channels by registry key name,
  450. DPA_Sort(hdpa, ProcessAddChannels_SortCallback, 0);
  451. // Now create them.
  452. for (i = 0; i < dwChannels; i++)
  453. {
  454. BSTR bstrURL = NULL;
  455. BSTR bstrTitle = NULL;
  456. BSTR bstrLogo = NULL;
  457. BSTR bstrWideLogo = NULL;
  458. BSTR bstrIcon = NULL;
  459. BSTR bstrPreloadURL = NULL;
  460. DWORD dwCategory = 0; // default to channel
  461. DWORD dwChannelGuide = 0; // default to not a guide
  462. DWORD dwSoftware = 0; // default to non-software channel
  463. DWORD dwOffline = 0;
  464. DWORD dwSynchronize = 0;
  465. CRegKey regChannel;
  466. regChannel.OpenForRead(hkey, (LPCTSTR)DPA_GetPtr(hdpa, i));
  467. hr = regChannel.GetBSTRValue(c_szURL, &bstrURL);
  468. hr = regChannel.GetBSTRValue(c_szTitle, &bstrTitle);
  469. hr = regChannel.GetBSTRValue(c_szLogo, &bstrLogo);
  470. hr = regChannel.GetBSTRValue(c_szWideLogo, &bstrWideLogo);
  471. hr = regChannel.GetBSTRValue(c_szIcon, &bstrIcon);
  472. hr = regChannel.GetBSTRValue(c_szPreloadURL, &bstrPreloadURL);
  473. hr = regChannel.GetValue(c_szCategory, &dwCategory);
  474. hr = regChannel.GetValue(c_szChannelGuide, &dwChannelGuide);
  475. hr = regChannel.GetValue(c_szSoftware, &dwSoftware);
  476. hr = regChannel.GetValue(c_szOffline, &dwOffline);
  477. hr = regChannel.GetValue(c_szSynchronize, &dwSynchronize);
  478. if (bstrTitle)
  479. {
  480. IChannelMgr *pChannelMgr = NULL;
  481. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgr, (void**)&pChannelMgr);
  482. if (SUCCEEDED(hr))
  483. {
  484. // See if channel already exists - do nothing if it does (62976)
  485. IEnumChannels *pEnumChannels = NULL;
  486. if (SUCCEEDED(pChannelMgr->EnumChannels(CHANENUM_ALLFOLDERS, bstrURL, &pEnumChannels)))
  487. {
  488. CHANNELENUMINFO Bogus={0};
  489. ULONG cFetched=0;
  490. if ((S_OK == pEnumChannels->Next(1, &Bogus, &cFetched)) && cFetched)
  491. {
  492. // Oops. It exists. Skip all this goo.
  493. hr = E_FAIL;
  494. }
  495. }
  496. SAFERELEASE(pEnumChannels);
  497. }
  498. if (SUCCEEDED(hr))
  499. {
  500. if (dwCategory && bCodePageMatch)
  501. {
  502. // create a category (useless if code page doesn't match)
  503. CHANNELCATEGORYINFO csi = {0};
  504. csi.cbSize = sizeof(csi);
  505. csi.pszURL = bstrURL;
  506. csi.pszTitle = bstrTitle;
  507. csi.pszLogo = bstrLogo;
  508. csi.pszIcon = bstrIcon;
  509. csi.pszWideLogo = bstrWideLogo;
  510. hr = pChannelMgr->AddCategory(&csi);
  511. }
  512. else if (!dwCategory && bstrURL)
  513. {
  514. // update the registry if it's a channel guide
  515. if (dwChannelGuide)
  516. {
  517. CRegKey reg;
  518. hr = reg.CreateForWrite(HKEY_CURRENT_USER, c_szRegKey);
  519. if (SUCCEEDED(hr))
  520. reg.SetBSTRValue(c_szChannelGuide, bstrTitle);
  521. }
  522. // tell wininet if there's preload content
  523. if (bstrPreloadURL)
  524. {
  525. CRegKey reg;
  526. hr = reg.CreateForWrite(HKEY_CURRENT_USER, c_szRegKeyCachePreload);
  527. if (SUCCEEDED(hr))
  528. {
  529. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  530. MyOleStrToStrN(szURL, ARRAYSIZE(szURL), bstrURL);
  531. reg.SetBSTRValue(szURL, bstrPreloadURL);
  532. }
  533. }
  534. // create a channel (use URL instead of Title if code page doesn't match)
  535. CHANNELSHORTCUTINFO csi = {0};
  536. csi.cbSize = sizeof(csi);
  537. csi.pszURL = bstrURL;
  538. if (bCodePageMatch)
  539. csi.pszTitle = bstrTitle;
  540. else
  541. csi.pszTitle = bstrURL;
  542. csi.pszLogo = bstrLogo;
  543. csi.pszIcon = bstrIcon;
  544. csi.pszWideLogo = bstrWideLogo;
  545. if (dwSoftware)
  546. csi.bIsSoftware = TRUE;
  547. hr = pChannelMgr->AddChannelShortcut(&csi);
  548. }
  549. }
  550. SAFERELEASE(pChannelMgr);
  551. if (dwOffline)
  552. {
  553. ISubscriptionMgr2 *pSubMgr2 = NULL;
  554. hr = CoCreateInstance(CLSID_SubscriptionMgr,
  555. NULL,
  556. CLSCTX_INPROC_SERVER,
  557. IID_ISubscriptionMgr2,
  558. (void**)&pSubMgr2);
  559. if (SUCCEEDED(hr))
  560. {
  561. hr = pSubMgr2->CreateSubscription(NULL,
  562. bstrURL,
  563. bstrTitle,
  564. CREATESUBS_NOUI,
  565. SUBSTYPE_CHANNEL,
  566. NULL);
  567. if (dwSynchronize)
  568. {
  569. BOOL bIsSubscribed;
  570. SUBSCRIPTIONCOOKIE cookie;
  571. if (SUCCEEDED(pSubMgr2->IsSubscribed(bstrURL, &bIsSubscribed))
  572. && bIsSubscribed &&
  573. SUCCEEDED(ReadCookieFromInetDB(bstrURL, &cookie)))
  574. {
  575. pSubMgr2->UpdateItems(SUBSMGRUPDATE_MINIMIZE, 1, &cookie);
  576. }
  577. }
  578. pSubMgr2->Release();
  579. }
  580. }
  581. }
  582. SAFEFREEBSTR(bstrURL);
  583. SAFEFREEBSTR(bstrTitle);
  584. SAFEFREEBSTR(bstrLogo);
  585. SAFEFREEBSTR(bstrWideLogo);
  586. SAFEFREEBSTR(bstrIcon);
  587. SAFEFREEBSTR(bstrPreloadURL);
  588. }
  589. }
  590. DPA_Destroy(hdpa);
  591. }
  592. MemFree(pch);
  593. }
  594. }
  595. regAdd.SetKey(NULL);
  596. return S_OK;
  597. }
  598. //
  599. // ProcessRemoveChannels
  600. //
  601. HRESULT ProcessRemoveChannels(HKEY hkey)
  602. {
  603. // Enumerate the channel keys in the RemoveChannels key
  604. HRESULT hr;
  605. CRegKey reg;
  606. reg.SetKey(hkey);
  607. TCHAR szChannel[MAX_PATH];
  608. while (S_OK == reg.Next(szChannel))
  609. {
  610. CRegKey regChannel;
  611. DWORD dwNonActive = 0; // default to deleting Active & NonActive channels
  612. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  613. regChannel.OpenForRead(hkey, szChannel);
  614. regChannel.GetValue(c_szNonActive, &dwNonActive);
  615. if (SUCCEEDED(regChannel.GetStringValue(c_szURL, szURL, sizeof(szURL))))
  616. {
  617. // Check if the channel is Active to determine if we can delete it
  618. if (dwNonActive)
  619. {
  620. CRegKey regPreload;
  621. if (SUCCEEDED(regPreload.OpenForRead(HKEY_CURRENT_USER, c_szRegKeyCachePreload)))
  622. {
  623. if (SUCCEEDED(regPreload.GetStringValue(szURL, NULL, 0)))
  624. {
  625. dwNonActive = 0;
  626. }
  627. }
  628. }
  629. // Now delete the channel if appropriate
  630. if (!dwNonActive)
  631. {
  632. IChannelMgr *pChannelMgr = NULL;
  633. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgr, (void**)&pChannelMgr);
  634. if (SUCCEEDED(hr))
  635. {
  636. BSTR bstrURL;
  637. if (SUCCEEDED(regChannel.GetBSTRValue(c_szURL, &bstrURL)))
  638. {
  639. IEnumChannels *pEnum;
  640. hr = pChannelMgr->EnumChannels(CHANENUM_ALLFOLDERS | CHANENUM_PATH, bstrURL, &pEnum);
  641. if (SUCCEEDED(hr))
  642. {
  643. CHANNELENUMINFO info;
  644. while (S_OK == pEnum->Next(1, &info, NULL))
  645. {
  646. hr = pChannelMgr->DeleteChannelShortcut(info.pszPath);
  647. ASSERT(SUCCEEDED(hr));
  648. CoTaskMemFree(info.pszPath);
  649. }
  650. pEnum->Release();
  651. }
  652. SysFreeString(bstrURL);
  653. }
  654. pChannelMgr->Release();
  655. }
  656. }
  657. }
  658. }
  659. reg.SetKey(NULL);
  660. return S_OK;
  661. }
  662. //
  663. // ProcessAddSubscriptions
  664. //
  665. HRESULT ProcessAddSubscriptions(HKEY hkey)
  666. {
  667. // Enumerate the subscription keys in the AddSubscriptions key
  668. HRESULT hr;
  669. CRegKey reg;
  670. reg.SetKey(hkey);
  671. TCHAR szSubscription[MAX_PATH];
  672. while (S_OK == reg.Next(szSubscription))
  673. {
  674. // Create the subscription
  675. // What if there is one already?
  676. CRegKey regSubscription;
  677. regSubscription.OpenForRead(hkey, szSubscription);
  678. BSTR bstrURL, bstrTitle, bstrGroup, bstrUsername, bstrPassword;
  679. DWORD dwSubType;
  680. DWORD dwSynchronize = 0;
  681. hr = regSubscription.GetBSTRValue(c_szURL, &bstrURL);
  682. hr = regSubscription.GetBSTRValue(c_szTitle, &bstrTitle);
  683. hr = regSubscription.GetBSTRValue(c_szScheduleGroup, &bstrGroup);
  684. hr = regSubscription.GetBSTRValue(c_szUsername, &bstrUsername);
  685. hr = regSubscription.GetBSTRValue(c_szPassword, &bstrPassword);
  686. hr = regSubscription.GetValue(c_szSynchronize, &dwSynchronize);
  687. if (bstrURL && bstrTitle && bstrGroup && SUCCEEDED(regSubscription.GetValue(c_szSubscriptionType, &dwSubType)))
  688. {
  689. SUBSCRIPTIONINFO si = {0};
  690. si.cbSize = sizeof(SUBSCRIPTIONINFO);
  691. si.fUpdateFlags = SUBSINFO_SCHEDULE;
  692. if (bstrUsername && bstrPassword)
  693. {
  694. si.fUpdateFlags |= (SUBSINFO_USER | SUBSINFO_PASSWORD);
  695. si.bstrUserName = bstrUsername;
  696. si.bstrPassword = bstrPassword;
  697. }
  698. if (dwSubType == SUBSTYPE_CHANNEL || dwSubType == SUBSTYPE_DESKTOPCHANNEL)
  699. {
  700. si.fUpdateFlags |= SUBSINFO_CHANNELFLAGS;
  701. si.fChannelFlags = 0; // Notify only.
  702. }
  703. if (SUCCEEDED(hr))
  704. {
  705. ISubscriptionMgr2 *pSubMgr2 = NULL;
  706. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr2, (void**)&pSubMgr2);
  707. if (SUCCEEDED(hr))
  708. {
  709. hr = pSubMgr2->CreateSubscription(NULL, bstrURL, bstrTitle, CREATESUBS_NOUI,
  710. (SUBSCRIPTIONTYPE)dwSubType, &si);
  711. if (dwSynchronize)
  712. {
  713. BOOL bIsSubscribed;
  714. SUBSCRIPTIONCOOKIE cookie;
  715. if (SUCCEEDED(pSubMgr2->IsSubscribed(bstrURL, &bIsSubscribed)) &&
  716. bIsSubscribed &&
  717. SUCCEEDED(ReadCookieFromInetDB(bstrURL, &cookie)))
  718. {
  719. pSubMgr2->UpdateItems(SUBSMGRUPDATE_MINIMIZE, 1, &cookie);
  720. }
  721. }
  722. pSubMgr2->Release();
  723. }
  724. }
  725. }
  726. SAFEFREEBSTR(bstrURL);
  727. SAFEFREEBSTR(bstrTitle);
  728. SAFEFREEBSTR(bstrGroup);
  729. SAFEFREEBSTR(bstrUsername);
  730. SAFEFREEBSTR(bstrPassword);
  731. }
  732. reg.SetKey(NULL);
  733. return S_OK;
  734. }
  735. //
  736. // ProcessRemoveSubscriptions
  737. //
  738. HRESULT ProcessRemoveSubscriptions(HKEY hkey)
  739. {
  740. // Enumerate the subscription keys in the RemoveSubscriptions key
  741. HRESULT hr;
  742. CRegKey reg;
  743. reg.SetKey(hkey);
  744. TCHAR szSubscription[MAX_PATH];
  745. while (S_OK == reg.Next(szSubscription))
  746. {
  747. // Find the URL to delete
  748. CRegKey regSubscription;
  749. regSubscription.OpenForRead(hkey, szSubscription);
  750. BSTR bstrURL;
  751. if (SUCCEEDED(regSubscription.GetBSTRValue(c_szURL, &bstrURL)))
  752. {
  753. ISubscriptionMgr *pSubMgr = NULL;
  754. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&pSubMgr);
  755. if (SUCCEEDED(hr))
  756. {
  757. hr = pSubMgr->DeleteSubscription(bstrURL, NULL);
  758. pSubMgr->Release();
  759. }
  760. SysFreeString(bstrURL);
  761. }
  762. }
  763. reg.SetKey(NULL);
  764. return S_OK;
  765. }
  766. //
  767. // PRIVATE VERSION HANDLING CODE - REVIEW THIS CODE SHOULD HAVE BEEN STOLEN
  768. // FROM SETUP
  769. //
  770. struct MYVERSION
  771. {
  772. DWORD dw1; // most sig version number
  773. DWORD dw2;
  774. DWORD dw3;
  775. DWORD dw4; // least sig version number
  776. };
  777. int CompareDW(DWORD dw1, DWORD dw2)
  778. {
  779. if (dw1 > dw2)
  780. return 1;
  781. if (dw1 < dw2)
  782. return -1;
  783. return 0;
  784. }
  785. int CompareVersion(MYVERSION * pv1, MYVERSION * pv2)
  786. {
  787. int rv;
  788. rv = CompareDW(pv1->dw1, pv2->dw1);
  789. if (rv == 0)
  790. {
  791. rv = CompareDW(pv1->dw2, pv2->dw2);
  792. if (rv == 0)
  793. {
  794. rv = CompareDW(pv1->dw3, pv2->dw3);
  795. if (rv == 0)
  796. {
  797. rv = CompareDW(pv1->dw4, pv2->dw4);
  798. }
  799. }
  800. }
  801. return rv;
  802. }
  803. //
  804. // Returns TRUE if an INT was parsed and *pwsz is NOT NULL
  805. // if a . was found
  806. //
  807. BOOL GetDWORDFromStringAndAdvancePtr(DWORD *pdw, LPWSTR *pwsz)
  808. {
  809. if (!StrToIntExW(*pwsz, 0, (int *)pdw))
  810. return FALSE;
  811. *pwsz = StrChrW(*pwsz, L'.');
  812. if (*pwsz)
  813. *pwsz = *pwsz +1;
  814. return TRUE;
  815. }
  816. BOOL GetVersionFromString(MYVERSION *pver, LPWSTR pwsz)
  817. {
  818. BOOL rv;
  819. rv = GetDWORDFromStringAndAdvancePtr(&pver->dw1, &pwsz);
  820. if (!rv || pwsz == NULL)
  821. return FALSE;
  822. rv = GetDWORDFromStringAndAdvancePtr(&pver->dw2, &pwsz);
  823. if (!rv || pwsz == NULL)
  824. return FALSE;
  825. rv = GetDWORDFromStringAndAdvancePtr(&pver->dw3, &pwsz);
  826. if (!rv || pwsz == NULL)
  827. return FALSE;
  828. rv = GetDWORDFromStringAndAdvancePtr(&pver->dw4, &pwsz);
  829. if (!rv)
  830. return FALSE;
  831. return TRUE;
  832. }
  833. //
  834. // ProcessRemoveAllChannels
  835. //
  836. HRESULT ProcessRemoveAllChannels(HKEY hkey)
  837. {
  838. HRESULT hr;
  839. HINSTANCE hAdvPack = NULL;
  840. DELNODE pfDELNODE = NULL;
  841. IChannelMgrPriv *pChannelMgrPriv = NULL;
  842. CRegKey regAdd;
  843. regAdd.SetKey(hkey);
  844. TCHAR szChannelFolder[MAX_PATH];
  845. hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgrPriv, (void**)&pChannelMgrPriv);
  846. if (FAILED(hr))
  847. {
  848. goto Exit;
  849. }
  850. if ((hAdvPack = LoadLibrary(TEXT("advpack.dll"))) != NULL)
  851. {
  852. pfDELNODE = (DELNODE)GetProcAddress( hAdvPack, "DelNode");
  853. if (!pfDELNODE)
  854. {
  855. hr = HRESULT_FROM_WIN32(GetLastError());
  856. goto Exit;
  857. }
  858. }
  859. else
  860. {
  861. hr = HRESULT_FROM_WIN32(GetLastError());
  862. goto Exit;
  863. }
  864. // Loop Through Channel Folders to delete
  865. while (S_OK == regAdd.Next(szChannelFolder))
  866. {
  867. DWORD dwSoftware = 0, dwChannelGuide = 0;
  868. CRegKey regChannelFolder;
  869. CHAR szChannelPath[MAX_PATH];
  870. TCHAR szChannelPathT[MAX_PATH];
  871. TCHAR szFavsT[MAX_PATH]; //Retrieve Unicode data from registry
  872. BSTR bstrOldIEVersion = NULL;
  873. BOOL bVersion = TRUE;
  874. regChannelFolder.OpenForRead(hkey, szChannelFolder);
  875. // Check whether old IE version is correct.
  876. hr = regChannelFolder.GetBSTRValue(c_szOldIEVersion, &bstrOldIEVersion);
  877. if (SUCCEEDED(hr) && bstrOldIEVersion)
  878. {
  879. CRegKey regKeyIESetup;
  880. hr = regKeyIESetup.OpenForRead(HKEY_LOCAL_MACHINE, c_szRegKeyIESetup);
  881. if (SUCCEEDED(hr))
  882. {
  883. BSTR bstrRealOldIEVersion = NULL;
  884. hr = regKeyIESetup.GetBSTRValue(c_szOldIEVersion, &bstrRealOldIEVersion);
  885. if (SUCCEEDED(hr) && bstrRealOldIEVersion)
  886. {
  887. MYVERSION verOldIEVersion, verRealOldIEVersion;
  888. if (GetVersionFromString(&verOldIEVersion, bstrOldIEVersion) &&
  889. GetVersionFromString(&verRealOldIEVersion, bstrRealOldIEVersion))
  890. {
  891. //
  892. // If the old version of IE that was on this machine (verRealOldIEVersion)
  893. // is infact NEWER than the old version number in the CABs that we want to
  894. // delete (verOldIEVersion) then dont blow away old channel folder.
  895. // Otherwise default to blow away channels.
  896. //
  897. if (CompareVersion(&verRealOldIEVersion, &verOldIEVersion) > 0)
  898. {
  899. bVersion = FALSE;
  900. }
  901. }
  902. SAFEFREEBSTR(bstrRealOldIEVersion);
  903. }
  904. }
  905. SAFEFREEBSTR(bstrOldIEVersion);
  906. }
  907. if (!bVersion)
  908. {
  909. continue;
  910. }
  911. hr = regChannelFolder.GetValue(c_szChannelGuide, &dwChannelGuide);
  912. if (FAILED(hr) || (SUCCEEDED(hr) && !dwChannelGuide))
  913. {
  914. if (SUCCEEDED(pChannelMgrPriv->GetChannelFolderPath(szChannelPath, MAX_PATH, IChannelMgrPriv::CF_CHANNEL)))
  915. {
  916. // Retrieve Favorites Path from registry
  917. if (SUCCEEDED(Channel_GetBasePath((LPTSTR)szFavsT, ARRAYSIZE(szFavsT))))
  918. {
  919. // Convert from ANSI
  920. SHAnsiToTChar(szChannelPath, szChannelPathT, ARRAYSIZE(szChannelPathT));
  921. // If channel folder doesn't exist, then szChannelPath will contain the Favorites path.
  922. // Don't delete the entries.
  923. if (StrCmpI(szFavsT, szChannelPathT))
  924. pfDELNODE(szChannelPath, ADN_DONT_DEL_DIR);
  925. }
  926. }
  927. }
  928. hr = regChannelFolder.GetValue(c_szSoftware, &dwSoftware);
  929. if (FAILED(hr) || (SUCCEEDED(hr) && !dwSoftware))
  930. {
  931. if (SUCCEEDED(pChannelMgrPriv->GetChannelFolderPath(szChannelPath, MAX_PATH, IChannelMgrPriv::CF_SOFTWAREUPDATE)))
  932. {
  933. pfDELNODE(szChannelPath, ADN_DONT_DEL_DIR);
  934. }
  935. }
  936. hr = S_OK;
  937. }
  938. regAdd.SetKey(NULL);
  939. Exit:
  940. SAFERELEASE(pChannelMgrPriv);
  941. if (hAdvPack) {
  942. FreeLibrary(hAdvPack);
  943. }
  944. return hr;
  945. }
  946. //
  947. // ProcessRemoveDesktopComponents
  948. //
  949. HRESULT ProcessRemoveDesktopComponents(HKEY hkey)
  950. {
  951. // Enumerate the component keys in the ProcessRemoveDesktopComponents key
  952. // HRESULT hr;
  953. CRegKey reg;
  954. reg.SetKey(hkey);
  955. TCHAR szComponent[MAX_PATH];
  956. while (S_OK == reg.Next(szComponent))
  957. {
  958. // Find the URL to delete
  959. CRegKey regComponent;
  960. regComponent.OpenForRead(hkey, szComponent);
  961. BSTR bstrURL;
  962. if (SUCCEEDED(regComponent.GetBSTRValue(c_szURL, &bstrURL)))
  963. {
  964. SysFreeString(bstrURL);
  965. }
  966. }
  967. reg.SetKey(NULL);
  968. return S_OK;
  969. }
  970. //
  971. // NoChannelUI processing.
  972. //
  973. #define SHELLFOLDERS \
  974. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders")
  975. typedef enum _tagXMLDOCTYPE {
  976. DOC_CHANNEL,
  977. DOC_SOFTWAREUPDATE
  978. } XMLDOCTYPE;
  979. //
  980. // Get the path to the favorites directory.
  981. //
  982. HRESULT Channel_GetBasePath(LPTSTR pszPath, int cch)
  983. {
  984. ASSERT(pszPath || 0 == cch);
  985. DWORD cbPath = cch * sizeof(TCHAR);
  986. return SHRegGetValue(HKEY_CURRENT_USER, SHELLFOLDERS, TEXT("Favorites"), SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND, NULL, pszPath, &cbPath) == ERROR_SUCCESS
  987. ? S_OK
  988. : E_FAIL;
  989. }
  990. HRESULT Channel_GetFolder(LPTSTR pszPath, XMLDOCTYPE xdt )
  991. {
  992. TCHAR szFavs[MAX_PATH];
  993. TCHAR szChannel[MAX_PATH];
  994. HRESULT hr = E_FAIL;
  995. if (SUCCEEDED(Channel_GetBasePath(szFavs, ARRAYSIZE(szFavs))))
  996. {
  997. //
  998. // Get the potentially localized name of the Channel folder from
  999. // tack this on the Favorites path
  1000. //
  1001. MLLoadString(
  1002. ((xdt == DOC_CHANNEL)? IDS_CHANNEL_FOLDER : IDS_SOFTWAREUPDATE_FOLDER),
  1003. szChannel, MAX_PATH);
  1004. PathCombine(pszPath, szFavs, szChannel);
  1005. hr = S_OK;
  1006. }
  1007. return hr;
  1008. }
  1009. //
  1010. // Set/Clear the "hidden" attribute of a channel directory.
  1011. //
  1012. void ShowChannelDirectory(BOOL fShow, XMLDOCTYPE xdt)
  1013. {
  1014. TCHAR szPath[MAX_PATH];
  1015. DWORD dwAttributes;
  1016. if (SUCCEEDED(Channel_GetFolder(szPath, xdt)))
  1017. {
  1018. dwAttributes = GetFileAttributes(szPath);
  1019. if (0xffffffff != dwAttributes)
  1020. {
  1021. if (fShow && (dwAttributes & FILE_ATTRIBUTE_HIDDEN))
  1022. {
  1023. SetFileAttributes(szPath, dwAttributes & ~FILE_ATTRIBUTE_HIDDEN);
  1024. }
  1025. else if (!fShow && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
  1026. {
  1027. SetFileAttributes(szPath, dwAttributes | FILE_ATTRIBUTE_HIDDEN);
  1028. }
  1029. }
  1030. }
  1031. }
  1032. //
  1033. // Hide or show channel directories
  1034. //
  1035. void ShowChannelDirectories(BOOL fShow)
  1036. {
  1037. ShowChannelDirectory(fShow, DOC_CHANNEL);
  1038. ShowChannelDirectory(fShow, DOC_SOFTWAREUPDATE);
  1039. }