|
|
#include "private.h"
#include "subsmgrp.h"
#include "offsync.h"
#include "offl_cpp.h"
#include "factory.h"
#include "notfcvt.h"
#define TF_THISMODULE TF_WEBCHECKCORE
#include "resource.h"
#define INITGUIDS
#include <shlguid.h>
#define MLUI_INIT
#include <mluisupp.h>
// We're going to use our own new and delete so that we can
// use shdocvw's leak detection code
//
//
// Subscription property names
//
// Agent Start
extern const WCHAR c_szPropURL[] = L"URL"; extern const WCHAR c_szPropName[] = L"Name"; extern const WCHAR c_szPropAgentFlags[] = L"AgentFlags"; extern const WCHAR c_szPropCrawlLevels[] = L"RecurseLevels"; extern const WCHAR c_szPropCrawlFlags[] = L"RecurseFlags"; extern const WCHAR c_szPropCrawlMaxSize[] = L"MaxSizeKB"; extern const WCHAR c_szPropCrawlChangesOnly[] = L"CheckChangesOnly"; extern const WCHAR c_szPropChangeCode[] = L"ChangeCode"; extern const WCHAR c_szPropCrawlUsername[] = L"Username"; extern const WCHAR c_szPropEmailNotf[] = L"EmailNotification"; extern const WCHAR c_szPropCrawlLocalDest[] = L"LocalDest"; extern const WCHAR c_szPropCrawlGroupID[] = L"GroupID"; extern const WCHAR c_szPropCrawlNewGroupID[] = L"NewGroupID"; extern const WCHAR c_szPropActualProgressMax[] = L"ActualProgressMax"; extern const WCHAR c_szPropCrawlActualSize[] = L"ActualSizeKB"; extern const WCHAR c_szPropEnableShortcutGleam[] = L"EnableShortcutGleam"; extern const WCHAR c_szPropChannelFlags[] = L"ChannelFlags"; extern const WCHAR c_szPropChannel[] = L"Channel"; extern const WCHAR c_szPropDesktopComponent[] = L"DesktopComponent"; extern const WCHAR c_szPropStatusCode[] = L"StatusCode"; extern const WCHAR c_szPropStatusString[] = L"StatusString"; extern const WCHAR c_szPropCompletionTime[] = L"CompletionTime"; extern const WCHAR c_szPropPassword[] = L"Password"; // End Report
extern const WCHAR c_szPropEmailURL[] = L"EmailURL"; extern const WCHAR c_szPropEmailFlags[] = L"EmailFlags"; extern const WCHAR c_szPropEmailTitle[] = L"EmailTitle"; extern const WCHAR c_szPropEmailAbstract[] = L"EmailAbstract"; extern const WCHAR c_szPropCharSet[] = L"CharSet";
// Tray Agent Properties
extern const WCHAR c_szPropGuidsArr[] = L"Guids Array";
// Tracking Properties
extern const WCHAR c_szTrackingCookie[] = L"LogGroupID"; extern const WCHAR c_szTrackingPostURL[] = L"PostURL"; extern const WCHAR c_szPostingRetry[] = L"PostFailureRetry"; extern const WCHAR c_szPostHeader[] = L"PostHeader"; extern const WCHAR c_szPostPurgeTime[] = L"PostPurgeTime";
// Delivery Agent Properties
extern const WCHAR c_szStartCookie[] = L"StartCookie";
// Initial cookie in AGENT_INIT
extern const WCHAR c_szInitCookie[] = L"InitCookie";
STDAPI OfflineFolderRegisterServer(); STDAPI OfflineFolderUnregisterServer();
// Count number of objects and number of locks.
ULONG g_cObj=0; ULONG g_cLock=0;
// DLL Instance handle
HINSTANCE g_hInst=0;
// other globals
BOOL g_fIsWinNT; // Are we on WinNT? Always initialized.
BOOL g_fIsWinNT5; // Is it NT5?
BOOL g_fIsMillennium = FALSE;
// logging globals
BOOL g_fCheckedForLog = FALSE; // have we checked registry?
TCHAR * g_pszLoggingFile = NULL; // file to write log to
TCHAR szInternetSettings[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"); TCHAR szProxyEnable[] = TEXT("ProxyEnable"); const TCHAR c_szRegKey[] = WEBCHECK_REGKEY; const TCHAR c_szRegKeyUsernames[] = WEBCHECK_REGKEY TEXT("\\UserFormFieldNames"); const TCHAR c_szRegKeyPasswords[] = WEBCHECK_REGKEY TEXT("\\PasswordFormFieldNames"); const TCHAR c_szRegKeyStore[] = WEBCHECK_REGKEY_STORE;
// Pstore related variables.
static PST_PROVIDERID s_provID = GUID_NULL;
// {14D96C20-255B-11d1-898F-00C04FB6BFC4}
static const GUID GUID_PStoreType = { 0x14d96c20, 0x255b, 0x11d1, { 0x89, 0x8f, 0x0, 0xc0, 0x4f, 0xb6, 0xbf, 0xc4 } };
static PST_KEY s_Key = PST_KEY_CURRENT_USER; static WCHAR c_szInfoDel[] = L"InfoDelivery"; static WCHAR c_szSubscriptions[] = L"Subscriptions";
//////////////////////////////////////////////////////////////////////////
//
// DLL entry point
//
//////////////////////////////////////////////////////////////////////////
EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) {
switch (ulReason) { case DLL_PROCESS_ATTACH: { SHFusionInitializeFromModule((HMODULE)hInstance); OSVERSIONINFOA vi;
DisableThreadLibraryCalls(hInstance); g_hInst = hInstance;
MLLoadResources(g_hInst, TEXT("webchklc.dll"));
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); GetVersionExA(&vi); if(vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { g_fIsWinNT = TRUE; if(vi.dwMajorVersion > 4) g_fIsWinNT5 = TRUE; else g_fIsWinNT5 = FALSE; } else { g_fIsWinNT = FALSE; g_fIsWinNT5 = FALSE;
g_fIsMillennium = IsOS(OS_MILLENNIUM); }
#ifdef DEBUG
g_qwTraceFlags = TF_NEVER; // Default if not overridden from INI
CcshellGetDebugFlags(); #endif
} break;
case DLL_PROCESS_DETACH: { MLFreeResources(g_hInst); SHFusionUninitialize(); } break; }
return TRUE; }
//////////////////////////////////////////////////////////////////////////
//
// Standard OLE entry points
//
//////////////////////////////////////////////////////////////////////////
// Class factory -
// For classes with no special needs these macros should take care of it.
// If your class needs some special stuff just to get the ball rolling,
// implement your own CreateInstance method. (ala, CConnectionAgent)
#define DEFINE_CREATEINSTANCE(cls, iface) \
HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \ { \ ASSERT(NULL == punkOuter); \ ASSERT(NULL != ppunk); \ *ppunk = (iface *)new cls; \ return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \ }
#define DEFINE_AGGREGATED_CREATEINSTANCE(cls, iface) \
HRESULT cls##_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk) \ { \ ASSERT(NULL != punkOuter); \ ASSERT(NULL != ppunk); \ *ppunk = (iface *)new cls(punkOuter); \ return (NULL != *ppunk) ? S_OK : E_OUTOFMEMORY; \ }
DEFINE_CREATEINSTANCE(CWebCheck, IOleCommandTarget) DEFINE_CREATEINSTANCE(CWebCrawler, ISubscriptionAgentControl) DEFINE_CREATEINSTANCE(CChannelAgent, ISubscriptionAgentControl) DEFINE_CREATEINSTANCE(COfflineFolder, IShellFolder) // extern HRESULT CConnectionAgent_CreateInstance(LPUNKNOWN pUnkOuter, IUnknown **ppunk);
DEFINE_CREATEINSTANCE(CSubscriptionMgr, ISubscriptionMgr2); DEFINE_CREATEINSTANCE(CWCPostAgent, ISubscriptionAgentControl) DEFINE_CREATEINSTANCE(CCDLAgent, ISubscriptionAgentControl) DEFINE_CREATEINSTANCE(COfflineSync, ISyncMgrSynchronize)
const CFactoryData g_FactoryData[] = { { &CLSID_WebCheck, CWebCheck_CreateInstance, 0 } ,{ &CLSID_WebCrawlerAgent, CWebCrawler_CreateInstance, 0 } ,{ &CLSID_ChannelAgent, CChannelAgent_CreateInstance, 0 } ,{ &CLSID_OfflineFolder, COfflineFolder_CreateInstance, 0 } // ,{ &CLSID_ConnectionAgent, CConnectionAgent_CreateInstance, 0 }
,{ &CLSID_SubscriptionMgr, CSubscriptionMgr_CreateInstance, 0 } ,{ &CLSID_PostAgent, CWCPostAgent_CreateInstance, 0 } ,{ &CLSID_CDLAgent, CCDLAgent_CreateInstance, 0 } ,{ &CLSID_WebCheckOfflineSync, COfflineSync_CreateInstance, 0 } };
HRESULT APIENTRY DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { HRESULT hr = S_OK; IUnknown *punk = NULL;
*ppv = NULL; // Validate request
for (int i = 0; i < ARRAYSIZE(g_FactoryData); i++) { if (rclsid == *g_FactoryData[i].m_pClsid) { punk = new CClassFactory(&g_FactoryData[i]); break; } }
if (ARRAYSIZE(g_FactoryData) <= i) { ASSERT(NULL == punk); hr = CLASS_E_CLASSNOTAVAILABLE; } else if (NULL == punk) { hr = E_OUTOFMEMORY; } else { hr = punk->QueryInterface(riid, ppv); punk->Release(); }
ASSERT((SUCCEEDED(hr) && (NULL != *ppv)) || (FAILED(hr) && (NULL == *ppv)));
return hr; }
STDAPI DllCanUnloadNow(void) { // check objects and locks
return (0L == DllGetRef() && 0L == DllGetLock()) ? S_OK : S_FALSE; }
//////////////////////////////////////////////////////////////////////////
//
// helper functions
//
//////////////////////////////////////////////////////////////////////////
int MyOleStrToStrN(LPTSTR psz, int cchMultiByte, LPCOLESTR pwsz) { int i; #ifdef UNICODE
StrCpyN(psz, pwsz, cchMultiByte); i = cchMultiByte; #else
i=WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, cchMultiByte, NULL, NULL);
if (!i) { DBG_WARN("MyOleStrToStrN string too long; truncated"); psz[cchMultiByte - 1]=0; } #ifdef DEBUG
else ZeroMemory(psz+i, sizeof(TCHAR)*(cchMultiByte-i)); #endif
#endif
return i; }
int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCTSTR psz) { int i;
#ifdef UNICODE
StrCpyN(pwsz, psz, cchWideChar); i = cchWideChar; #else
i=MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchWideChar); if (!i) { DBG_WARN("MyStrToOleStrN string too long; truncated"); pwsz[cchWideChar-1]=0; } #ifdef DEBUG
else ZeroMemory(pwsz+i, sizeof(OLECHAR)*(cchWideChar-i)); #endif
#endif
return i; }
// Convert upper to lower for ASCII wide characters
inline WCHAR MyToLower(WCHAR wch) { return (wch >= 'A' && wch <= 'Z') ? (wch - 'A'+ 'a') : wch; }
// Optimized for the knowledge that urls are 7-bit characters.
int MyAsciiCmpNIW(LPCWSTR pwsz1, LPCWSTR pwsz2, int iLen) { while (iLen-- && *pwsz1 && *pwsz2) { ASSERT(*pwsz1 || *pwsz2);
if (MyToLower(*pwsz1++) != MyToLower(*pwsz2++)) return 1; }
return 0; }
int MyAsciiCmpW(LPCWSTR pwsz1, LPCWSTR pwsz2) { while (*pwsz1) { if (*pwsz1++ != *pwsz2++) { return 1; } }
if (*pwsz2) return 1;
return 0; }
#ifdef DEBUG
void DumpIID(LPCSTR psz, REFIID riid) { // Convert the GUID to an ANSI string
TCHAR pszGUID[GUIDSTR_MAX]; WCHAR pwszGUID[GUIDSTR_MAX]; int len = StringFromGUID2(riid, pwszGUID, ARRAYSIZE(pwszGUID)); ASSERT(GUIDSTR_MAX == len); ASSERT(0 == pwszGUID[GUIDSTR_MAX - 1]); len = MyOleStrToStrN(pszGUID, GUIDSTR_MAX, pwszGUID); ASSERT(GUIDSTR_MAX == len); ASSERT(0 == pszGUID[GUIDSTR_MAX - 1]);
// See if the IID has a string in the registry
TCHAR pszKey[MAX_PATH]; TCHAR pszIIDName[MAX_PATH]; wnsprintf(pszKey, ARRAYSIZE(pszKey), TEXT("Interface\\%s"), pszGUID); BOOL fRet; fRet = ReadRegValue(HKEY_CLASSES_ROOT, pszKey, NULL, pszIIDName, sizeof(pszIIDName));
// Print all the strings
if (fRet) TraceMsg(TF_THISMODULE, "%s - %s %s", psz, pszIIDName, pszGUID); else TraceMsg(TF_THISMODULE, "%s - %s", psz, pszGUID); } #endif // DEBUG
//////////////////////////////////////////////////////////////////////////
//
// Autoregistration entry points
//
//////////////////////////////////////////////////////////////////////////
HRESULT CallRegInstall(LPSTR szSection) { HRESULT hr = E_FAIL; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
if (hinstAdvPack) { REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, achREGINSTALL);
if (pfnri) { hr = pfnri(g_hInst, szSection, NULL); }
FreeLibrary(hinstAdvPack); }
return hr; }
STDAPI DllRegisterServer(void) { // Delete any old registration entries, then add the new ones.
// Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); // CallRegInstall("UnReg");
CallRegInstall("Reg"); if (hinstAdvPack) { FreeLibrary(hinstAdvPack); }
// OfflineFolder registers.
OfflineFolderRegisterServer();
// do external setup stuff on non-NT5 platforms
if(FALSE == g_fIsWinNT5) { // register LCE
HINSTANCE hLCE = LoadLibrary(TEXT("estier2.dll")); if (hLCE) { LCEREGISTER regfunc; regfunc = (LCEREGISTER)GetProcAddress(hLCE, "LCERegisterServer"); if (regfunc) if (FAILED(regfunc(NULL))) DBG_WARN("LCE register server failed!");
FreeLibrary(hLCE); }
// create reg key that SENS needs
DWORD dwValue = 0; WriteRegValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Mobile\\Sens"), TEXT("Configured"), &dwValue, sizeof(DWORD), REG_DWORD);
// if we're on NT4, call SENS configuration api
if (g_fIsWinNT) { HINSTANCE hSENS = LoadLibrary(TEXT("senscfg.dll"));
if(hSENS) { SENSREGISTER regfunc; regfunc = (SENSREGISTER)GetProcAddress(hSENS, "SensRegister"); if(regfunc) if (FAILED(regfunc())) DBG_WARN("SENS register server failed!");
FreeLibrary(hSENS); } } }
return NOERROR; }
STDAPI DllUnregisterServer(void) { HRESULT hr;
hr = OfflineFolderUnregisterServer(); hr = CallRegInstall("UnReg");
// do external unregister stuff on non-NT5 platforms
if(FALSE == g_fIsWinNT5) {
// unregister SENS on NT4
if(g_fIsWinNT){ HINSTANCE hSENS = LoadLibrary(TEXT("senscfg.dll")); if(hSENS) { SENSREGISTER regfunc; regfunc = (SENSREGISTER)GetProcAddress(hSENS, "SensUnregister"); if(regfunc) regfunc(); FreeLibrary(hSENS); } }
// unregister LCE
HINSTANCE hLCE = LoadLibrary(TEXT("estier2.dll")); if(hLCE) { LCEUNREGISTER unregfunc; unregfunc = (LCEUNREGISTER)GetProcAddress(hLCE, "LCEUnregisterServer"); if(unregfunc) unregfunc(NULL); FreeLibrary(hLCE); }
// Remove Sens key
SHDeleteKey( HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Mobile\\Sens") ); }
return hr; }
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { HRESULT hr = S_OK; typedef enum { InstallNone, InstallPolicies, InstallPerUser } InstallType; InstallType installType = InstallNone; if (pszCmdLine && *pszCmdLine) { //
// Setup will call DllInstall by running 'regsvr32 /n /i:Policy webcheck.dll'.
// This tells webcheck to process the Infodelivery Admin Policies.
//
if (0 == StrCmpIW(pszCmdLine, TEXTW("policy"))) { installType = InstallPolicies; } else if (0 == StrCmpIW(pszCmdLine, TEXTW("U"))) { installType = InstallPerUser; } }
if (bInstall && (installType != InstallNone)) { hr = CoInitialize(NULL);
if (SUCCEEDED(hr)) { switch (installType) { case InstallPolicies: hr = ProcessInfodeliveryPolicies(); break;
case InstallPerUser: hr = ConvertIE4Subscriptions(); DBGASSERT(SUCCEEDED(hr), "webcheck DllInstall - Failed to convert notification manager subscriptions"); break; } }
CoUninitialize(); }
return SUCCEEDED(hr) ? S_OK : hr; }
//////////////////////////////////////////////////////////////////////////
//
// Helper functions for Subscription Store
//
//////////////////////////////////////////////////////////////////////////
// Can return S_OK with NULL bstr
HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet) { ASSERT(pItem && bstrRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_BSTR)) { *bstrRet = Val.bstrVal; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
*bstrRet = NULL; return E_INVALIDARG; } }
// Cannot return S_OK with emptry string
HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet) { HRESULT hr; BSTR bstrRet = NULL; *ppszRet = NULL; hr = ReadBSTR(pItem, szName, &bstrRet); if (SUCCEEDED(hr) && bstrRet && bstrRet[0]) { int len = (lstrlenW(bstrRet) + 1) * sizeof(WCHAR); *ppszRet = (LPWSTR) CoTaskMemAlloc(len); if (*ppszRet) { CopyMemory(*ppszRet, bstrRet, len); } } SAFEFREEBSTR(bstrRet); if (*ppszRet) return S_OK; else return E_FAIL; }
HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet) { HRESULT hr; BSTR bstrRet = NULL; *ppszRet = NULL; hr = ReadBSTR(pItem, szName, &bstrRet); if (SUCCEEDED(hr) && bstrRet && bstrRet[0]) { // Don't forget to allocate a long string for DBCS.
int len = (lstrlenW(bstrRet) + 1) * sizeof(CHAR) * 2; *ppszRet = (LPSTR) MemAlloc(LMEM_FIXED, len); if (*ppszRet) { SHUnicodeToAnsi(bstrRet, *ppszRet, len); } } SAFEFREEBSTR(bstrRet); if (*ppszRet) return S_OK; else return E_FAIL; }
HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet) { ASSERT(pItem && pBoolRet);
VARIANT Val; Val.vt = VT_EMPTY;
// accept VT_I4 or VT_BOOL
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_BOOL || Val.vt==VT_I4)) { if (Val.vt==VT_I4) { if (Val.lVal) *pBoolRet = VARIANT_TRUE; else *pBoolRet = VARIANT_FALSE; } else *pBoolRet = Val.boolVal; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet) { ASSERT(pItem && pscRet);
VARIANT Val;
Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && Val.vt == VT_ERROR) { *pscRet = Val.scode; return S_OK; } else { VariantClear(&Val); return E_INVALIDARG; } }
HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName) { ASSERT(pItem);
VARIANT Val;
Val.vt = VT_EMPTY; return pItem->WriteProperties(1, &szName, &Val); }
HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal) { ASSERT(pItem);
VARIANT Val;
Val.vt = VT_ERROR; Val.scode = scVal;
return pItem->WriteProperties(1, &szName, &Val); } HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet) { ASSERT(pItem && pdwRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_I4 || Val.vt==VT_I2)) { if (Val.vt==VT_I4) *pdwRet = (DWORD) Val.lVal; else *pdwRet = (DWORD) Val.iVal;
return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet) { ASSERT(pItem && pllRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_CY)) { *pllRet = *((LONGLONG *) &(Val.cyVal));
return S_OK; } else { *pllRet = 0; VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } } HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid) { ASSERT(pItem && pGuid);
BSTR bstrGUID = NULL; HRESULT hr = E_INVALIDARG; if (SUCCEEDED(ReadBSTR(pItem, szName, &bstrGUID)) && SUCCEEDED(CLSIDFromString(bstrGUID, pGuid))) { hr = NOERROR; } SAFEFREEBSTR(bstrGUID);
return hr; }
HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid) { ASSERT(pItem && pGuid); WCHAR wszCookie[GUIDSTR_MAX];
#ifdef DEBUG
int len = #endif
StringFromGUID2(*pGuid, wszCookie, ARRAYSIZE(wszCookie)); ASSERT(GUIDSTR_MAX == len); return WriteOLESTR(pItem, szName, wszCookie); }
HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal) { VARIANT Val;
Val.vt = VT_CY; Val.cyVal = *((CY *) &llVal);
return pItem->WriteProperties(1, &szName, &Val); }
HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal) { VARIANT Val;
Val.vt = VT_I4; Val.lVal = dwVal;
return pItem->WriteProperties(1, &szName, &Val); }
HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal) { ASSERT(pItem && dtVal);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_DATE)) { *dtVal = Val.date; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal) { VARIANT Val;
Val.vt = VT_DATE; Val.date= *dtVal;
return pItem->WriteProperties(1, &szName, &Val); }
HRESULT ReadVariant (ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet) { ASSERT(pvarRet->vt == VT_EMPTY); return pItem->ReadProperties(1, &szName, pvarRet); }
HRESULT WriteVariant (ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal) { return pItem->WriteProperties(1, &szName, pvarVal); }
HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal) { VARIANT Val;
Val.vt = VT_BSTR; Val.bstrVal = SysAllocString(szVal);
HRESULT hr = pItem->WriteProperties(1, &szName, &Val);
SysFreeString(Val.bstrVal);
return hr; }
HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal) { VARIANT Val; BSTR bstrVal; HRESULT hr;
bstrVal = SysAllocStringByteLen(szVal, lstrlenA(szVal)); if (bstrVal) { Val.vt = VT_BSTR; Val.bstrVal = bstrVal;
hr = pItem->WriteProperties(1, &szName, &Val);
SysFreeString(bstrVal); } else { hr = E_OUTOFMEMORY; }
return hr; }
HRESULT WriteResSTR(ISubscriptionItem *pItem, LPCWSTR szName, UINT uID) { TCHAR szString[MAX_RES_STRING_LEN];
if (MLLoadString(uID, szString, ARRAYSIZE(szString))) { return WriteTSTR(pItem, szName, szString); }
return E_INVALIDARG; }
DWORD LogEvent(LPTSTR pszFormat, ...) {
// check registry if necessary
if(FALSE == g_fCheckedForLog) {
TCHAR pszFilePath[MAX_PATH];
if(ReadRegValue(HKEY_CURRENT_USER, c_szRegKey, TEXT("LoggingFile"), pszFilePath, sizeof(pszFilePath))) {
g_pszLoggingFile = new TCHAR[lstrlen(pszFilePath) + 1]; if(g_pszLoggingFile) { StrCpy(g_pszLoggingFile, pszFilePath); } }
g_fCheckedForLog = TRUE; }
if(g_pszLoggingFile) {
TCHAR pszString[MAX_PATH+INTERNET_MAX_URL_LENGTH]; SYSTEMTIME st; HANDLE hLog; DWORD dwWritten; va_list va;
hLog = CreateFile(g_pszLoggingFile, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(INVALID_HANDLE_VALUE == hLog) return GetLastError();
// seek to end of file
SetFilePointer(hLog, 0, 0, FILE_END);
// dump time
GetLocalTime(&st); wnsprintf(pszString, ARRAYSIZE(pszString), TEXT("\r\n%02d:%02d:%02d - "), st.wHour, st.wMinute, st.wSecond); WriteFile(hLog, pszString, lstrlen(pszString), &dwWritten, NULL);
// dump passed in string
va_start(va, pszFormat); wvnsprintf(pszString, ARRAYSIZE(pszString), pszFormat, va); va_end(va); WriteFile(hLog, pszString, lstrlen(pszString), &dwWritten, NULL);
// clean up
CloseHandle(hLog); }
return 0; }
// Functions related to saving and restoring user passwords from the pstore.
// We have wrappers around Create and Release to allow for future caching of the pstore
// instance within webcheck.
STDAPI CreatePStore(IPStore **ppIPStore) { HRESULT hr;
hr = PStoreCreateInstance ( ppIPStore, IsEqualGUID(s_provID, GUID_NULL) ? NULL : &s_provID, NULL, 0); return hr; }
STDAPI ReleasePStore(IPStore *pIPStore) { HRESULT hr;
if (pIPStore) { pIPStore->Release(); hr = S_OK; } else { hr = E_POINTER; }
return hr; }
// Given a field name this figures out the type and sub-type in the pstore
// that should be queried. Currently these are hard-coded.
STDAPI GetPStoreTypes(LPCWSTR /* wszField */, GUID * pguidType, GUID * pguidSubType) { *pguidType = GUID_PStoreType; *pguidSubType = GUID_NULL;
return S_OK; }
STDAPI ReadNotificationPassword(LPCWSTR wszUrl, BSTR *pbstrPassword) { GUID itemType = GUID_NULL; GUID itemSubtype = GUID_NULL; PST_PROMPTINFO promptInfo = {0}; IPStore* pStore = NULL; HRESULT hr ; if (wszUrl == NULL || pbstrPassword == NULL) return E_POINTER;
// Will return NULL if there is no password entry or we
// fail for some reason.
*pbstrPassword = NULL;
promptInfo.cbSize = sizeof(promptInfo); promptInfo.szPrompt = NULL; promptInfo.dwPromptFlags = 0; promptInfo.hwndApp = NULL; hr = CreatePStore(&pStore);
if (SUCCEEDED(hr)) { ASSERT(pStore != NULL); hr = GetPStoreTypes(wszUrl, &itemType, &itemSubtype);
if (SUCCEEDED(hr)) { DWORD cbData; BYTE * pbData = NULL;
hr = pStore->ReadItem( s_Key, &itemType, &itemSubtype, wszUrl, &cbData, &pbData, &promptInfo, 0);
if (SUCCEEDED(hr)) { *pbstrPassword = SysAllocString((OLECHAR *)pbData); CoTaskMemFree(pbData); hr = S_OK; } }
ReleasePStore(pStore); }
return hr; }
STDAPI WriteNotificationPassword(LPCWSTR wszUrl, BSTR bstrPassword) { HRESULT hr; PST_TYPEINFO typeInfo; PST_PROMPTINFO promptInfo; IPStore * pStore;
if (wszUrl == NULL) return E_POINTER;
typeInfo.cbSize = sizeof(typeInfo);
typeInfo.szDisplayName = c_szInfoDel;
promptInfo.cbSize = sizeof(promptInfo); promptInfo.dwPromptFlags = 0; promptInfo.hwndApp = NULL; promptInfo.szPrompt = NULL;
hr = CreatePStore(&pStore);
if (SUCCEEDED(hr)) { GUID itemType = GUID_NULL; GUID itemSubtype = GUID_NULL;
ASSERT(pStore != NULL);
hr = GetPStoreTypes(wszUrl, &itemType, &itemSubtype); if (SUCCEEDED(hr)) { hr = pStore->CreateType(s_Key, &itemType, &typeInfo, 0);
// PST_E_TYPE_EXISTS implies type already exists which is just fine
// by us.
if (SUCCEEDED(hr) || hr == PST_E_TYPE_EXISTS) { typeInfo.szDisplayName = c_szSubscriptions;
hr = pStore->CreateSubtype( s_Key, &itemType, &itemSubtype, &typeInfo, NULL, 0);
if (SUCCEEDED(hr) || hr == PST_E_TYPE_EXISTS) { if (bstrPassword != NULL) { hr = pStore->WriteItem( s_Key, &itemType, &itemSubtype, wszUrl, ((lstrlenW(bstrPassword)+1) * sizeof(WCHAR)), (BYTE *)bstrPassword, &promptInfo, PST_CF_NONE, 0); } else { hr = pStore->DeleteItem( s_Key, &itemType, &itemSubtype, wszUrl, &promptInfo, 0); } } } } ReleasePStore(pStore); } return hr; }
HRESULT WritePassword(ISubscriptionItem *pItem, BSTR bstrPassword) { BSTR bstrURL = NULL; HRESULT hr = E_FAIL;
hr = ReadBSTR(pItem, c_szPropURL, &bstrURL); RETURN_ON_FAILURE(hr);
hr = WriteNotificationPassword(bstrURL, bstrPassword); SAFEFREEBSTR(bstrURL); return hr; }
HRESULT ReadPassword(ISubscriptionItem *pItem, BSTR * pBstrPassword) { BSTR bstrURL = NULL; HRESULT hr = E_FAIL;
hr = ReadBSTR(pItem, c_szPropURL, &bstrURL); RETURN_ON_FAILURE(hr);
ASSERT(pBstrPassword); hr = ReadNotificationPassword(bstrURL, pBstrPassword); SAFEFREEBSTR(bstrURL); return hr; }
|