mirror of https://github.com/tongzx/nt5src
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
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"));
|
|
}
|
|
}
|