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.

1133 lines
31 KiB

  1. #include "private.h"
  2. #include "subsmgrp.h"
  3. #include "offsync.h"
  4. #include "offl_cpp.h"
  5. #include "factory.h"
  6. #include "notfcvt.h"
  7. #define TF_THISMODULE TF_WEBCHECKCORE
  8. #include "resource.h"
  9. #define INITGUIDS
  10. #include <shlguid.h>
  11. #define MLUI_INIT
  12. #include <mluisupp.h>
  13. //
  14. // Downlevel delay load support (we forward to shlwapi)
  15. //
  16. #include <delayimp.h>
  17. PfnDliHook __pfnDliFailureHook;
  18. // We're going to use our own new and delete so that we can
  19. // use shdocvw's leak detection code
  20. //
  21. //
  22. // Subscription property names
  23. //
  24. // Agent Start
  25. extern const WCHAR c_szPropURL[] = L"URL";
  26. extern const WCHAR c_szPropName[] = L"Name";
  27. extern const WCHAR c_szPropAgentFlags[] = L"AgentFlags";
  28. extern const WCHAR c_szPropCrawlLevels[] = L"RecurseLevels";
  29. extern const WCHAR c_szPropCrawlFlags[] = L"RecurseFlags";
  30. extern const WCHAR c_szPropCrawlMaxSize[] = L"MaxSizeKB";
  31. extern const WCHAR c_szPropCrawlChangesOnly[] = L"CheckChangesOnly";
  32. extern const WCHAR c_szPropChangeCode[] = L"ChangeCode";
  33. extern const WCHAR c_szPropCrawlUsername[] = L"Username";
  34. extern const WCHAR c_szPropEmailNotf[] = L"EmailNotification";
  35. extern const WCHAR c_szPropCrawlLocalDest[] = L"LocalDest";
  36. extern const WCHAR c_szPropCrawlGroupID[] = L"GroupID";
  37. extern const WCHAR c_szPropCrawlNewGroupID[] = L"NewGroupID";
  38. extern const WCHAR c_szPropActualProgressMax[] = L"ActualProgressMax";
  39. extern const WCHAR c_szPropCrawlActualSize[] = L"ActualSizeKB";
  40. extern const WCHAR c_szPropEnableShortcutGleam[] = L"EnableShortcutGleam";
  41. extern const WCHAR c_szPropChannelFlags[] = L"ChannelFlags";
  42. extern const WCHAR c_szPropChannel[] = L"Channel";
  43. extern const WCHAR c_szPropDesktopComponent[] = L"DesktopComponent";
  44. extern const WCHAR c_szPropStatusCode[] = L"StatusCode";
  45. extern const WCHAR c_szPropStatusString[] = L"StatusString";
  46. extern const WCHAR c_szPropCompletionTime[] = L"CompletionTime";
  47. extern const WCHAR c_szPropPassword[] = L"Password";
  48. // End Report
  49. extern const WCHAR c_szPropEmailURL[] = L"EmailURL";
  50. extern const WCHAR c_szPropEmailFlags[] = L"EmailFlags";
  51. extern const WCHAR c_szPropEmailTitle[] = L"EmailTitle";
  52. extern const WCHAR c_szPropEmailAbstract[] = L"EmailAbstract";
  53. extern const WCHAR c_szPropCharSet[] = L"CharSet";
  54. // Tray Agent Properties
  55. extern const WCHAR c_szPropGuidsArr[] = L"Guids Array";
  56. // Tracking Properties
  57. extern const WCHAR c_szTrackingCookie[] = L"LogGroupID";
  58. extern const WCHAR c_szTrackingPostURL[] = L"PostURL";
  59. extern const WCHAR c_szPostingRetry[] = L"PostFailureRetry";
  60. extern const WCHAR c_szPostHeader[] = L"PostHeader";
  61. extern const WCHAR c_szPostPurgeTime[] = L"PostPurgeTime";
  62. // Delivery Agent Properties
  63. extern const WCHAR c_szStartCookie[] = L"StartCookie";
  64. // Initial cookie in AGENT_INIT
  65. extern const WCHAR c_szInitCookie[] = L"InitCookie";
  66. STDAPI OfflineFolderRegisterServer();
  67. STDAPI OfflineFolderUnregisterServer();
  68. // Count number of objects and number of locks.
  69. ULONG g_cObj=0;
  70. ULONG g_cLock=0;
  71. // DLL Instance handle
  72. HINSTANCE g_hInst=0;
  73. // other globals
  74. BOOL g_fIsWinNT; // Are we on WinNT? Always initialized.
  75. BOOL g_fIsWinNT5; // Is it NT5?
  76. BOOL g_fIsMillennium = FALSE;
  77. // logging globals
  78. BOOL g_fCheckedForLog = FALSE; // have we checked registry?
  79. TCHAR * g_pszLoggingFile = NULL; // file to write log to
  80. TCHAR szInternetSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings");
  81. TCHAR szProxyEnable[] = TEXT("ProxyEnable");
  82. const TCHAR c_szRegKey[] = WEBCHECK_REGKEY;
  83. const TCHAR c_szRegKeyUsernames[] = WEBCHECK_REGKEY TEXT("\\UserFormFieldNames");
  84. const TCHAR c_szRegKeyPasswords[] = WEBCHECK_REGKEY TEXT("\\PasswordFormFieldNames");
  85. const TCHAR c_szRegKeyStore[] = WEBCHECK_REGKEY_STORE;
  86. // Pstore related variables.
  87. static PST_PROVIDERID s_provID = GUID_NULL;
  88. // {14D96C20-255B-11d1-898F-00C04FB6BFC4}
  89. static const GUID GUID_PStoreType = { 0x14d96c20, 0x255b, 0x11d1, { 0x89, 0x8f, 0x0, 0xc0, 0x4f, 0xb6, 0xbf, 0xc4 } };
  90. static PST_KEY s_Key = PST_KEY_CURRENT_USER;
  91. static WCHAR c_szInfoDel[] = L"InfoDelivery";
  92. static WCHAR c_szSubscriptions[] = L"Subscriptions";
  93. void SetupDelayloadErrorHandler()
  94. {
  95. __pfnDliFailureHook = (PfnDliHook)GetProcAddress(GetModuleHandleA("shlwapi.dll"), "DelayLoadFailureHook");
  96. }
  97. //////////////////////////////////////////////////////////////////////////
  98. //
  99. // DLL entry point
  100. //
  101. //////////////////////////////////////////////////////////////////////////
  102. EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
  103. {
  104. switch (ulReason)
  105. {
  106. case DLL_PROCESS_ATTACH:
  107. {
  108. SHFusionInitializeFromModule((HMODULE)hInstance);
  109. OSVERSIONINFOA vi;
  110. DisableThreadLibraryCalls(hInstance);
  111. g_hInst = hInstance;
  112. SetupDelayloadErrorHandler();
  113. MLLoadResources(g_hInst, TEXT("webchklc.dll"));
  114. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  115. GetVersionExA(&vi);
  116. if(vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  117. g_fIsWinNT = TRUE;
  118. if(vi.dwMajorVersion > 4)
  119. g_fIsWinNT5 = TRUE;
  120. else
  121. g_fIsWinNT5 = FALSE;
  122. } else {
  123. g_fIsWinNT = FALSE;
  124. g_fIsWinNT5 = FALSE;
  125. g_fIsMillennium = IsOS(OS_MILLENNIUM);
  126. }
  127. #ifdef DEBUG
  128. g_qwTraceFlags = TF_NEVER; // Default if not overridden from INI
  129. CcshellGetDebugFlags();
  130. #endif
  131. }
  132. break;
  133. case DLL_PROCESS_DETACH:
  134. {
  135. MLFreeResources(g_hInst);
  136. SHFusionUninitialize();
  137. }
  138. break;
  139. }
  140. return TRUE;
  141. }
  142. //////////////////////////////////////////////////////////////////////////
  143. //
  144. // Standard OLE entry points
  145. //
  146. //////////////////////////////////////////////////////////////////////////
  147. // Class factory -
  148. // For classes with no special needs these macros should take care of it.
  149. // If your class needs some special stuff just to get the ball rolling,
  150. // implement your own CreateInstance method.
  151. #define DEFINE_CREATEINSTANCE(cls, iface) \
  152. HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \
  153. { \
  154. ASSERT(NULL == punkOuter); \
  155. ASSERT(NULL != ppunk); \
  156. *ppunk = (iface *)new cls; \
  157. return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \
  158. }
  159. #define DEFINE_AGGREGATED_CREATEINSTANCE(cls, iface) \
  160. HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \
  161. { \
  162. ASSERT(NULL != punkOuter); \
  163. ASSERT(NULL != ppunk); \
  164. *ppunk = (iface *)new cls(punkOuter); \
  165. return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \
  166. }
  167. DEFINE_CREATEINSTANCE(CWebCheck, IOleCommandTarget)
  168. DEFINE_CREATEINSTANCE(CChannelAgent, ISubscriptionAgentControl)
  169. DEFINE_CREATEINSTANCE(COfflineFolder, IShellFolder)
  170. DEFINE_CREATEINSTANCE(CSubscriptionMgr, ISubscriptionMgr2);
  171. DEFINE_CREATEINSTANCE(CWCPostAgent, ISubscriptionAgentControl)
  172. DEFINE_CREATEINSTANCE(CCDLAgent, ISubscriptionAgentControl)
  173. DEFINE_CREATEINSTANCE(COfflineSync, ISyncMgrSynchronize)
  174. const CFactoryData g_FactoryData[] =
  175. {
  176. { &CLSID_WebCheck, CWebCheck_CreateInstance, 0 }
  177. ,{ &CLSID_WebCrawlerAgent, CWebCrawler::CreateInstance, 0 }
  178. ,{ &CLSID_ChannelAgent, CChannelAgent_CreateInstance, 0 }
  179. ,{ &CLSID_OfflineFolder, COfflineFolder_CreateInstance, 0 }
  180. ,{ &CLSID_SubscriptionMgr, CSubscriptionMgr_CreateInstance, 0 }
  181. ,{ &CLSID_PostAgent, CWCPostAgent_CreateInstance, 0 }
  182. ,{ &CLSID_CDLAgent, CCDLAgent_CreateInstance, 0 }
  183. ,{ &CLSID_WebCheckOfflineSync, COfflineSync_CreateInstance, 0 }
  184. };
  185. HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  186. {
  187. HRESULT hr = S_OK;
  188. IUnknown *punk = NULL;
  189. *ppv = NULL;
  190. // Validate request
  191. for (int i = 0; i < ARRAYSIZE(g_FactoryData); i++)
  192. {
  193. if (rclsid == *g_FactoryData[i].m_pClsid)
  194. {
  195. punk = new CClassFactory(&g_FactoryData[i]);
  196. break;
  197. }
  198. }
  199. if (ARRAYSIZE(g_FactoryData) <= i)
  200. {
  201. ASSERT(NULL == punk);
  202. hr = CLASS_E_CLASSNOTAVAILABLE;
  203. }
  204. else if (NULL == punk)
  205. {
  206. hr = E_OUTOFMEMORY;
  207. }
  208. else
  209. {
  210. hr = punk->QueryInterface(riid, ppv);
  211. punk->Release();
  212. }
  213. ASSERT((SUCCEEDED(hr) && (NULL != *ppv)) ||
  214. (FAILED(hr) && (NULL == *ppv)));
  215. return hr;
  216. }
  217. STDAPI DllCanUnloadNow(void)
  218. {
  219. // check objects and locks
  220. return (0L == DllGetRef() && 0L == DllGetLock()) ? S_OK : S_FALSE;
  221. }
  222. //////////////////////////////////////////////////////////////////////////
  223. //
  224. // helper functions
  225. //
  226. //////////////////////////////////////////////////////////////////////////
  227. int MyOleStrToStrN(LPTSTR psz, int cchMultiByte, LPCOLESTR pwsz)
  228. {
  229. StrCpyN(psz, pwsz, cchMultiByte);
  230. return cchMultiByte;
  231. }
  232. int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCTSTR psz)
  233. {
  234. StrCpyN(pwsz, psz, cchWideChar);
  235. return cchWideChar;
  236. }
  237. // Convert upper to lower for ASCII wide characters
  238. inline WCHAR MyToLower(WCHAR wch)
  239. {
  240. return (wch >= 'A' && wch <= 'Z') ? (wch - 'A'+ 'a') : wch;
  241. }
  242. // Optimized for the knowledge that urls are 7-bit characters.
  243. int MyAsciiCmpNIW(LPCWSTR pwsz1, LPCWSTR pwsz2, int iLen)
  244. {
  245. while (iLen-- && *pwsz1 && *pwsz2)
  246. {
  247. ASSERT(*pwsz1 || *pwsz2);
  248. if (MyToLower(*pwsz1++) != MyToLower(*pwsz2++))
  249. return 1;
  250. }
  251. return 0;
  252. }
  253. int MyAsciiCmpW(LPCWSTR pwsz1, LPCWSTR pwsz2)
  254. {
  255. while (*pwsz1)
  256. {
  257. if (*pwsz1++ != *pwsz2++)
  258. {
  259. return 1;
  260. }
  261. }
  262. if (*pwsz2)
  263. return 1;
  264. return 0;
  265. }
  266. #ifdef DEBUG
  267. void DumpIID(LPCSTR psz, REFIID riid)
  268. {
  269. // Convert the GUID to an ANSI string
  270. TCHAR pszGUID[GUIDSTR_MAX];
  271. WCHAR pwszGUID[GUIDSTR_MAX];
  272. int len = StringFromGUID2(riid, pwszGUID, ARRAYSIZE(pwszGUID));
  273. ASSERT(GUIDSTR_MAX == len);
  274. ASSERT(0 == pwszGUID[GUIDSTR_MAX - 1]);
  275. len = MyOleStrToStrN(pszGUID, GUIDSTR_MAX, pwszGUID);
  276. ASSERT(GUIDSTR_MAX == len);
  277. ASSERT(0 == pszGUID[GUIDSTR_MAX - 1]);
  278. // See if the IID has a string in the registry
  279. TCHAR pszKey[MAX_PATH];
  280. TCHAR pszIIDName[MAX_PATH];
  281. wnsprintf(pszKey, ARRAYSIZE(pszKey), TEXT("Interface\\%s"), pszGUID);
  282. BOOL fRet;
  283. fRet = ReadRegValue(HKEY_CLASSES_ROOT, pszKey, NULL, pszIIDName, sizeof(pszIIDName));
  284. // Print all the strings
  285. if (fRet)
  286. TraceMsg(TF_THISMODULE, "%s - %s %s", psz, pszIIDName, pszGUID);
  287. else
  288. TraceMsg(TF_THISMODULE, "%s - %s", psz, pszGUID);
  289. }
  290. #endif // DEBUG
  291. //////////////////////////////////////////////////////////////////////////
  292. //
  293. // Autoregistration entry points
  294. //
  295. //////////////////////////////////////////////////////////////////////////
  296. HRESULT CallRegInstall(LPSTR szSection)
  297. {
  298. HRESULT hr = E_FAIL;
  299. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  300. if (hinstAdvPack)
  301. {
  302. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, achREGINSTALL);
  303. if (pfnri)
  304. {
  305. hr = pfnri(g_hInst, szSection, NULL);
  306. }
  307. FreeLibrary(hinstAdvPack);
  308. }
  309. return hr;
  310. }
  311. STDAPI DllRegisterServer(void)
  312. {
  313. // Delete any old registration entries, then add the new ones.
  314. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  315. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  316. // CallRegInstall("UnReg");
  317. CallRegInstall("Reg");
  318. if (hinstAdvPack)
  319. {
  320. FreeLibrary(hinstAdvPack);
  321. }
  322. // OfflineFolder registers.
  323. OfflineFolderRegisterServer();
  324. // do external setup stuff on non-NT5 platforms
  325. if(FALSE == g_fIsWinNT5)
  326. {
  327. // register LCE
  328. HINSTANCE hLCE = LoadLibrary(TEXT("estier2.dll"));
  329. if (hLCE)
  330. {
  331. LCEREGISTER regfunc;
  332. regfunc = (LCEREGISTER)GetProcAddress(hLCE, "LCERegisterServer");
  333. if (regfunc)
  334. if (FAILED(regfunc(NULL)))
  335. DBG_WARN("LCE register server failed!");
  336. FreeLibrary(hLCE);
  337. }
  338. // create reg key that SENS needs
  339. DWORD dwValue = 0;
  340. WriteRegValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Mobile\\Sens"),
  341. TEXT("Configured"), &dwValue, sizeof(DWORD), REG_DWORD);
  342. // if we're on NT4, call SENS configuration api
  343. if (g_fIsWinNT)
  344. {
  345. HINSTANCE hSENS = LoadLibrary(TEXT("senscfg.dll"));
  346. if(hSENS)
  347. {
  348. SENSREGISTER regfunc;
  349. regfunc = (SENSREGISTER)GetProcAddress(hSENS, "SensRegister");
  350. if(regfunc)
  351. if (FAILED(regfunc()))
  352. DBG_WARN("SENS register server failed!");
  353. FreeLibrary(hSENS);
  354. }
  355. }
  356. }
  357. return NOERROR;
  358. }
  359. STDAPI
  360. DllUnregisterServer(void)
  361. {
  362. HRESULT hr;
  363. hr = OfflineFolderUnregisterServer();
  364. hr = CallRegInstall("UnReg");
  365. // do external unregister stuff on non-NT5 platforms
  366. if(FALSE == g_fIsWinNT5) {
  367. // unregister SENS on NT4
  368. if(g_fIsWinNT){
  369. HINSTANCE hSENS = LoadLibrary(TEXT("senscfg.dll"));
  370. if(hSENS) {
  371. SENSREGISTER regfunc;
  372. regfunc = (SENSREGISTER)GetProcAddress(hSENS, "SensUnregister");
  373. if(regfunc)
  374. regfunc();
  375. FreeLibrary(hSENS);
  376. }
  377. }
  378. // unregister LCE
  379. HINSTANCE hLCE = LoadLibrary(TEXT("estier2.dll"));
  380. if(hLCE) {
  381. LCEUNREGISTER unregfunc;
  382. unregfunc = (LCEUNREGISTER)GetProcAddress(hLCE, "LCEUnregisterServer");
  383. if(unregfunc)
  384. unregfunc(NULL);
  385. FreeLibrary(hLCE);
  386. }
  387. // Remove Sens key
  388. SHDeleteKey( HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Mobile\\Sens") );
  389. }
  390. return hr;
  391. }
  392. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  393. {
  394. HRESULT hr = S_OK;
  395. typedef enum { InstallNone, InstallPolicies, InstallPerUser } InstallType;
  396. InstallType installType = InstallNone;
  397. if (pszCmdLine && *pszCmdLine)
  398. {
  399. //
  400. // Setup will call DllInstall by running 'regsvr32 /n /i:Policy webcheck.dll'.
  401. // This tells webcheck to process the Infodelivery Admin Policies.
  402. //
  403. if (0 == StrCmpIW(pszCmdLine, TEXTW("policy")))
  404. {
  405. installType = InstallPolicies;
  406. }
  407. else if (0 == StrCmpIW(pszCmdLine, TEXTW("U")))
  408. {
  409. installType = InstallPerUser;
  410. }
  411. }
  412. if (bInstall && (installType != InstallNone))
  413. {
  414. hr = CoInitialize(NULL);
  415. if (SUCCEEDED(hr))
  416. {
  417. switch (installType)
  418. {
  419. case InstallPolicies:
  420. hr = ProcessInfodeliveryPolicies();
  421. break;
  422. case InstallPerUser:
  423. hr = ConvertIE4Subscriptions();
  424. DBGASSERT(SUCCEEDED(hr), "webcheck DllInstall - Failed to convert notification manager subscriptions");
  425. break;
  426. }
  427. }
  428. CoUninitialize();
  429. }
  430. return SUCCEEDED(hr) ? S_OK : hr;
  431. }
  432. //////////////////////////////////////////////////////////////////////////
  433. //
  434. // Helper functions for Subscription Store
  435. //
  436. //////////////////////////////////////////////////////////////////////////
  437. // Can return S_OK with NULL bstr
  438. HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet)
  439. {
  440. ASSERT(pItem && bstrRet);
  441. VARIANT Val;
  442. Val.vt = VT_EMPTY;
  443. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  444. (Val.vt==VT_BSTR))
  445. {
  446. *bstrRet = Val.bstrVal;
  447. return S_OK;
  448. }
  449. else
  450. {
  451. VariantClear(&Val); // free any return value of wrong type
  452. *bstrRet = NULL;
  453. return E_INVALIDARG;
  454. }
  455. }
  456. // Cannot return S_OK with emptry string
  457. HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet)
  458. {
  459. HRESULT hr;
  460. BSTR bstrRet = NULL;
  461. *ppszRet = NULL;
  462. hr = ReadBSTR(pItem, szName, &bstrRet);
  463. if (SUCCEEDED(hr) && bstrRet && bstrRet[0])
  464. {
  465. int len = (lstrlenW(bstrRet) + 1) * sizeof(WCHAR);
  466. *ppszRet = (LPWSTR) CoTaskMemAlloc(len);
  467. if (*ppszRet)
  468. {
  469. CopyMemory(*ppszRet, bstrRet, len);
  470. }
  471. }
  472. SAFEFREEBSTR(bstrRet);
  473. if (*ppszRet)
  474. return S_OK;
  475. else
  476. return E_FAIL;
  477. }
  478. HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet)
  479. {
  480. HRESULT hr;
  481. BSTR bstrRet = NULL;
  482. *ppszRet = NULL;
  483. hr = ReadBSTR(pItem, szName, &bstrRet);
  484. if (SUCCEEDED(hr) && bstrRet && bstrRet[0])
  485. {
  486. // Don't forget to allocate a long string for DBCS.
  487. int len = (lstrlenW(bstrRet) + 1) * sizeof(CHAR) * 2;
  488. *ppszRet = (LPSTR) MemAlloc(LMEM_FIXED, len);
  489. if (*ppszRet)
  490. {
  491. SHUnicodeToAnsi(bstrRet, *ppszRet, len);
  492. }
  493. }
  494. SAFEFREEBSTR(bstrRet);
  495. if (*ppszRet)
  496. return S_OK;
  497. else
  498. return E_FAIL;
  499. }
  500. HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet)
  501. {
  502. ASSERT(pItem && pBoolRet);
  503. VARIANT Val;
  504. Val.vt = VT_EMPTY;
  505. // accept VT_I4 or VT_BOOL
  506. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  507. (Val.vt==VT_BOOL || Val.vt==VT_I4))
  508. {
  509. if (Val.vt==VT_I4)
  510. {
  511. if (Val.lVal)
  512. *pBoolRet = VARIANT_TRUE;
  513. else
  514. *pBoolRet = VARIANT_FALSE;
  515. }
  516. else
  517. *pBoolRet = Val.boolVal;
  518. return S_OK;
  519. }
  520. else
  521. {
  522. VariantClear(&Val); // free any return value of wrong type
  523. return E_INVALIDARG;
  524. }
  525. }
  526. HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet)
  527. {
  528. ASSERT(pItem && pscRet);
  529. VARIANT Val;
  530. Val.vt = VT_EMPTY;
  531. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && Val.vt == VT_ERROR)
  532. {
  533. *pscRet = Val.scode;
  534. return S_OK;
  535. }
  536. else
  537. {
  538. VariantClear(&Val);
  539. return E_INVALIDARG;
  540. }
  541. }
  542. HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName)
  543. {
  544. ASSERT(pItem);
  545. VARIANT Val;
  546. Val.vt = VT_EMPTY;
  547. return pItem->WriteProperties(1, &szName, &Val);
  548. }
  549. HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal)
  550. {
  551. ASSERT(pItem);
  552. VARIANT Val;
  553. Val.vt = VT_ERROR;
  554. Val.scode = scVal;
  555. return pItem->WriteProperties(1, &szName, &Val);
  556. }
  557. HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet)
  558. {
  559. ASSERT(pItem && pdwRet);
  560. VARIANT Val;
  561. Val.vt = VT_EMPTY;
  562. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  563. (Val.vt==VT_I4 || Val.vt==VT_I2))
  564. {
  565. if (Val.vt==VT_I4)
  566. *pdwRet = (DWORD) Val.lVal;
  567. else
  568. *pdwRet = (DWORD) Val.iVal;
  569. return S_OK;
  570. }
  571. else
  572. {
  573. VariantClear(&Val); // free any return value of wrong type
  574. return E_INVALIDARG;
  575. }
  576. }
  577. HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet)
  578. {
  579. ASSERT(pItem && pllRet);
  580. VARIANT Val;
  581. Val.vt = VT_EMPTY;
  582. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  583. (Val.vt==VT_CY))
  584. {
  585. *pllRet = *((LONGLONG *) &(Val.cyVal));
  586. return S_OK;
  587. }
  588. else
  589. {
  590. *pllRet = 0;
  591. VariantClear(&Val); // free any return value of wrong type
  592. return E_INVALIDARG;
  593. }
  594. }
  595. HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid)
  596. {
  597. ASSERT(pItem && pGuid);
  598. BSTR bstrGUID = NULL;
  599. HRESULT hr = E_INVALIDARG;
  600. if (SUCCEEDED(ReadBSTR(pItem, szName, &bstrGUID)) &&
  601. SUCCEEDED(CLSIDFromString(bstrGUID, pGuid)))
  602. {
  603. hr = NOERROR;
  604. }
  605. SAFEFREEBSTR(bstrGUID);
  606. return hr;
  607. }
  608. HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid)
  609. {
  610. ASSERT(pItem && pGuid);
  611. WCHAR wszCookie[GUIDSTR_MAX];
  612. #ifdef DEBUG
  613. int len =
  614. #endif
  615. StringFromGUID2(*pGuid, wszCookie, ARRAYSIZE(wszCookie));
  616. ASSERT(GUIDSTR_MAX == len);
  617. return WriteOLESTR(pItem, szName, wszCookie);
  618. }
  619. HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal)
  620. {
  621. VARIANT Val;
  622. Val.vt = VT_CY;
  623. Val.cyVal = *((CY *) &llVal);
  624. return pItem->WriteProperties(1, &szName, &Val);
  625. }
  626. HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal)
  627. {
  628. VARIANT Val;
  629. Val.vt = VT_I4;
  630. Val.lVal = dwVal;
  631. return pItem->WriteProperties(1, &szName, &Val);
  632. }
  633. HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal)
  634. {
  635. ASSERT(pItem && dtVal);
  636. VARIANT Val;
  637. Val.vt = VT_EMPTY;
  638. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_DATE))
  639. {
  640. *dtVal = Val.date;
  641. return S_OK;
  642. }
  643. else
  644. {
  645. VariantClear(&Val); // free any return value of wrong type
  646. return E_INVALIDARG;
  647. }
  648. }
  649. HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal)
  650. {
  651. VARIANT Val;
  652. Val.vt = VT_DATE;
  653. Val.date= *dtVal;
  654. return pItem->WriteProperties(1, &szName, &Val);
  655. }
  656. HRESULT ReadVariant (ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet)
  657. {
  658. ASSERT(pvarRet->vt == VT_EMPTY);
  659. return pItem->ReadProperties(1, &szName, pvarRet);
  660. }
  661. HRESULT WriteVariant (ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal)
  662. {
  663. return pItem->WriteProperties(1, &szName, pvarVal);
  664. }
  665. HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal)
  666. {
  667. VARIANT Val;
  668. Val.vt = VT_BSTR;
  669. Val.bstrVal = SysAllocString(szVal);
  670. HRESULT hr = pItem->WriteProperties(1, &szName, &Val);
  671. SysFreeString(Val.bstrVal);
  672. return hr;
  673. }
  674. HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal)
  675. {
  676. VARIANT Val;
  677. BSTR bstrVal;
  678. HRESULT hr;
  679. bstrVal = SysAllocStringByteLen(szVal, lstrlenA(szVal));
  680. if (bstrVal)
  681. {
  682. Val.vt = VT_BSTR;
  683. Val.bstrVal = bstrVal;
  684. hr = pItem->WriteProperties(1, &szName, &Val);
  685. SysFreeString(bstrVal);
  686. }
  687. else
  688. {
  689. hr = E_OUTOFMEMORY;
  690. }
  691. return hr;
  692. }
  693. HRESULT WriteResSTR(ISubscriptionItem *pItem, LPCWSTR szName, UINT uID)
  694. {
  695. TCHAR szString[MAX_RES_STRING_LEN];
  696. if (MLLoadString(uID, szString, ARRAYSIZE(szString)))
  697. {
  698. return WriteTSTR(pItem, szName, szString);
  699. }
  700. return E_INVALIDARG;
  701. }
  702. DWORD LogEvent(LPTSTR pszFormat, ...)
  703. {
  704. // check registry if necessary
  705. if(FALSE == g_fCheckedForLog) {
  706. TCHAR pszFilePath[MAX_PATH];
  707. if(ReadRegValue(HKEY_CURRENT_USER, c_szRegKey, TEXT("LoggingFile"),
  708. pszFilePath, sizeof(pszFilePath))) {
  709. int nLen = lstrlen(pszFilePath) + 1;
  710. g_pszLoggingFile = new TCHAR[nLen];
  711. if(g_pszLoggingFile) {
  712. StrCpyN(g_pszLoggingFile, pszFilePath, nLen);
  713. }
  714. }
  715. g_fCheckedForLog = TRUE;
  716. }
  717. if(g_pszLoggingFile) {
  718. TCHAR pszString[MAX_PATH+INTERNET_MAX_URL_LENGTH];
  719. SYSTEMTIME st;
  720. HANDLE hLog;
  721. DWORD dwWritten;
  722. va_list va;
  723. hLog = CreateFile(g_pszLoggingFile, GENERIC_WRITE, 0, NULL,
  724. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  725. if(INVALID_HANDLE_VALUE == hLog)
  726. return GetLastError();
  727. // seek to end of file
  728. SetFilePointer(hLog, 0, 0, FILE_END);
  729. // dump time
  730. GetLocalTime(&st);
  731. wnsprintf(pszString, ARRAYSIZE(pszString), TEXT("\r\n%02d:%02d:%02d - "), st.wHour, st.wMinute, st.wSecond);
  732. WriteFile(hLog, pszString, lstrlen(pszString), &dwWritten, NULL);
  733. // dump passed in string
  734. va_start(va, pszFormat);
  735. wvnsprintf(pszString, ARRAYSIZE(pszString), pszFormat, va);
  736. va_end(va);
  737. WriteFile(hLog, pszString, lstrlen(pszString), &dwWritten, NULL);
  738. // clean up
  739. CloseHandle(hLog);
  740. }
  741. return 0;
  742. }
  743. // Functions related to saving and restoring user passwords from the pstore.
  744. // We have wrappers around Create and Release to allow for future caching of the pstore
  745. // instance within webcheck.
  746. STDAPI CreatePStore(IPStore **ppIPStore)
  747. {
  748. HRESULT hr;
  749. hr = PStoreCreateInstance ( ppIPStore,
  750. IsEqualGUID(s_provID, GUID_NULL) ? NULL : &s_provID,
  751. NULL,
  752. 0);
  753. return hr;
  754. }
  755. STDAPI ReleasePStore(IPStore *pIPStore)
  756. {
  757. HRESULT hr;
  758. if (pIPStore)
  759. {
  760. pIPStore->Release();
  761. hr = S_OK;
  762. }
  763. else
  764. {
  765. hr = E_POINTER;
  766. }
  767. return hr;
  768. }
  769. // Given a field name this figures out the type and sub-type in the pstore
  770. // that should be queried. Currently these are hard-coded.
  771. STDAPI GetPStoreTypes(LPCWSTR /* wszField */, GUID * pguidType, GUID * pguidSubType)
  772. {
  773. *pguidType = GUID_PStoreType;
  774. *pguidSubType = GUID_NULL;
  775. return S_OK;
  776. }
  777. STDAPI ReadNotificationPassword(LPCWSTR wszUrl, BSTR *pbstrPassword)
  778. {
  779. GUID itemType = GUID_NULL;
  780. GUID itemSubtype = GUID_NULL;
  781. PST_PROMPTINFO promptInfo = {0};
  782. IPStore* pStore = NULL;
  783. HRESULT hr ;
  784. if (wszUrl == NULL || pbstrPassword == NULL)
  785. return E_POINTER;
  786. // Will return NULL if there is no password entry or we
  787. // fail for some reason.
  788. *pbstrPassword = NULL;
  789. promptInfo.cbSize = sizeof(promptInfo);
  790. promptInfo.szPrompt = NULL;
  791. promptInfo.dwPromptFlags = 0;
  792. promptInfo.hwndApp = NULL;
  793. hr = CreatePStore(&pStore);
  794. if (SUCCEEDED(hr))
  795. {
  796. ASSERT(pStore != NULL);
  797. hr = GetPStoreTypes(wszUrl, &itemType, &itemSubtype);
  798. if (SUCCEEDED(hr))
  799. {
  800. DWORD cbData;
  801. BYTE * pbData = NULL;
  802. hr = pStore->ReadItem(
  803. s_Key,
  804. &itemType,
  805. &itemSubtype,
  806. wszUrl,
  807. &cbData,
  808. &pbData,
  809. &promptInfo,
  810. 0);
  811. if (SUCCEEDED(hr))
  812. {
  813. *pbstrPassword = SysAllocString((OLECHAR *)pbData);
  814. CoTaskMemFree(pbData);
  815. hr = S_OK;
  816. }
  817. }
  818. ReleasePStore(pStore);
  819. }
  820. return hr;
  821. }
  822. STDAPI WriteNotificationPassword(LPCWSTR wszUrl, BSTR bstrPassword)
  823. {
  824. HRESULT hr;
  825. PST_TYPEINFO typeInfo;
  826. PST_PROMPTINFO promptInfo;
  827. IPStore * pStore;
  828. if (wszUrl == NULL)
  829. return E_POINTER;
  830. typeInfo.cbSize = sizeof(typeInfo);
  831. typeInfo.szDisplayName = c_szInfoDel;
  832. promptInfo.cbSize = sizeof(promptInfo);
  833. promptInfo.dwPromptFlags = 0;
  834. promptInfo.hwndApp = NULL;
  835. promptInfo.szPrompt = NULL;
  836. hr = CreatePStore(&pStore);
  837. if (SUCCEEDED(hr))
  838. {
  839. GUID itemType = GUID_NULL;
  840. GUID itemSubtype = GUID_NULL;
  841. ASSERT(pStore != NULL);
  842. hr = GetPStoreTypes(wszUrl, &itemType, &itemSubtype);
  843. if (SUCCEEDED(hr))
  844. {
  845. hr = pStore->CreateType(s_Key, &itemType, &typeInfo, 0);
  846. // PST_E_TYPE_EXISTS implies type already exists which is just fine
  847. // by us.
  848. if (SUCCEEDED(hr) || hr == PST_E_TYPE_EXISTS)
  849. {
  850. typeInfo.szDisplayName = c_szSubscriptions;
  851. hr = pStore->CreateSubtype(
  852. s_Key,
  853. &itemType,
  854. &itemSubtype,
  855. &typeInfo,
  856. NULL,
  857. 0);
  858. if (SUCCEEDED(hr) || hr == PST_E_TYPE_EXISTS)
  859. {
  860. if (bstrPassword != NULL)
  861. {
  862. hr = pStore->WriteItem(
  863. s_Key,
  864. &itemType,
  865. &itemSubtype,
  866. wszUrl,
  867. ((lstrlenW(bstrPassword)+1) * sizeof(WCHAR)),
  868. (BYTE *)bstrPassword,
  869. &promptInfo,
  870. PST_CF_NONE,
  871. 0);
  872. }
  873. else
  874. {
  875. hr = pStore->DeleteItem(
  876. s_Key,
  877. &itemType,
  878. &itemSubtype,
  879. wszUrl,
  880. &promptInfo,
  881. 0);
  882. }
  883. }
  884. }
  885. }
  886. ReleasePStore(pStore);
  887. }
  888. return hr;
  889. }
  890. HRESULT WritePassword(ISubscriptionItem *pItem, BSTR bstrPassword)
  891. {
  892. BSTR bstrURL = NULL;
  893. HRESULT hr = E_FAIL;
  894. hr = ReadBSTR(pItem, c_szPropURL, &bstrURL);
  895. RETURN_ON_FAILURE(hr);
  896. hr = WriteNotificationPassword(bstrURL, bstrPassword);
  897. SAFEFREEBSTR(bstrURL);
  898. return hr;
  899. }
  900. HRESULT ReadPassword(ISubscriptionItem *pItem, BSTR * pBstrPassword)
  901. {
  902. BSTR bstrURL = NULL;
  903. HRESULT hr = E_FAIL;
  904. hr = ReadBSTR(pItem, c_szPropURL, &bstrURL);
  905. RETURN_ON_FAILURE(hr);
  906. ASSERT(pBstrPassword);
  907. hr = ReadNotificationPassword(bstrURL, pBstrPassword);
  908. SAFEFREEBSTR(bstrURL);
  909. return hr;
  910. }