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.
 
 
 
 
 
 

2604 lines
73 KiB

#include "private.h"
#include "offl_cpp.h"
#include "subsmgrp.h"
#include "helper.h"
#include <mluisupp.h>
#ifdef DEBUG
void DumpTaskTrigger(TASK_TRIGGER * pTaskTrigger);
#endif // DEBUG
// {D994B6F0-DA3C-11d1-857D-00C04FA35C89}
const GUID NOOP_SCHEDULE_COOKIE =
{ 0xd994b6f0, 0xda3c, 0x11d1, { 0x85, 0x7d, 0x0, 0xc0, 0x4f, 0xa3, 0x5c, 0x89
} };
#ifndef TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
#define TASK_FLAG_RUN_ONLY_IF_LOGGED_ON (0x2000)
#endif
const PROPSPEC c_rgPropRead[] = {
{ PRSPEC_PROPID, PID_INTSITE_SUBSCRIPTION},
{ PRSPEC_PROPID, PID_INTSITE_FLAGS},
{ PRSPEC_PROPID, PID_INTSITE_TRACKING},
{ PRSPEC_PROPID, PID_INTSITE_CODEPAGE},
};
void UpdateTimeFormat(LPTSTR tszTimeFormat, ULONG cchTimeFormat);
HRESULT WriteProperties(POOEntry pooe);
HRESULT ReadProperties(POOEBuf pBuf);
const TCHAR c_szLoadWC[] = TEXT("LoadWC");
void FixupRandomTrigger(TASK_TRIGGER *pTrigger)
{
if (pTrigger->wRandomMinutesInterval > 0)
{
// We have a random interval so we need to add a random number of minutes to it.
// Given the fact that all of the fields need to carry over to the next, the
// simplest way to do this is to flatten the start time into FILETIME, add the
// random minutes, and then convert back to a TASK_TRIGGER. This let's us use
// Win32 APIs instead of doing all of the calendar and carry over stuff ourselves.
SYSTEMTIME st;
CFileTime ft;
memset(&st, 0, sizeof(SYSTEMTIME));
st.wYear = pTrigger->wBeginYear;
st.wMonth = pTrigger->wBeginMonth;
st.wDay = pTrigger->wBeginDay;
st.wHour = pTrigger->wStartHour;
st.wMinute = pTrigger->wStartMinute;
SystemTimeToFileTime(&st, &ft);
ft += ONE_MINUTE_IN_FILETIME * (__int64)Random(pTrigger->wRandomMinutesInterval);
FileTimeToSystemTime(&ft, &st);
pTrigger->wBeginYear = st.wYear;
pTrigger->wBeginMonth = st.wMonth;
pTrigger->wBeginDay = st.wDay;
pTrigger->wStartHour = st.wHour;
pTrigger->wStartMinute = st.wMinute;
pTrigger->wRandomMinutesInterval = 0;
}
}
// Come up with a name like "MSN Recommended Schedule"
void CreatePublisherScheduleNameW(WCHAR *pwszSchedName, int cchSchedName,
const TCHAR *pszName, const WCHAR *pwszName)
{
WCHAR wszFormat[MAX_PATH];
WCHAR wszPubName[MAX_PATH];
const WCHAR *pwszPubName;
ASSERT((NULL != pszName) || (NULL != pwszName));
ASSERT((NULL != pwszSchedName) && (cchSchedName > 0));
if (NULL == pwszName)
{
ASSERT(NULL != pszName);
MyStrToOleStrN(wszPubName, ARRAYSIZE(wszPubName), pszName);
pwszPubName = wszPubName;
}
else
{
pwszPubName = pwszName;
}
#ifdef UNICODE
MLLoadStringW(IDS_RECOMMENDED_SCHEDULE_FORMAT, wszFormat, ARRAYSIZE(wszFormat));
#else
CHAR szFormat[MAX_PATH];
MLLoadStringA(IDS_RECOMMENDED_SCHEDULE_FORMAT, szFormat, ARRAYSIZE(szFormat));
MultiByteToWideChar(CP_ACP, 0, szFormat, -1, wszFormat, ARRAYSIZE(wszFormat));
#endif
wnsprintfW(pwszSchedName, cchSchedName, wszFormat, pwszPubName);
}
void CreatePublisherScheduleName(TCHAR *pszSchedName, int cchSchedName,
const TCHAR *pszName, const WCHAR *pwszName)
{
WCHAR wszSchedName[MAX_PATH];
CreatePublisherScheduleNameW(wszSchedName, ARRAYSIZE(wszSchedName),
pszName, pwszName);
MyOleStrToStrN(pszSchedName, cchSchedName, wszSchedName);
}
HICON LoadItemIcon(ISubscriptionItem *psi, BOOL bLarge)
{
HICON hIcon = NULL;
SUBSCRIPTIONITEMINFO sii;
SUBSCRIPTIONCOOKIE cookie;
HRESULT hr;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
psi->GetCookie(&cookie);
hr = psi->GetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr))
{
ISubscriptionAgentShellExt *pSubscriptionAgentShellExt;
hr = CoCreateInstance(sii.clsidAgent, NULL, CLSCTX_INPROC_SERVER,
IID_ISubscriptionAgentShellExt,
(void **)&pSubscriptionAgentShellExt);
if (SUCCEEDED(hr))
{
hr = pSubscriptionAgentShellExt->Initialize(&cookie, L"", L"", (SUBSCRIPTIONTYPE)-1);
if (SUCCEEDED(hr))
{
IExtractIcon *pExtractIcon;
hr = pSubscriptionAgentShellExt->QueryInterface(IID_IExtractIcon,
(void **)&pExtractIcon);
if (SUCCEEDED(hr))
{
TCHAR szIconFile[INTERNET_MAX_URL_LENGTH];
int iIndex;
UINT wFlags;
HICON hIconScrap = NULL;
HICON *phIconLarge = bLarge ? &hIcon : &hIconScrap;
HICON *phIconSmall = bLarge ? &hIconScrap : &hIcon;
hr = pExtractIcon->GetIconLocation(0, szIconFile, ARRAYSIZE(szIconFile), &iIndex, &wFlags);
if (SUCCEEDED(hr))
{
hr = pExtractIcon->Extract(szIconFile, iIndex, phIconLarge, phIconSmall,
MAKELONG(GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CXSMICON)));
if (S_FALSE == hr)
{
hIcon = ExtractIcon(g_hInst, szIconFile, iIndex);
if (NULL == hIcon)
{
hr = E_FAIL;
}
}
else if ((NULL != hIconScrap) && (hIcon != hIconScrap))
{
DestroyIcon(hIconScrap);
}
}
pExtractIcon->Release();
}
}
pSubscriptionAgentShellExt->Release();
}
}
if (FAILED(hr))
{
DWORD dwChannel = 0;
DWORD dwDesktop = 0;
int iSize = bLarge ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXSMICON);
int id;
HINSTANCE hinstSrc;
ReadDWORD(psi, c_szPropChannel, &dwChannel);
ReadDWORD(psi, c_szPropDesktopComponent, &dwDesktop);
if (dwDesktop == 1)
{
id = IDI_DESKTOPITEM;
hinstSrc = MLGetHinst();
}
else if (dwChannel == 1)
{
id = IDI_CHANNEL;
hinstSrc = g_hInst;
}
else
{
id = IDI_WEBDOC;
hinstSrc = g_hInst;
}
hIcon = (HICON)LoadImage(hinstSrc, MAKEINTRESOURCE(id), IMAGE_ICON,
iSize, iSize, LR_DEFAULTCOLOR);
}
return hIcon;
}
BOOL ScheduleCookieExists(SYNCSCHEDULECOOKIE *pSchedCookie)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
ISyncSchedule *pSyncSchedule = NULL;
hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
if (SUCCEEDED(hr))
{
pSyncSchedule->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr == S_OK;
}
BOOL IsScheduleNameInUse(TCHAR *pszSchedName)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
CWaitCursor waitCursor;
ISyncSchedule *pSyncSchedule = NULL;
SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
WCHAR wszSchedName[MAX_PATH];
MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), pszSchedName);
hr = pSyncScheduleMgr->CreateSchedule(wszSchedName, 0,
&schedCookie, &pSyncSchedule);
if (SUCCEEDED(hr))
{
pSyncSchedule->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr == SYNCMGR_E_NAME_IN_USE;
}
struct CONFLICT_DATA
{
TCHAR szSchedName[MAX_PATH];
TCHAR szFriendlyTrigger[MAX_PATH];
};
INT_PTR CALLBACK SchedConflictDlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL bResult = FALSE;
switch (message)
{
case WM_INITDIALOG:
{
TCHAR szConflictFormat[MAX_PATH];
TCHAR szConflictMsg[MAX_PATH * 2];
CONFLICT_DATA *pcd = (CONFLICT_DATA *)lParam;
ASSERT(NULL != pcd);
MLLoadString(IDS_SCHED_CONFLICT_FORMAT,
szConflictFormat, ARRAYSIZE(szConflictFormat));
wnsprintf(szConflictMsg, ARRAYSIZE(szConflictMsg),
szConflictFormat, pcd->szSchedName);
SetDlgItemText(hdlg, IDC_SCHEDULE_MESSAGE, szConflictMsg);
SetDlgItemText(hdlg, IDC_FRIENDLY_SCHEDULE_TEXT, pcd->szFriendlyTrigger);
bResult = TRUE;
break;
}
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
EndDialog(hdlg, LOWORD(wParam));
bResult = TRUE;
}
break;
}
return bResult;
}
BOOL CompareTaskTrigger(TASK_TRIGGER *pTrigA, TASK_TRIGGER *pTrigB)
{
BOOL bDontMatch; // TRUE if any elements don't match
// Simple memcmp won't work since the start date will be different
// when in fact they are effectively the same schedule - at least
// from a user perspective.
// FEATURE - this is far from complete - we only check for values
// which can be set by our wizard.
bDontMatch = pTrigA->wStartHour != pTrigB->wStartHour;
bDontMatch |= pTrigA->wStartMinute != pTrigB->wStartMinute;
bDontMatch |= pTrigA->TriggerType != pTrigB->TriggerType;
bDontMatch |= pTrigA->Type.Daily.DaysInterval != pTrigB->Type.Daily.DaysInterval;
bDontMatch |= pTrigA->MinutesDuration != pTrigB->MinutesDuration;
bDontMatch |= pTrigA->MinutesInterval != pTrigB->MinutesInterval;
bDontMatch |= pTrigA->wRandomMinutesInterval != pTrigB->wRandomMinutesInterval;
return !bDontMatch;
}
// HandleScheduleNameConflict
//
// Return values:
// CONFLICT_NONE - pSchedCookie will be GUID_NULL and the caller is
// free to create a new schedule
// CONFLICT_RESOLVED_USE_NEW - pSchedCookie will be the cookie of an existing
// schedule which the caller should update with
// it's new TASK_TRIGGER
// CONFLICT_RESOLVED_USE_OLD - pSchedCookie will be the cookie of an existing
// schedule which the caller should use without
// modifying anything
// CONFLICT_UNRESOLVED - pSchedCookie will be GUID_NULL and the caller
// shouldn't do anything until the user has made
// up his/her mind
//
int HandleScheduleNameConflict(/* in */ TCHAR *pszSchedName,
/* in */ TASK_TRIGGER *pTrigger,
/* in */ HWND hwndParent,
/* out */ SYNCSCHEDULECOOKIE *pSchedCookie)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
int iResult = CONFLICT_NONE;
*pSchedCookie = GUID_NULL;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
ISyncSchedule *pSyncSchedule = NULL;
SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
WCHAR wszSchedName[MAX_PATH];
MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), pszSchedName);
{
CWaitCursor waitCursor;
hr = pSyncScheduleMgr->CreateSchedule(wszSchedName, 0,
&schedCookie, &pSyncSchedule);
}
if (SUCCEEDED(hr))
{
pSyncSchedule->Release();
}
else if (SYNCMGR_E_NAME_IN_USE == hr)
{
// schedCookie will have the cookie of the conflicting schedule
hr = pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule);
if (SUCCEEDED(hr))
{
ITaskTrigger *pITaskTrigger;
hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
if (SUCCEEDED(hr))
{
TASK_TRIGGER existTrigger = { sizeof(TASK_TRIGGER) };
hr = pITaskTrigger->GetTrigger(&existTrigger);
if (SUCCEEDED(hr))
{
if (!CompareTaskTrigger(&existTrigger, pTrigger))
{
CONFLICT_DATA cd;
LPWSTR pwszFriendlyTrigger;
StrCpyN(cd.szSchedName, pszSchedName, ARRAYSIZE(cd.szSchedName));
if (SUCCEEDED(pITaskTrigger->GetTriggerString(&pwszFriendlyTrigger)))
{
MyOleStrToStrN(cd.szFriendlyTrigger,
ARRAYSIZE(cd.szFriendlyTrigger),
pwszFriendlyTrigger);
CoTaskMemFree(pwszFriendlyTrigger);
}
else
{
cd.szFriendlyTrigger[0] = TEXT('\0');
}
INT_PTR iRet = DialogBoxParam(MLGetHinst(),
MAKEINTRESOURCE(IDD_DUPLICATE_SCHEDULE),
hwndParent,
SchedConflictDlgProc,
(LPARAM)&cd);
switch (iRet)
{
case IDC_NEW_SETTINGS:
iResult = CONFLICT_RESOLVED_USE_NEW;
*pSchedCookie = schedCookie;
break;
case IDC_OLD_SETTINGS:
iResult = CONFLICT_RESOLVED_USE_OLD;
*pSchedCookie = schedCookie;
break;
default:
iResult = CONFLICT_UNRESOLVED;
break;
}
}
}
pITaskTrigger->Release();
}
pSyncSchedule->Release();
}
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return iResult;
}
HRESULT UpdateScheduleTrigger(SYNCSCHEDULECOOKIE *pSchedCookie, TASK_TRIGGER *pTrigger)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
CWaitCursor waitCursor;
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
ISyncSchedule *pSyncSchedule;
hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
if (SUCCEEDED(hr))
{
ITaskTrigger *pITaskTrigger;
hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
if (SUCCEEDED(hr))
{
FixupRandomTrigger(pTrigger);
hr = pITaskTrigger->SetTrigger(pTrigger);
if (SUCCEEDED(hr))
{
hr = pSyncSchedule->Save();
}
pITaskTrigger->Release();
}
pSyncSchedule->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
HRESULT RemoveItemFromAllSchedules(SUBSCRIPTIONCOOKIE *pCookie)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
CWaitCursor waitCursor;
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
IEnumSyncSchedules *pEnumSyncSchedules;
hr = pSyncScheduleMgr->EnumSyncSchedules(&pEnumSyncSchedules);
if (SUCCEEDED(hr))
{
SYNCSCHEDULECOOKIE schedCookie;
ULONG ulFetched;
while (S_OK == pEnumSyncSchedules->Next(1, &schedCookie, &ulFetched) &&
(0 != ulFetched)) // this shouldn't be necessary
{
ISyncSchedule *pSyncSchedule;
// If this fails, there ain't much we can do about
// it so just plod along anyhow
if (SUCCEEDED(pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule)))
{
// Don't care about the return value, it's cheaper
// for us to just delete than to ask if it's there
// and then delete.
pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
pCookie,
SYNCMGRITEMSTATE_UNCHECKED);
pSyncSchedule->Save();
pSyncSchedule->Release();
}
}
pEnumSyncSchedules->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
HRESULT AddRemoveScheduledItem(SYNC_HANDLER_ITEM_INFO *pSyncHandlerItemInfo, // For Add
SUBSCRIPTIONCOOKIE *pCookie, // For Remove
SYNCSCHEDULECOOKIE *pSchedCookie, BOOL bAdd)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
ASSERT((bAdd && (NULL != pSyncHandlerItemInfo)) ||
(!bAdd && (NULL != pCookie)));
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
ISyncSchedule *pSyncSchedule;
hr = pSyncScheduleMgr->OpenSchedule(pSchedCookie, 0, &pSyncSchedule);
if (SUCCEEDED(hr))
{
if (bAdd)
{
hr = pSyncSchedule->AddItem(pSyncHandlerItemInfo);
hr = pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
&pSyncHandlerItemInfo->itemID,
SYNCMGRITEMSTATE_CHECKED);
}
else
{
hr = pSyncSchedule->SetItemCheck(CLSID_WebCheckOfflineSync,
pCookie,
SYNCMGRITEMSTATE_UNCHECKED);
}
hr = pSyncSchedule->Save();
pSyncSchedule->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
HRESULT SetScheduleValues(ISyncSchedule *pSyncSchedule,
TASK_TRIGGER *pTrigger,
DWORD dwSyncScheduleFlags)
{
HRESULT hr;
ITaskTrigger *pITaskTrigger;
ASSERT(NULL != pSyncSchedule);
ASSERT(NULL != pTrigger);
hr = pSyncSchedule->GetTrigger(&pITaskTrigger);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
FixupRandomTrigger(pTrigger);
hr = pITaskTrigger->SetTrigger(pTrigger);
pITaskTrigger->Release();
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
DWORD dwFlags;
DWORD dwConnectionType = SYNCSCHEDINFO_FLAGS_CONNECTION_LAN;
WCHAR wszConnectionName[MAX_PATH];
// Return code doesn't help us. This returns the best guess
// at connection:
// 1) LAN
// 2) currently connected connectoid
// 3) auto-dial connectoid
// This is according to darrenmi, if this changes - kill him.
InternetGetConnectedStateExW(&dwFlags, wszConnectionName,
ARRAYSIZE(wszConnectionName), 0);
if (dwFlags & INTERNET_CONNECTION_MODEM)
{
dwConnectionType = SYNCSCHEDINFO_FLAGS_CONNECTION_WAN;
}
hr = pSyncSchedule->SetConnection(
(dwConnectionType == SYNCSCHEDINFO_FLAGS_CONNECTION_WAN) ?
wszConnectionName : NULL,
dwConnectionType);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
hr = pSyncSchedule->SetFlags(dwSyncScheduleFlags);
ASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
hr = pSyncSchedule->Save();
ASSERT(SUCCEEDED(hr));
}
}
}
}
return hr;
}
HRESULT CreateSchedule(LPWSTR pwszScheduleName, DWORD dwSyncScheduleFlags,
SYNCSCHEDULECOOKIE *pSchedCookie, TASK_TRIGGER *pTrigger,
BOOL fDupCookieOK)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
ISyncSchedule *pSyncSchedule = NULL;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
CWaitCursor waitCursor;
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
hr = pSyncScheduleMgr->CreateSchedule(pwszScheduleName, 0,
pSchedCookie, &pSyncSchedule);
ASSERT((FAILED(hr) && (NULL == pSyncSchedule)) ||
(SUCCEEDED(hr) && (NULL != pSyncSchedule)));
switch (hr)
{
case S_OK:
hr = SetScheduleValues(pSyncSchedule, pTrigger, dwSyncScheduleFlags);
#ifdef DEBUG
if (FAILED(hr))
{
TraceMsg(TF_ALWAYS, "SetScheduleValues failed - hr=0x%08x", hr);
}
#endif
break;
case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):
if (fDupCookieOK)
{
hr = S_OK;
}
break;
}
SAFERELEASE(pSyncSchedule);
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
BOOL IsCookieOnSchedule(ISyncSchedule *pSyncSchedule, SUBSCRIPTIONCOOKIE *pCookie)
{
HRESULT hr;
DWORD dwCheckState = SYNCMGRITEMSTATE_UNCHECKED;
hr = pSyncSchedule->GetItemCheck(CLSID_WebCheckOfflineSync,
pCookie,
&dwCheckState);
return SUCCEEDED(hr) && (SYNCMGRITEMSTATE_CHECKED & dwCheckState);
}
struct GIS_DATA
{
SUBSCRIPTIONCOOKIE *pSubsCookie;
SYNCSCHEDULECOOKIE *pSchedCookie;
};
BOOL GetItemScheduleCallback(ISyncSchedule *pSyncSchedule,
SYNCSCHEDULECOOKIE *pSchedCookie,
LPARAM lParam)
{
BOOL bContinue = TRUE;
GIS_DATA *pgd = (GIS_DATA *)lParam;
if (IsCookieOnSchedule(pSyncSchedule, pgd->pSubsCookie))
{
*pgd->pSchedCookie = *pSchedCookie;
bContinue = FALSE;
}
return bContinue;
}
HRESULT GetItemSchedule(SUBSCRIPTIONCOOKIE *pSubsCookie, SYNCSCHEDULECOOKIE *pSchedCookie)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
*pSchedCookie = GUID_NULL;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
ISubscriptionItem *psi;
// First let's chech to see if it has a custom schedule
hr = SubscriptionItemFromCookie(FALSE, pSubsCookie, &psi);
if (SUCCEEDED(hr))
{
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
hr = psi->GetSubscriptionItemInfo(&sii);
psi->Release();
if (SUCCEEDED(hr) && (sii.ScheduleGroup != GUID_NULL))
{
*pSchedCookie = sii.ScheduleGroup;
}
else
{
GIS_DATA gd;
gd.pSubsCookie = pSubsCookie;
gd.pSchedCookie = pSchedCookie;
EnumSchedules(GetItemScheduleCallback, (LPARAM)&gd);
}
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
HRESULT EnumSchedules(SCHEDULEENUMCALLBACK pCallback, LPARAM lParam)
{
HRESULT hr;
ISyncScheduleMgr *pSyncScheduleMgr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
CWaitCursor waitCursor;
hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
if (SUCCEEDED(hr))
{
IEnumSyncSchedules *pEnumSyncSchedules;
hr = pSyncScheduleMgr->EnumSyncSchedules(&pEnumSyncSchedules);
if (SUCCEEDED(hr))
{
SYNCSCHEDULECOOKIE schedCookie;
ULONG ulFetched;
while (S_OK == pEnumSyncSchedules->Next(1, &schedCookie, &ulFetched)&&
(0 != ulFetched)) // this shouldn't be necessary
{
ISyncSchedule *pSyncSchedule;
HRESULT hrTemp = pSyncScheduleMgr->OpenSchedule(&schedCookie, 0, &pSyncSchedule);
if (SUCCEEDED(hrTemp) && pSyncSchedule)
{
BOOL bContinue = pCallback(pSyncSchedule, &schedCookie, lParam);
pSyncSchedule->Release();
if (!bContinue)
{
hr = S_FALSE;
break;
}
}
}
pEnumSyncSchedules->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
return hr;
}
SUBSCRIPTIONTYPE GetItemCategory(BOOL bDesktop, const CLSID& clsidDest)
{
SUBSCRIPTIONTYPE st;
if (clsidDest == CLSID_WebCrawlerAgent)
{
st = (!bDesktop) ? SUBSTYPE_URL : SUBSTYPE_DESKTOPURL;
}
else if (clsidDest == CLSID_ChannelAgent)
{
st = (!bDesktop) ? SUBSTYPE_CHANNEL : SUBSTYPE_DESKTOPCHANNEL;
}
else
{
st = SUBSTYPE_EXTERNAL;
}
return st;
}
SUBSCRIPTIONSCHEDULE GetGroup(BOOL bDesktop, const CLSID& clsidDest,
DWORD fChannelFlags, const NOTIFICATIONCOOKIE& groupCookie)
{
SUBSCRIPTIONTYPE category = GetItemCategory(bDesktop, clsidDest);
if (category == SUBSTYPE_CHANNEL || category == SUBSTYPE_DESKTOPCHANNEL) {
if ((fChannelFlags & CHANNEL_AGENT_DYNAMIC_SCHEDULE) &&
(GUID_NULL == groupCookie))
return SUBSSCHED_AUTO;
}
// We have no idea about the AUTO schedule stuff of unknown types.
if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_DAILY)
return SUBSSCHED_DAILY;
else if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY)
return SUBSSCHED_WEEKLY;
else if (groupCookie == NOTFCOOKIE_SCHEDULE_GROUP_MANUAL)
return SUBSSCHED_MANUAL;
else
return SUBSSCHED_CUSTOM;
}
HRESULT LoadGroupCookie(NOTIFICATIONCOOKIE * pCookie, SUBSCRIPTIONSCHEDULE subGroup)
{
if (pCookie) {
switch (subGroup) {
case SUBSSCHED_DAILY:
*pCookie = NOTFCOOKIE_SCHEDULE_GROUP_DAILY;
break;
case SUBSSCHED_WEEKLY:
*pCookie = NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY;
break;
case SUBSSCHED_MANUAL:
*pCookie = NOTFCOOKIE_SCHEDULE_GROUP_MANUAL;
break;
default:
*pCookie = CLSID_NULL;
ASSERT(0);
break;
}
return S_OK;
}
return E_INVALIDARG;
}
/////////////////////////////////////////////////////////////////////
// Subscription helper functions.
HRESULT TSTR2BSTR(VARIANT * pvarBSTR, LPCTSTR srcTSTR)
{
ASSERT(pvarBSTR);
ASSERT(srcTSTR);
BSTR bstrBuf = NULL;
LONG lTSTRLen = 0;
lTSTRLen = lstrlen(srcTSTR) + 1;
bstrBuf = SysAllocStringLen(NULL, lTSTRLen);
if (!bstrBuf)
return E_OUTOFMEMORY;
MyStrToOleStrN(bstrBuf, lTSTRLen, srcTSTR);
pvarBSTR->vt = VT_BSTR;
pvarBSTR->bstrVal = bstrBuf;
return S_OK;
}
HRESULT WriteCookieToInetDB(LPCTSTR pszURL, SUBSCRIPTIONCOOKIE *pCookie, BOOL bRemove)
{
PROPVARIANT propCookie;
LPOLESTR pclsid = NULL; // init to keep compiler happy
ASSERT(pszURL);
if (bRemove)
{
propCookie.vt = VT_EMPTY;
}
else
{
ASSERT(pCookie);
if (FAILED(StringFromCLSID(*pCookie, &pclsid)))
return E_FAIL;
propCookie.vt = VT_LPWSTR;
propCookie.pwszVal = pclsid;
}
HRESULT hr = IntSiteHelper(pszURL, &c_rgPropRead[PROP_SUBSCRIPTION], &propCookie, 1, TRUE);
if (!bRemove)
CoTaskMemFree(pclsid);
return hr;
}
HRESULT WritePropertiesToItem(POOEntry pooe, ISubscriptionItem *psi)
{
HRESULT hr = S_OK;
VARIANT var;
BOOL bHasUNAME = TRUE;
ASSERT(NULL != psi);
VariantInit(&var);
if (pooe->dwFlags & PROP_WEBCRAWL_URL)
{
if (FAILED(TSTR2BSTR(&var, URL(pooe))))
return E_FAIL;
WriteVariant(psi, c_szPropURL, &var);
VariantClear(&var);
}
if (pooe->dwFlags & PROP_WEBCRAWL_NAME)
{
if (FAILED(TSTR2BSTR(&var, NAME(pooe))))
return E_FAIL;
WriteVariant(psi, c_szPropName, &var);
VariantClear(&var);
}
if (pooe->dwFlags & PROP_WEBCRAWL_UNAME)
{
if(*(UNAME(pooe)))
{
if (FAILED(TSTR2BSTR(&var, UNAME(pooe))))
return E_FAIL;
WriteVariant(psi, c_szPropCrawlUsername, &var);
VariantClear(&var);
}
else
{
WriteEMPTY(psi, c_szPropCrawlUsername);
bHasUNAME = FALSE;
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_DESKTOP)
{
if (pooe->bDesktop)
{
WriteDWORD(psi, c_szPropDesktopComponent, 1);
}
else
{
WriteEMPTY(psi, c_szPropDesktopComponent);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_CHANNEL)
{
if (pooe->bChannel)
{
WriteDWORD(psi, c_szPropChannel, 1);
}
else
{
WriteEMPTY(psi, c_szPropChannel);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_GLEAM)
{
if (pooe->bGleam)
{
WriteDWORD(psi, c_szPropEnableShortcutGleam, 1);
}
else
{
WriteEMPTY(psi, c_szPropEnableShortcutGleam);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_CHANGESONLY)
{
if (pooe->bChangesOnly)
{
WriteDWORD(psi, c_szPropCrawlChangesOnly, 1);
}
else
{
WriteEMPTY(psi, c_szPropCrawlChangesOnly);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_CHANNELFLAGS)
{
if (pooe->fChannelFlags)
{
WriteDWORD(psi, c_szPropChannelFlags, pooe->fChannelFlags);
}
else
{
WriteEMPTY(psi, c_szPropChannelFlags);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_EMAILNOTF)
{
if (pooe->bMail)
{
WriteDWORD(psi, c_szPropEmailNotf, 1);
}
else
{
WriteEMPTY(psi, c_szPropEmailNotf);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_PSWD)
{
if (*(PASSWD(pooe)) && bHasUNAME)
{
if (FAILED(TSTR2BSTR(&var, PASSWD(pooe))))
return E_FAIL;
WritePassword(psi, var.bstrVal);
VariantClear(&var);
}
else
{
WritePassword(psi, NULL);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_LEVEL)
{
if(pooe->m_RecurseLevels)
{
WriteDWORD(psi, c_szPropCrawlLevels, pooe->m_RecurseLevels);
}
else
{
// top page only was specified, empty out levels
WriteEMPTY(psi, c_szPropCrawlLevels);
}
}
if (pooe->dwFlags & PROP_WEBCRAWL_FLAGS)
{
WriteDWORD(psi, c_szPropCrawlFlags, pooe->m_RecurseFlags);
}
if (pooe->dwFlags & PROP_WEBCRAWL_ACTUALSIZE)
{
WriteDWORD(psi, c_szPropCrawlActualSize, pooe->m_ActualSize);
}
if (pooe->dwFlags & PROP_WEBCRAWL_SIZE)
{
if(pooe->m_SizeLimit)
{
// limit was specified
WriteDWORD(psi, c_szPropCrawlMaxSize, pooe->m_SizeLimit);
}
else
{
// no limit was specified, empty out limit prop
WriteEMPTY(psi, c_szPropCrawlMaxSize);
}
}
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii)))
{
sii.dwFlags = pooe->grfTaskTrigger;
psi->SetSubscriptionItemInfo(&sii);
}
// We don't write Status/Last update.
// FEATURE: We should fail the subscription if we were unable to write
// any of the properties into the notification for some reason.
return hr;
}
HRESULT WriteProperties(POOEntry pooe)
{
HRESULT hr;
ISubscriptionItem *psi = NULL;
ASSERT(NULL != pooe);
hr = SubscriptionItemFromCookie(FALSE, &pooe->m_Cookie, &psi);
if (SUCCEEDED(hr))
{
hr = WritePropertiesToItem(pooe, psi);
psi->Release();
}
return hr;
}
HRESULT CreatePublisherSchedule()
{
return S_OK;
}
#define RANDOM_TIME_START 0 // 12am (in minutes)
#define RANDOM_TIME_END 300 // 5am (in minutes)
#define RANDOM_TIME_INC 30 // 30min increment
DWORD GetRandomTime(DWORD StartMins, DWORD EndMins, DWORD Inc)
{
DWORD Range;
DWORD nIncrements;
if (StartMins > EndMins)
{
Range = ((1440 - StartMins) + EndMins);
}
else
{
Range = (EndMins - StartMins);
}
nIncrements = ((Range / Inc) + 1);
return (StartMins + (Random(nIncrements) * Inc));
}
HRESULT CreateDefaultSchedule(SUBSCRIPTIONSCHEDULE subsSchedule,
SYNCSCHEDULECOOKIE *pSchedCookie)
{
HRESULT hr = S_OK;
TASK_TRIGGER trig;
int resID;
memset((void*) &trig, 0x0, sizeof(TASK_TRIGGER));
*pSchedCookie = GUID_NULL;
ZeroMemory(&trig, sizeof(trig));
switch (subsSchedule)
{
case SUBSSCHED_DAILY:
trig.TriggerType = TASK_TIME_TRIGGER_DAILY;
trig.Type.Daily.DaysInterval = 1;
resID = IDS_DAILY_GRO;
*pSchedCookie = NOTFCOOKIE_SCHEDULE_GROUP_DAILY;
break;
case SUBSSCHED_WEEKLY:
trig.TriggerType = TASK_TIME_TRIGGER_WEEKLY;
trig.Type.Weekly.WeeksInterval = 1;
trig.Type.Weekly.rgfDaysOfTheWeek = TASK_MONDAY;
resID = IDS_WEEKLY_GRO;
*pSchedCookie = NOTFCOOKIE_SCHEDULE_GROUP_WEEKLY;
break;
case SUBSSCHED_AUTO:
case SUBSSCHED_CUSTOM:
case SUBSSCHED_MANUAL:
default:
resID = 0;
hr = E_FAIL;
break;
}
if (SUCCEEDED(hr))
{
if (!ScheduleCookieExists(pSchedCookie))
{
WCHAR wszSchedName[MAX_PATH];
DWORD dwRandTime = GetRandomTime(RANDOM_TIME_START,
RANDOM_TIME_END,
RANDOM_TIME_INC);
trig.cbTriggerSize = sizeof(TASK_TRIGGER);
trig.wRandomMinutesInterval = RANDOM_TIME_INC;
trig.wStartHour = (UINT)(dwRandTime / 60);
trig.wStartMinute = (UINT)(dwRandTime % 60);
trig.rgFlags = 0;
MLLoadStringW(resID, wszSchedName, ARRAYSIZE(wszSchedName));
hr = CreateSchedule(wszSchedName, 0, pSchedCookie, &trig, TRUE);
if (hr == SYNCMGR_E_NAME_IN_USE)
{
hr = S_OK;
}
}
}
return hr;
}
HRESULT AddIt(ISubscriptionItem *psi, POOEntry pooe, SUBSCRIPTIONSCHEDULE subGroup)
{
SYNCSCHEDULECOOKIE schedCookie = GUID_NULL;
HRESULT hr = E_FAIL;
switch (subGroup)
{
case SUBSSCHED_DAILY:
case SUBSSCHED_WEEKLY:
hr = CreateDefaultSchedule(subGroup, &schedCookie);
break;
case SUBSSCHED_CUSTOM:
schedCookie = pooe->groupCookie;
hr = S_OK;
break;
case SUBSSCHED_MANUAL:
SUBSCRIPTIONCOOKIE cookie;
cookie = pooe->m_Cookie;
RemoveItemFromAllSchedules(&cookie);
pooe->m_Cookie = cookie;
hr = S_FALSE;
break;
case SUBSSCHED_AUTO:
// FEATURE - for now, until pub schedules are wired in
hr = CreateDefaultSchedule(SUBSSCHED_DAILY, &schedCookie);
break;
}
if (hr == S_OK)
{
ASSERT(GUID_NULL != schedCookie);
if (NOOP_SCHEDULE_COOKIE == schedCookie)
{
hr = S_FALSE;
}
if (GUID_NULL != schedCookie)
{
SYNC_HANDLER_ITEM_INFO shii;
shii.handlerID = CLSID_WebCheckOfflineSync;
shii.itemID = pooe->m_Cookie;
shii.hIcon = NULL;
MyStrToOleStrN(shii.wszItemName, ARRAYSIZE(shii.wszItemName), NAME(pooe));
shii.dwCheckState = SYNCMGRITEMSTATE_CHECKED;
hr = AddScheduledItem(&shii, &schedCookie);
}
else
{
hr = E_FAIL;
}
}
return S_OK;
// return hr;
}
HRESULT ScheduleIt(ISubscriptionItem *psi, TCHAR *pszName, TASK_TRIGGER *pTrigger)
{
HRESULT hr;
SUBSCRIPTIONITEMINFO subscriptionItemInfo;
ASSERT(pTrigger->cbTriggerSize == sizeof(TASK_TRIGGER));
subscriptionItemInfo.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
#ifdef DEBUG
DumpTaskTrigger(pTrigger);
#endif
hr = psi->GetSubscriptionItemInfo(&subscriptionItemInfo);
if (SUCCEEDED(hr))
{
if (GUID_NULL != subscriptionItemInfo.ScheduleGroup)
{
hr = UpdateScheduleTrigger(&subscriptionItemInfo.ScheduleGroup, pTrigger);
}
else
{
hr = E_FAIL;
}
}
if (FAILED(hr))
{
WCHAR wszSchedName[MAX_PATH];
CreatePublisherScheduleNameW(wszSchedName, ARRAYSIZE(wszSchedName),
pszName, NULL);
hr = CreateSchedule(wszSchedName, SYNCSCHEDINFO_FLAGS_READONLY,
&subscriptionItemInfo.ScheduleGroup, pTrigger, TRUE);
if (SUCCEEDED(hr) || (hr == SYNCMGR_E_NAME_IN_USE))
{
psi->SetSubscriptionItemInfo(&subscriptionItemInfo);
hr = S_OK;
}
else
{
TraceMsg(TF_ALWAYS, "Error creating schedule - hr=0x%08x", hr);
}
}
if (SUCCEEDED(hr))
{
SYNC_HANDLER_ITEM_INFO shii;
shii.handlerID = CLSID_WebCheckOfflineSync;
psi->GetCookie(&shii.itemID);
shii.hIcon = NULL;
MyStrToOleStrN(shii.wszItemName, ARRAYSIZE(shii.wszItemName), pszName);
hr = AddScheduledItem(&shii, &subscriptionItemInfo.ScheduleGroup);
}
return S_OK;
// return hr;
}
HRESULT ReadProperties(POOEBuf pBuf)
{
VARIANT var;
HRESULT hr;
ASSERT(pBuf);
BOOL bHasUNAME = TRUE;
ISubscriptionItem *psi = NULL;
ASSERT(NULL != pBuf);
hr = SubscriptionItemFromCookie(FALSE, &pBuf->m_Cookie, &psi);
if (SUCCEEDED(hr))
{
VariantInit(&var);
if (pBuf->dwFlags & PROP_WEBCRAWL_URL)
{
hr = ReadVariant(psi, c_szPropURL, &var);
if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
{
MyOleStrToStrN(pBuf->m_URL, MAX_URL, var.bstrVal);
}
else
{
pBuf->m_URL[0] = (TCHAR)0;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_NAME)
{
hr = ReadVariant(psi, c_szPropName, &var);
if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
{
MyOleStrToStrN(pBuf->m_Name, MAX_NAME, var.bstrVal);
}
else
{
pBuf->m_Name[0] = (TCHAR)0;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_UNAME)
{
hr = ReadVariant(psi, c_szPropCrawlUsername, &var);
if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
{
MyOleStrToStrN(pBuf->username, MAX_USERNAME, var.bstrVal);
}
else
{
pBuf->username[0] = (TCHAR)0;
bHasUNAME = FALSE;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_DESKTOP)
{
hr = ReadVariant(psi, c_szPropDesktopComponent, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
{
pBuf->bDesktop = TRUE;
}
else
{
pBuf->bDesktop = FALSE;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_CHANNEL)
{
hr = ReadVariant(psi, c_szPropChannel, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
{
pBuf->bChannel = TRUE;
}
else
{
pBuf->bChannel = FALSE;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_GLEAM)
{
hr = ReadVariant(psi, c_szPropEnableShortcutGleam, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
{
pBuf->bGleam = TRUE;
}
else
{
pBuf->bGleam = FALSE;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_CHANGESONLY)
{
hr = ReadVariant(psi, c_szPropCrawlChangesOnly, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
{
pBuf->bChangesOnly = TRUE;
}
else
{
pBuf->bChangesOnly = FALSE;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_CHANNELFLAGS)
{
hr = ReadVariant(psi, c_szPropChannelFlags, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4))
{
pBuf->fChannelFlags = var.lVal;
}
else
{
pBuf->fChannelFlags = 0;
}
VariantClear(&var);
}
if (pBuf->dwFlags & PROP_WEBCRAWL_EMAILNOTF)
{
hr = ReadVariant(psi, c_szPropEmailNotf, &var);
if (SUCCEEDED(hr) && (var.vt == VT_I4) && (var.lVal == 1))
{
pBuf->bMail = TRUE;
}
else
{
pBuf->bMail = FALSE;
}
VariantClear(&var);
}
if ((pBuf->dwFlags & PROP_WEBCRAWL_PSWD) && bHasUNAME)
{
BSTR bstrVal = NULL;
hr = ReadPassword(psi, &bstrVal);
if (SUCCEEDED(hr) && bstrVal)
{
MyOleStrToStrN(pBuf->password, MAX_PASSWORD, bstrVal);
}
else
{
pBuf->password[0] = (TCHAR)0;
}
SAFEFREEBSTR(bstrVal);
}
if ((pBuf->dwFlags & PROP_WEBCRAWL_PSWD) || (pBuf->dwFlags & PROP_WEBCRAWL_UNAME)) {
//bNeedPassword isn't stored in the property map... calculate it from the presence
//of username/password.
pBuf->bNeedPassword = pBuf->password[0] || pBuf->username[0];
}
if (pBuf->dwFlags & PROP_WEBCRAWL_STATUS)
{
hr = ReadVariant(psi, c_szPropStatusString, &var);
if (SUCCEEDED(hr) && (var.vt == VT_BSTR))
{
MyOleStrToStrN(pBuf->statusStr, MAX_STATUS, var.bstrVal);
}
else
{
pBuf->statusStr[0] = (TCHAR)0;
}
VariantClear(&var);
hr = ReadSCODE(psi, c_szPropStatusCode, &(pBuf->status));
// FEATURE What should we put here if we don't have last status?
if (FAILED(hr))
{
pBuf->status = S_OK;
}
VariantClear(&var);
}
//
// Use the CompletionTime property if present and it is greater than
// value in the NOTIFICATIONITEM structure.
//
if (pBuf->dwFlags & PROP_WEBCRAWL_LAST)
{
CFileTime ft;
hr = ReadVariant(psi, c_szPropCompletionTime, &var);
if (SUCCEEDED(hr) && (var.vt == VT_DATE))
{
VariantTimeToFileTime(var.date, ft);
if (ft > pBuf->m_LastUpdated)
{
pBuf->m_LastUpdated = ft;
}
}
}
if (pBuf->dwFlags & PROP_WEBCRAWL_LEVEL)
{
hr = ReadDWORD(psi, c_szPropCrawlLevels, (DWORD *)&(pBuf->m_RecurseLevels));
if (FAILED(hr))
{
pBuf->m_RecurseLevels = 0;
}
}
if (pBuf->dwFlags & PROP_WEBCRAWL_FLAGS)
{
hr = ReadDWORD(psi, c_szPropCrawlFlags, (DWORD *)&(pBuf->m_RecurseFlags));
if (FAILED(hr))
{
pBuf->m_RecurseFlags = 0; // Minimal memory usage.
}
}
if (pBuf->dwFlags & PROP_WEBCRAWL_SIZE)
{
hr = ReadDWORD(psi, c_szPropCrawlMaxSize, (DWORD *)&(pBuf->m_SizeLimit));
if (FAILED(hr))
{
pBuf->m_SizeLimit = 0;
}
}
if (pBuf->dwFlags & PROP_WEBCRAWL_ACTUALSIZE)
{
hr = ReadDWORD(psi, c_szPropCrawlActualSize, (DWORD *)&(pBuf->m_ActualSize));
if (FAILED(hr))
{
pBuf->m_ActualSize = 0;
}
}
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii)))
{
pBuf->grfTaskTrigger = sii.dwFlags;
}
psi->Release();
}
// FEATURE: Need to support c_szPropEnableShortcutGleam here.
return S_OK;
}
// If url is NULL, no need to compare.
HRESULT LoadWithCookie(LPCTSTR pszURL, POOEBuf pBuf, DWORD *pdwBufferSize, SUBSCRIPTIONCOOKIE *pCookie)
{
HRESULT hr = LoadOOEntryInfo(pBuf, pCookie, pdwBufferSize);
if (SUCCEEDED(hr) && pszURL)
{
if (UrlCompare(pBuf->m_URL, pszURL, TRUE))
{
TraceMsg(TF_ALWAYS, "Mismatched cookie/URL in LoadWithCookie");
hr = E_FAIL; // Mismatched cookie!
}
}
return hr;
}
HRESULT ReadCookieFromInetDB(LPCTSTR pszURL, SUBSCRIPTIONCOOKIE *pCookie)
{
ASSERT(pszURL && pCookie);
PROPVARIANT propCookie;
PropVariantInit(&propCookie);
HRESULT hr = FindURLProps(pszURL, &propCookie);
if (SUCCEEDED(hr) && (propCookie.vt == VT_LPWSTR))
{
hr = CLSIDFromString(propCookie.pwszVal, pCookie);
}
PropVariantClear(&propCookie);
// If we couldn't find it, use a brute force approach
if (S_OK != hr)
{
CEnumSubscription *pes = new CEnumSubscription;
if (NULL != pes)
{
if (SUCCEEDED(pes->Initialize(0)))
{
SUBSCRIPTIONCOOKIE cookie;
BOOL bFound = FALSE;
while (!bFound && (S_OK == pes->Next(1, &cookie, NULL)))
{
ISubscriptionItem *psi;
if (SUCCEEDED(SubscriptionItemFromCookie(FALSE, &cookie, &psi)))
{
LPTSTR pszCurURL;
if (SUCCEEDED(ReadTSTR(psi, c_szPropURL, &pszCurURL)))
{
bFound = (StrCmpI(pszCurURL, pszURL) == 0);
CoTaskMemFree(pszCurURL);
}
psi->Release();
}
}
if (bFound)
{
WriteCookieToInetDB(pszURL, &cookie, FALSE);
*pCookie = cookie;
hr = S_OK;
}
}
pes->Release();
}
}
return hr;
}
HRESULT LoadSubscription(LPCTSTR url, LPMYPIDL *ppidl)
{
HRESULT hr;
POOEntry pooe = NULL;
OOEBuf ooeBuf;
DWORD dwBufferSize;
SUBSCRIPTIONCOOKIE cookie;
hr = ReadCookieFromInetDB(url, &cookie);
if (S_OK == hr)
{
hr = LoadWithCookie(url, &ooeBuf, &dwBufferSize, &cookie);
if (hr == S_OK)
{
*ppidl = COfflineFolderEnum::NewPidl(dwBufferSize);
if (!(*ppidl))
{
return E_OUTOFMEMORY;
}
pooe = &((*ppidl)->ooe);
CopyToMyPooe(&ooeBuf, pooe);
}
else
{
WriteCookieToInetDB(url, NULL, TRUE);
hr = E_FAIL;
}
}
else
{
hr = E_FAIL;
}
return hr;
}
// KENSY: This needs to work like GetDefaultInfo
HRESULT GetDefaultOOEBuf(OOEBuf * pBuf, SUBSCRIPTIONTYPE subType)
{
ASSERT(pBuf);
ASSERT(IS_VALID_SUBSCRIPTIONTYPE(subType));
memset((void *)pBuf, 0, sizeof(OOEBuf));
pBuf->dwFlags = PROP_WEBCRAWL_ALL;
pBuf->m_RecurseLevels = DEFAULTLEVEL;
pBuf->m_RecurseFlags = DEFAULTFLAGS;
pBuf->m_Priority = AGENT_PRIORITY_NORMAL;
if (subType == SUBSTYPE_CHANNEL || subType == SUBSTYPE_DESKTOPCHANNEL)
{
pBuf->clsidDest = CLSID_ChannelAgent;
pBuf->fChannelFlags = CHANNEL_AGENT_PRECACHE_ALL | CHANNEL_AGENT_DYNAMIC_SCHEDULE;
}
else
{
pBuf->clsidDest = CLSID_WebCrawlerAgent;
}
pBuf->bDesktop = (subType == SUBSTYPE_DESKTOPCHANNEL || subType == SUBSTYPE_DESKTOPURL);
pBuf->bChannel = (subType == SUBSTYPE_CHANNEL || subType == SUBSTYPE_DESKTOPCHANNEL);
pBuf->bGleam = !(pBuf->bDesktop);
pBuf->m_LastUpdated = 0;
pBuf->m_NextUpdate = 0;
// APPCOMPAT: Is this what we want? IE 4 was DAILY.
// Default to not changing the schedule settings -- if it's already subscribed
// we won't blast anything and if it's not already subscribed then it will
// just be manual.
pBuf->groupCookie = NOOP_SCHEDULE_COOKIE;
pBuf->grfTaskTrigger = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET | // Default to not autodial
TASK_FLAG_START_ONLY_IF_IDLE; // and to idle time
return S_OK;
}
HRESULT CreateSubscriptionFromOOEBuf(OOEBuf *pBuf, LPMYPIDL *ppidl)
{
HRESULT hr;
DWORD dwBufferSize = BufferSize(pBuf);
SUBSCRIPTIONCOOKIE cookie;
*ppidl = COfflineFolderEnum::NewPidl(dwBufferSize);
if (!(*ppidl))
{
return E_OUTOFMEMORY;
}
POOEntry pooe = &((*ppidl)->ooe);
CopyToMyPooe(pBuf, pooe);
// See if the caller has already given us a cookie
if (GUID_NULL == pooe->m_Cookie)
{
// Nope, see if we have one already
cookie = pooe->m_Cookie;
ReadCookieFromInetDB(URL(pooe), &cookie);
pooe->m_Cookie = cookie;
if (GUID_NULL == pooe->m_Cookie)
{
// Nope, so create one
CreateCookie(&pooe->m_Cookie);
}
}
cookie = pooe->m_Cookie;
WriteCookieToInetDB(URL(pooe), &cookie, FALSE);
pooe->m_Cookie = cookie;
WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
sii.dwFlags = 0;
sii.dwPriority = 0;
sii.ScheduleGroup = CLSID_NULL;
sii.clsidAgent = pooe->clsidDest;
MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), URL(pooe));
hr = AddUpdateSubscription(&(pooe->m_Cookie), &sii, wszURL, 0, NULL, NULL);
if (SUCCEEDED(hr))
{
hr = WriteProperties(pooe);
if (SUCCEEDED(hr))
{
ISubscriptionItem *psi;
hr = SubscriptionItemFromCookie(TRUE, &pooe->m_Cookie, &psi);
if (SUCCEEDED(hr))
{
SUBSCRIPTIONSCHEDULE subGroup = GetGroup(pooe);
SUBSCRIPTIONTYPE subType = GetItemCategory(pooe);
if (subGroup == SUBSSCHED_AUTO)
{
if (subType != SUBSTYPE_CHANNEL && subType != SUBSTYPE_DESKTOPCHANNEL)
{
hr = AddIt(psi, pooe, SUBSSCHED_DAILY);
}
else
{
if (pooe->m_Trigger.cbTriggerSize == sizeof(TASK_TRIGGER))
{
TASK_TRIGGER trigger;
trigger = pooe->m_Trigger;
hr = ScheduleIt(psi, NAME(pooe), &trigger);
pooe->m_Trigger = trigger;
pooe->groupCookie = CLSID_NULL;
}
else
{
hr = AddIt(psi, pooe, SUBSSCHED_DAILY);
}
}
}
else
{
hr = AddIt(psi, pooe, subGroup);
}
psi->Release();
}
}
}
if (SUCCEEDED(hr))
{
FireSubscriptionEvent(SUBSNOTF_CREATE, &pooe->m_Cookie);
}
else
{
TraceMsg(TF_ALWAYS, "Failed to add new subscription");
TraceMsg(TF_ALWAYS, "\thr = 0x%x", hr);
COfflineFolderEnum::FreePidl(*ppidl);
*ppidl = NULL;
}
return hr;
}
HRESULT SendUpdateRequests(HWND hwnd, CLSID * arrClsid, UINT count)
{
ISubscriptionMgr2 *pSubsMgr2;
HRESULT hr;
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
IID_ISubscriptionMgr2, (void**)&pSubsMgr2);
if (SUCCEEDED(hr))
{
SUBSCRIPTIONCOOKIE *pCookies = NULL;
ULONG nItemsToRun = count;
if (NULL == arrClsid)
{
IEnumSubscription *pes;
hr = pSubsMgr2->EnumSubscriptions(0, &pes);
if (SUCCEEDED(hr))
{
ASSERT(NULL != pes);
pes->GetCount(&nItemsToRun);
if (nItemsToRun > 0)
{
pCookies = new SUBSCRIPTIONCOOKIE[nItemsToRun];
if (NULL != pCookies)
{
hr = pes->Next(nItemsToRun, pCookies, &nItemsToRun);
}
else
{
hr = E_OUTOFMEMORY;
}
}
pes->Release();
}
}
else
{
pCookies = arrClsid;
}
if (SUCCEEDED(hr))
{
hr = pSubsMgr2->UpdateItems(0, nItemsToRun, pCookies);
}
if ((NULL == arrClsid) && (NULL != pCookies))
{
delete [] pCookies;
}
pSubsMgr2->Release();
}
CoUninitialize();
}
return hr;
}
HRESULT DoDeleteSubscription(POOEntry pooe)
{
HRESULT hr;
ISubscriptionItem *psi;
ASSERT(NULL != pooe);
hr = SubscriptionItemFromCookie(FALSE, &pooe->m_Cookie, &psi);
if (SUCCEEDED(hr))
{
WritePassword(psi, NULL);
hr = DoDeleteSubscriptionItem(&pooe->m_Cookie, TRUE);
if (SUCCEEDED(hr) && (GetItemCategory(pooe) != SUBSTYPE_EXTERNAL))
{
WriteCookieToInetDB(URL(pooe), NULL, TRUE);
}
}
return hr;
}
HRESULT PersistUpdate(POOEntry pooe, BOOL bCreate)
{
HRESULT hr;
ISubscriptionItem *psi;
hr = SubscriptionItemFromCookie(bCreate, &(pooe->m_Cookie), &psi);
if (SUCCEEDED(hr))
{
SUBSCRIPTIONITEMINFO sii = { sizeof(SUBSCRIPTIONITEMINFO) };
hr = psi->GetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr) || bCreate)
{
sii.clsidAgent = pooe->clsidDest;
hr = psi->SetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr))
{
hr = WritePropertiesToItem(pooe, psi);
if (SUCCEEDED(hr) && IsNativeAgent(pooe->clsidDest))
{
SUBSCRIPTIONCOOKIE cookie;
cookie = pooe->m_Cookie;
WriteCookieToInetDB(URL(pooe), &cookie, FALSE);
pooe->m_Cookie = cookie;
}
}
}
// REVIEW: should we delete on failure here?
psi->Release();
}
return hr;
}
#ifdef NEWSCHED_AUTONAME
void NewSched_AutoNameHelper(HWND hDlg)
{
TCHAR szDays[16];
TCHAR szTime[128];
TCHAR szFormat[MAX_PATH];
TCHAR szSchedName[MAX_PATH];
LPTSTR lpArguments[2];
BOOL bTranslate;
int nDays = GetDlgItemInt(hDlg, IDC_SCHEDULE_DAYS, &bTranslate, FALSE);
if (MLLoadString((nDays == 1) ? IDS_SCHED_FORMAT_DAILY : IDS_SCHED_FORMAT,
szFormat, ARRAYSIZE(szFormat)))
{
TCHAR szTimeFormat[32];
SYSTEMTIME st;
DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_SCHEDULE_TIME), &st);
UpdateTimeFormat(szTimeFormat, ARRAYSIZE(szTimeFormat));
GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st,
szTimeFormat, szTime, ARRAYSIZE(szTime));
GetDlgItemText(hDlg, IDC_SCHEDULE_DAYS, szDays, ARRAYSIZE(szDays));
lpArguments[0] = szDays;
lpArguments[1] = szTime;
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
szFormat, 0, 0, szSchedName, ARRAYSIZE(szSchedName),
(va_list *)&lpArguments[0]))
{
SetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName);
}
}
}
#endif
BOOL NewSched_ResolveNameConflictHelper(HWND hDlg, TASK_TRIGGER *pTrig,
SYNCSCHEDULECOOKIE *pSchedCookie)
{
BOOL bResult;
SYSTEMTIME st;
TCHAR szSchedName[MAX_PATH];
GetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName, ARRAYSIZE(szSchedName));
TrimWhiteSpace(szSchedName);
if (szSchedName[0] != 0)
{
bResult = TRUE;
memset(pTrig, 0, sizeof(TASK_TRIGGER));
pTrig->cbTriggerSize = sizeof(TASK_TRIGGER);
GetLocalTime(&st);
pTrig->wBeginYear = st.wYear;
pTrig->wBeginMonth = st.wMonth;
pTrig->wBeginDay = st.wDay;
DateTime_GetSystemtime(GetDlgItem(hDlg, IDC_SCHEDULE_TIME), &st);
pTrig->wStartHour = st.wHour;
pTrig->wStartMinute = st.wMinute;
pTrig->TriggerType = TASK_TIME_TRIGGER_DAILY;
BOOL bTranslated;
pTrig->Type.Daily.DaysInterval = (WORD)GetDlgItemInt(hDlg, IDC_SCHEDULE_DAYS, &bTranslated, FALSE);
int iConflictResult = HandleScheduleNameConflict(szSchedName,
pTrig,
hDlg,
pSchedCookie);
switch (iConflictResult)
{
case CONFLICT_NONE:
ASSERT(GUID_NULL == *pSchedCookie);
break;
case CONFLICT_RESOLVED_USE_NEW:
ASSERT(GUID_NULL != *pSchedCookie);
break;
case CONFLICT_RESOLVED_USE_OLD:
ASSERT(GUID_NULL == *pSchedCookie);
pTrig->cbTriggerSize = 0;
break;
case CONFLICT_UNRESOLVED:
bResult = FALSE;
break;
}
}
else
{
SGMessageBox(hDlg, IDS_EMPTY_SCHEDULE_NAME, MB_OK | MB_ICONWARNING);
bResult = FALSE;
}
return bResult;
}
void NewSched_CreateScheduleHelper(HWND hDlg, TASK_TRIGGER *pTrig,
SYNCSCHEDULECOOKIE *pSchedCookie)
{
HRESULT hr;
if (GUID_NULL == *pSchedCookie)
{
// Create new schedule
TCHAR szSchedName[MAX_PATH];
WCHAR wszSchedName[MAX_PATH];
DWORD dwSyncScheduleFlags =
(IsDlgButtonChecked(hDlg, IDC_WIZ_SCHEDULE_AUTOCONNECT) == BST_CHECKED)
? SYNCSCHEDINFO_FLAGS_AUTOCONNECT : 0;
GetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName, ARRAYSIZE(szSchedName));
MyStrToOleStrN(wszSchedName, ARRAYSIZE(wszSchedName), szSchedName);
hr = CreateSchedule(wszSchedName, dwSyncScheduleFlags, pSchedCookie, pTrig, FALSE);
ASSERT(SUCCEEDED(hr));
}
else if (sizeof(TASK_TRIGGER) == pTrig->cbTriggerSize)
{
// Update existing schedule with new task trigger
hr = UpdateScheduleTrigger(pSchedCookie, pTrig);
ASSERT(SUCCEEDED(hr));
}
else
{
// Use existing schedule without munging it
}
}
void NewSched_SetDefaultScheduleName(HWND hDlg)
{
if (SUCCEEDED(CoInitialize(NULL)))
{
ISyncScheduleMgr *pSyncScheduleMgr;
if (SUCCEEDED(CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
IID_ISyncScheduleMgr,
(void **)&pSyncScheduleMgr)))
{
SYNCSCHEDULECOOKIE schedCookie;
ISyncSchedule *pSyncSchedule;
if (SUCCEEDED(pSyncScheduleMgr->CreateSchedule(L"", 0, &schedCookie, &pSyncSchedule)))
{
WCHAR wszSchedName[MAX_PATH];
DWORD cchSchedName = ARRAYSIZE(wszSchedName);
if (SUCCEEDED(pSyncSchedule->GetScheduleName(&cchSchedName, wszSchedName)))
{
TCHAR szSchedName[MAX_PATH];
MyOleStrToStrN(szSchedName, ARRAYSIZE(szSchedName), wszSchedName);
SetDlgItemText(hDlg, IDC_SCHEDULE_NAME, szSchedName);
}
pSyncSchedule->Release();
}
pSyncScheduleMgr->Release();
}
CoUninitialize();
}
}
void NewSched_OnInitDialogHelper(HWND hDlg)
{
SYSTEMTIME st;
GetLocalTime(&st);
Edit_LimitText(GetDlgItem(hDlg, IDC_SCHEDULE_NAME), MAX_PATH - 1);
Edit_LimitText(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS), 2);
SendMessage(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS_SPIN),
UDM_SETRANGE, 0, MAKELONG(99, 1));
SendMessage(GetDlgItem(hDlg, IDC_SCHEDULE_DAYS_SPIN), UDM_SETPOS, 0, 1);
HWND hwndTimePicker = GetDlgItem(hDlg, IDC_SCHEDULE_TIME);
TCHAR szTimeFormat[32];
UpdateTimeFormat(szTimeFormat, ARRAYSIZE(szTimeFormat));
DateTime_SetSystemtime(hwndTimePicker, GDT_VALID, &st);
DateTime_SetFormat(hwndTimePicker, szTimeFormat);
NewSched_SetDefaultScheduleName(hDlg);
}
int KeepSpinNumberInRange(HWND hdlg, int idEdit, int idSpin, int minVal, int maxVal)
{
BOOL bTranslate;
int val = GetDlgItemInt(hdlg, idEdit, &bTranslate, FALSE);
if (!bTranslate || (val < minVal) || (val > maxVal))
{
// We have a problem, query the spin control
val = LOWORD(SendDlgItemMessage(hdlg, idSpin, UDM_GETPOS, 0, 0));
val = max(minVal, min(maxVal, val));
SetDlgItemInt(hdlg, idEdit, val, FALSE);
}
return val;
}
void SetPropSheetFlags(POOEBuf pBuf, BOOL bSet, DWORD dwPropSheetFlags)
{
if (bSet)
{
pBuf->m_dwPropSheetFlags |= dwPropSheetFlags;
}
else
{
pBuf->m_dwPropSheetFlags &= ~dwPropSheetFlags;
}
}
HRESULT FindURLProps(LPCTSTR m_URL, PROPVARIANT * pVarInfo)
{
HRESULT hr;
hr = IntSiteHelper(m_URL, &c_rgPropRead[PROP_SUBSCRIPTION], pVarInfo, 1, FALSE);
return hr;
}
HRESULT LoadOOEntryInfo(POOEBuf pBuf, SUBSCRIPTIONCOOKIE *pCookie, DWORD *pdwSize)
{
HRESULT hr;
if (!pBuf || !pCookie || !pdwSize)
{
TraceMsg(TF_ALWAYS, "Invalid ARG (1/2/3) %x %x", pBuf, pCookie, pdwSize);
return E_INVALIDARG;
}
ISubscriptionItem *psi;
hr = SubscriptionItemFromCookie(FALSE, pCookie, &psi);
if (SUCCEEDED(hr))
{
SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
hr = psi->GetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr))
{
ZeroMemory((void *)pBuf, sizeof(OOEBuf));
pBuf->m_Cookie = *pCookie;
// TODO: resolve scheduling goo!
// pBuf->groupCookie = pItem->groupCookie;
// pBuf->grfTaskTrigger = pItem->TaskData.dwTaskFlags;
/* if (pItem->groupCookie == CLSID_NULL) {
pBuf->m_Trigger = pItem->TaskTrigger;
if (pBuf->m_Trigger.cbTriggerSize != sizeof(TASK_TRIGGER)) {
ASSERT(0);
return E_INVALIDARG;
}
} else {
pBuf->m_Trigger.cbTriggerSize = 0; // Invalid
}
*/
pBuf->clsidDest = sii.clsidAgent;
if (!IsNativeAgent(sii.clsidAgent))
{
pBuf->dwFlags = PROP_WEBCRAWL_EXTERNAL;
}
else
{
pBuf->dwFlags = PROP_WEBCRAWL_ALL;
}
hr = ReadProperties(pBuf);
*pdwSize = BufferSize(pBuf);
}
psi->Release();
}
return hr;
}
/////////////////////////////////////////////////
//
// SaveBufferChange
// newBuf: [in/out]
/////////////////////////////////////////////////
HRESULT SaveBufferChange(POOEBuf newBuf, BOOL bCreate)
{
HRESULT hr;
DWORD dwSize;
POOEntry pooe;
LPMYPIDL newPidl;
ASSERT (newBuf);
if (newBuf->dwFlags == 0)
return S_OK;
dwSize = BufferSize(newBuf);
newPidl = COfflineFolderEnum::NewPidl(dwSize);
if (!newPidl)
return E_OUTOFMEMORY;
pooe = &(newPidl->ooe);
CopyToMyPooe(newBuf, pooe);
newBuf->dwFlags = 0;
hr = PersistUpdate(pooe, bCreate);
if (SUCCEEDED(hr)) {
SUBSCRIPTIONCOOKIE cookie;
DWORD dwPropSheetFlags = newBuf->m_dwPropSheetFlags; // Preserve prop sheet flags
cookie = pooe->m_Cookie;
hr = LoadWithCookie(URL(pooe), newBuf, &dwSize, &cookie);
pooe->m_Cookie = cookie;
newBuf->m_dwPropSheetFlags = dwPropSheetFlags; // restore
newBuf->dwFlags = 0;
if (hr == S_OK) {
COfflineFolderEnum::FreePidl(newPidl);
newPidl = COfflineFolderEnum::NewPidl(dwSize);
if (!(newPidl)) {
return E_OUTOFMEMORY;
}
pooe = &(newPidl->ooe);
CopyToMyPooe(newBuf, pooe);
}
_GenerateEvent(SHCNE_UPDATEITEM, (LPITEMIDLIST)newPidl, NULL);
}
COfflineFolderEnum::FreePidl(newPidl);
return hr;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// IntSiteHelper
//
// pszURL url to read/write props for
// pPropspec properties to read or write
// pReadPropvar where to store or get properties
// uPropVarArraySize number of properties
// fWrite read/write flag
//
HRESULT IntSiteHelper(LPCTSTR pszURL, const PROPSPEC *pPropspec,
PROPVARIANT *pPropvar, UINT uPropVarArraySize, BOOL fWrite)
{
HRESULT hr;
IUniformResourceLocator * purl = NULL;
IPropertySetStorage * ppropsetstg = NULL; // init to keep compiler happy
IPropertyStorage * ppropstg = NULL; // init to keep compiler happy
hr = SHCoCreateInstance(NULL, &CLSID_InternetShortcut, NULL,
IID_IUniformResourceLocator, (LPVOID*)&purl);
if(SUCCEEDED(hr)) {
hr = purl->SetURL(pszURL, 0);
}
if(SUCCEEDED(hr)) {
hr = purl->QueryInterface(IID_IPropertySetStorage,
(LPVOID *)&ppropsetstg);
}
if(SUCCEEDED(hr)) {
hr = ppropsetstg->Open(FMTID_InternetSite, STGM_READWRITE, &ppropstg);
ppropsetstg->Release();
}
if(SUCCEEDED(hr)) {
if(fWrite) {
hr = ppropstg->WriteMultiple(uPropVarArraySize, pPropspec,
pPropvar, 0);
ppropstg->Commit(STGC_DEFAULT);
} else {
hr = ppropstg->ReadMultiple(uPropVarArraySize, pPropspec,
pPropvar);
}
ppropstg->Release();
}
if(purl)
purl->Release();
return hr;
}
// CODE FROM SYNCMGR SOURCES.
//
// Local constants
//
// DEFAULT_TIME_FORMAT - what to use if there's a problem getting format
// from system.
//
#define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
#define DEFAULT_TIME_FORMAT TEXT("hh:mm tt")
#define GET_LOCALE_INFO(lcid) \
{ \
cch = GetLocaleInfo(LOCALE_USER_DEFAULT, \
(lcid), \
tszScratch, \
ARRAYLEN(tszScratch)); \
if (!cch) \
{ \
break; \
} \
}
//+--------------------------------------------------------------------------
//
// Function: UpdateTimeFormat
//
// Synopsis: Construct a time format containing hour and minute for use
// with the date picker control.
//
// Arguments: [tszTimeFormat] - buffer to fill with time format
// [cchTimeFormat] - size in chars of buffer
//
// Modifies: *[tszTimeFormat]
//
// History: 11-18-1996 DavidMun Created
//
// Notes: This is called on initialization and for wininichange
// processing.
//
//---------------------------------------------------------------------------
void
UpdateTimeFormat(
LPTSTR tszTimeFormat,
ULONG cchTimeFormat)
{
ULONG cch;
TCHAR tszScratch[80];
BOOL fAmPm = FALSE;
BOOL fAmPmPrefixes = FALSE;
BOOL fLeadingZero = FALSE;
do
{
GET_LOCALE_INFO(LOCALE_ITIME);
fAmPm = (*tszScratch == TEXT('0'));
if (fAmPm)
{
GET_LOCALE_INFO(LOCALE_ITIMEMARKPOSN);
fAmPmPrefixes = (*tszScratch == TEXT('1'));
}
GET_LOCALE_INFO(LOCALE_ITLZERO);
fLeadingZero = (*tszScratch == TEXT('1'));
GET_LOCALE_INFO(LOCALE_STIME);
//
// See if there's enough room in destination string
//
cch = 1 + // terminating nul
1 + // first hour digit specifier "h"
2 + // minutes specifier "mm"
(fLeadingZero != 0) + // leading hour digit specifier "h"
lstrlen(tszScratch) + // separator string
(fAmPm ? 3 : 0); // space and "tt" for AM/PM
if (cch > cchTimeFormat)
{
cch = 0; // signal error
}
} while (0);
//
// If there was a problem in getting locale info for building time string
// just use the default and bail.
//
if (!cch)
{
StrCpy(tszTimeFormat, DEFAULT_TIME_FORMAT);
return;
}
//
// Build a time string that has hours and minutes but no seconds.
//
tszTimeFormat[0] = TEXT('\0');
if (fAmPm)
{
if (fAmPmPrefixes)
{
StrCpy(tszTimeFormat, TEXT("tt "));
}
StrCat(tszTimeFormat, TEXT("h"));
if (fLeadingZero)
{
StrCat(tszTimeFormat, TEXT("h"));
}
}
else
{
StrCat(tszTimeFormat, TEXT("H"));
if (fLeadingZero)
{
StrCat(tszTimeFormat, TEXT("H"));
}
}
StrCat(tszTimeFormat, tszScratch); // separator
StrCat(tszTimeFormat, TEXT("mm"));
if (fAmPm && !fAmPmPrefixes)
{
StrCat(tszTimeFormat, TEXT(" tt"));
}
}