Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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