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.

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