windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/dll/schedif.cpp

2515 lines
66 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998.
//
// File: schedif.cpp
//
// Contents: interfaces for synchronization scheduling
//
// Interfaces: IEnumSyncSchedules
// ISyncSchedule
// IEnumSyncItems
//
// Classes: CEnumSyncSchedules
// CSyncSchedule
// CEnumSyncItems
//
// Notes:
//
// History: 27-Feb-98 Susia Created.
//
//--------------------------------------------------------------------------
#include "precomp.h"
extern DWORD g_dwPlatformId;
extern UINT g_cRefThisDll;
extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
DWORD StartScheduler();
IsFriendlyNameInUse(LPTSTR ptszScheduleGUIDName, LPCTSTR ptstrFriendlyName);
//+--------------------------------------------------------------
//
// Class: CEnumSyncSchedules
//
// FUNCTION: CEnumSyncSchedules::CEnumSyncSchedules()
//
// PURPOSE: Constructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CEnumSyncSchedules::CEnumSyncSchedules(IEnumWorkItems *pIEnumWorkItems,
ITaskScheduler *pITaskScheduler)
{
TRACE("CEnumSyncSchedules::CEnumSyncSchedules()\r\n");
m_cRef = 1;
++g_cRefThisDll;
m_pIEnumWorkItems = pIEnumWorkItems;
m_pITaskScheduler = pITaskScheduler;
m_pITaskScheduler->AddRef();
m_pIEnumWorkItems->AddRef();
}
//+--------------------------------------------------------------
//
// Class: CEnumSyncSchedules
//
// FUNCTION: CEnumSyncSchedules::~CEnumSyncSchedules()
//
// PURPOSE: Destructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CEnumSyncSchedules::~CEnumSyncSchedules()
{
TRACE("CEnumSyncSchedules::~CEnumSyncSchedules()\r\n");
m_pITaskScheduler->Release();
m_pIEnumWorkItems->Release();
--g_cRefThisDll;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::QueryInterface(REFIID riid, LPVOID FAR *ppv)
//
// PURPOSE: QI for the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncSchedules::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
*ppv = NULL;
if (IsEqualIID(riid, IID_IUnknown))
{
TRACE("CEnumSyncSchedules::QueryInterface()==>IID_IUknown\r\n");
*ppv = (LPUNKNOWN)this;
}
else if (IsEqualIID(riid, IID_IEnumSyncSchedules))
{
TRACE("CSyncScheduleMgr::QueryInterface()==>IID_IEnumSyncSchedules\r\n");
*ppv = (LPENUMSYNCSCHEDULES) this;
}
if (*ppv)
{
AddRef();
return NOERROR;
}
TRACE("CEnumSyncSchedules::QueryInterface()==>Unknown Interface!\r\n");
return E_NOINTERFACE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::AddRef()
//
// PURPOSE: Addref for the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumSyncSchedules::AddRef()
{
TRACE("CEnumSyncSchedules::AddRef()\r\n");
return ++m_cRef;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::Release()
//
// PURPOSE: Release for the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumSyncSchedules::Release()
{
TRACE("CEnumSyncSchedules::Release()\r\n");
if (--m_cRef)
return m_cRef;
delete this;
return 0L;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::Next(ULONG celt,
// SYNCSCHEDULECOOKIE *pSyncSchedCookie,
// ULONG *pceltFetched)
//
// PURPOSE: Next sync Schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncSchedules::Next(ULONG celt,
SYNCSCHEDULECOOKIE *pSyncSchedCookie,
ULONG *pceltFetched)
{
SCODE sc;
LPWSTR *pwszSchedNames;
ULONG ulSyncCount = 0, ulTaskCount = 0;
ULONG ulFetched;
Assert(m_pIEnumWorkItems);
if ((0 == celt) ||
((celt > 1) && (NULL == pceltFetched)) ||
(NULL == pSyncSchedCookie))
{
return E_INVALIDARG;
}
//We may have to call Next multiple times, as we must filter out non-sync schedules.
do
{
ulTaskCount = 0;
if (FAILED (sc = m_pIEnumWorkItems->Next(celt - ulSyncCount,
&pwszSchedNames, &ulFetched)))
{
return sc;
}
if (ulFetched == 0)
{
break;
}
while (ulTaskCount < ulFetched)
{
//IsSyncMgrSched will blow away turds
if ( IsSyncMgrSched(pwszSchedNames[ulTaskCount]) )
{
if (!IsSyncMgrSchedHidden(pwszSchedNames[ulTaskCount]) )
{
pwszSchedNames[ulTaskCount][GUIDSTR_MAX] = NULL;
GUIDFromString(pwszSchedNames[ulTaskCount], &(pSyncSchedCookie[ulSyncCount]));
ulSyncCount++;
}
}
//Free this TaskName, we are done with it.
CoTaskMemFree(pwszSchedNames[ulTaskCount]);
ulTaskCount++;
}
CoTaskMemFree(pwszSchedNames);
} while (ulFetched && (ulSyncCount < celt));
if (pceltFetched)
{
*pceltFetched = ulSyncCount;
}
if (ulSyncCount == celt)
{
return S_OK;
}
return S_FALSE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::Skip(ULONG celt)
//
// PURPOSE: skip celt sync schedules
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncSchedules::Skip(ULONG celt)
{
SCODE sc;
LPWSTR *pwszSchedNames;
ULONG ulSyncCount = 0, ulTaskCount = 0;
ULONG ulFetched;
Assert(m_pIEnumWorkItems);
//We have to call Next, rather than wrap Skip, because we need the schedule name to
//determine if it is ours or not.
//We may have to call Next multiple times, as we must filter out non-sync schedules.
do
{
ulTaskCount = 0;
if (S_OK != (sc = m_pIEnumWorkItems->Next(celt - ulSyncCount,
&pwszSchedNames, &ulFetched)))
{
return sc;
}
while (ulTaskCount < ulFetched)
{
//IsSyncMgrSched will blow away turds
if ( IsSyncMgrSched(pwszSchedNames[ulTaskCount]) )
{
if (!IsSyncMgrSchedHidden(pwszSchedNames[ulTaskCount]) )
{
ulSyncCount++;
}
}
//Free this TaskName, we are done with it.
FREE(pwszSchedNames[ulTaskCount]);
ulTaskCount++;
}
FREE(pwszSchedNames);
} while (ulFetched && (ulSyncCount < celt));
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::Reset(void)
//
// PURPOSE: reset the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncSchedules::Reset(void)
{
Assert(m_pIEnumWorkItems);
return m_pIEnumWorkItems->Reset();
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncSchedules::Clone(IEnumSyncSchedules **ppEnumSyncSchedules)
//
// PURPOSE: Clone the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncSchedules::Clone(IEnumSyncSchedules **ppEnumSyncSchedules)
{
SCODE sc;
IEnumWorkItems *pIEnumWorkItems;
if (!ppEnumSyncSchedules)
{
return E_INVALIDARG;
}
Assert(m_pIEnumWorkItems);
if (FAILED(sc = m_pIEnumWorkItems->Clone(&pIEnumWorkItems)))
{
return sc;
}
*ppEnumSyncSchedules = new CEnumSyncSchedules(pIEnumWorkItems, m_pITaskScheduler);
if (!ppEnumSyncSchedules)
{
return E_OUTOFMEMORY;
}
//Constructor AddRefed it, we release it here.
pIEnumWorkItems->Release();
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: BOOL CEnumSyncSchedules::VerifyScheduleSID(LPCWSTR pwstrTaskName)
//
// PURPOSE: determine if this schedule SID matches the current user SID
// !!!Warning - This functions deletes the .job file so make sure
// if you call this function you validated the Task .job file
// was created by SyncMgr. Should change this so caller needs to
// delete
//
// History: 15-Oct-98 susia Created.
//
//--------------------------------------------------------------------------------
BOOL CEnumSyncSchedules::VerifyScheduleSID(LPCWSTR pwstrTaskName)
{
TCHAR ptszTaskName[MAX_PATH + 1],
ptszTextualSidUser[MAX_PATH + 1],
ptszTextualSidSched[MAX_PATH + 1];
DWORD dwSizeSid=MAX_PATH * sizeof(TCHAR);
if (!GetUserTextualSid( ptszTextualSidUser, &dwSizeSid ))
{
return FALSE;
}
ConvertString(ptszTaskName,(WCHAR *) pwstrTaskName, MAX_PATH);
//Truncate off the .job extension of the schedule name
int iTaskNameLen = lstrlen(ptszTaskName);
if (iTaskNameLen < 4)
{
return FALSE;
}
ptszTaskName[iTaskNameLen -4] = TEXT('\0');
//Get the SID for this schedule from the registry
dwSizeSid=MAX_PATH * sizeof(TCHAR);
//If this fails the key didn't exist
if (!RegGetSIDForSchedule(ptszTextualSidSched, &dwSizeSid, ptszTaskName) ||
//If this fails the key exists but has the wrong SID
lstrcmp(ptszTextualSidSched, ptszTextualSidUser))
{
//Try to remove the schedule
if (FAILED(m_pITaskScheduler->Delete(pwstrTaskName)))
{
//pwstrTaskName should have the .job extension for this function
RemoveScheduledJobFile((TCHAR *)pwstrTaskName);
}
//Remove our Registry settings for this schedule
//Note this should not have the .job extension
RegRemoveScheduledTask(ptszTaskName);
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: BOOL CEnumSyncSchedules::CheckForTaskNameKey(LPCWSTR pwstrTaskName)
//
// PURPOSE: check for a corresponging key for the .job
// !!!Warning - This functions deletes the .job file so make sure
// if you call this function you validated the Task .job file
// was created by SyncMgr. Should change this so caller needs to
// delete
//
// History: 21-Dec-98 susia Created.
//
//--------------------------------------------------------------------------------
BOOL CEnumSyncSchedules::CheckForTaskNameKey(LPCWSTR pwstrTaskName)
{
HKEY hkeySchedSync,hkeyDomainUser,hkeySchedName;
LONG lRegResult;
TCHAR ptszTaskName[MAX_SCHEDULENAMESIZE + 5];
hkeySchedSync = hkeyDomainUser = hkeySchedName = NULL;
if (!pwstrTaskName)
{
Assert(pwstrTaskName);
return FALSE;
}
ConvertString(ptszTaskName, (WCHAR *) pwstrTaskName, MAX_SCHEDULENAMESIZE + 4);
int iTaskNameLen = lstrlen(ptszTaskName);
if (iTaskNameLen < 4)
{
AssertSz (0, "Schedule name is too short");
return FALSE;
}
ptszTaskName[iTaskNameLen -4] = TEXT('\0');
// validate this is a valid schedule and if no registry data for
// it then delete the .job file.
// Get the UserName key from the TaskName itself since on NT schedules
// can fire if User provided as Password as a different user thant the
// current user.
//Idle GUID is the same UNICODE lenght as all GUID strings.
int OffsetToUserName = wcslen(WSZGUID_IDLESCHEDULE)
+ 1; // +1 for _ char between guid and user name.
TCHAR *pszDomainAndUser = (TCHAR *) ptszTaskName + OffsetToUserName;
// can't call standard function for getting since DomainName is from
// the task, if fails its okay
lRegResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,SCHEDSYNC_REGKEY,0,KEY_READ, &hkeySchedSync);
if (ERROR_SUCCESS == lRegResult)
{
lRegResult = RegOpenKeyEx (hkeySchedSync,pszDomainAndUser,0,KEY_READ, &hkeyDomainUser);
}
if (ERROR_SUCCESS == lRegResult)
{
lRegResult = RegOpenKeyEx (hkeyDomainUser,ptszTaskName,0,KEY_READ, &hkeySchedName);
}
// close up the keys
if (hkeySchedName) RegCloseKey(hkeySchedName);
if (hkeyDomainUser) RegCloseKey(hkeyDomainUser);
if (hkeySchedSync) RegCloseKey(hkeySchedSync);
// if any of the keys are bad then nix the TS file and return;
if ( ERROR_FILE_NOT_FOUND == lRegResult)
{
//Try to remove the schedule
if (FAILED(m_pITaskScheduler->Delete(pwstrTaskName)))
{
//pwstrTaskName should have the .job extension for this function
RemoveScheduledJobFile((TCHAR *)pwstrTaskName);
}
return FALSE;
}
else
{
return TRUE;
}
}
//--------------------------------------------------------------------------------
//
// FUNCTION: BOOL CEnumSyncSchedules::IsSyncMgrSched(LPCWSTR pwstrTaskName)
//
// PURPOSE: determine if this schedule is a SyncSched
//
// History: 03-Mar-98 susia Created.
//
//--------------------------------------------------------------------------------
BOOL CEnumSyncSchedules::IsSyncMgrSched(LPCWSTR pwstrTaskName)
{
TCHAR pszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE];
WCHAR pwszDomainAndUser[MAX_DOMANDANDMACHINENAMESIZE];
Assert(m_pITaskScheduler);
// First let's make sure our address arithmetic
// doesn't push us off the string
if (lstrlen(pwstrTaskName) <= GUIDSTR_MAX)
{
return FALSE;
}
//Now make sure this was created by CREATOR_SYNCMGR_TASK.
ITask *pITask;
LPWSTR pwszCreator;
if (FAILED(m_pITaskScheduler->Activate(pwstrTaskName,
IID_ITask,
(IUnknown **)&pITask)))
{
return FALSE;
}
if (FAILED(pITask->GetCreator(&pwszCreator)))
{
pITask->Release();
return FALSE;
}
if (0 != lstrcmp(pwszCreator, CREATOR_SYNCMGR_TASK))
{
CoTaskMemFree(pwszCreator);
pITask->Release();
return FALSE;
}
CoTaskMemFree(pwszCreator);
pITask->Release();
//Blow away the .job if there is no reg entry for it.
// so remember to make sure this schedule was created by us before
// calling
if (!CheckForTaskNameKey(pwstrTaskName))
{
return FALSE;
}
GetDefaultDomainAndUserName(pszDomainAndUser,TEXT("_"), MAX_DOMANDANDMACHINENAMESIZE);
ConvertString(pwszDomainAndUser, pszDomainAndUser,MAX_DOMANDANDMACHINENAMESIZE);
//Get the Domain and User name
if (0 != wcsncmp(&(pwstrTaskName[GUIDSTR_MAX +1]),pwszDomainAndUser,lstrlen(pwszDomainAndUser)))
{
return FALSE;
}
//Ok the name looks right for this user.
//Let's make sure the SID matches as well.
//on Win9X the SID should be the empty string
// !! this removes the .job file and regKeys if the sid doesn't match
if (!VerifyScheduleSID(pwstrTaskName))
{
return FALSE;
}
return TRUE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: BOOL CEnumSyncSchedules::IsSyncMgrSchedHidden(LPCWSTR pwstrTaskName)
//
// PURPOSE: determine if this schedule is a hidden
//
// History: 16-Mar-98 susia Created.
//
//--------------------------------------------------------------------------------
BOOL CEnumSyncSchedules::IsSyncMgrSchedHidden(LPCWSTR pwstrTaskName)
{
SCODE sc;
HKEY hKeyUser,hkeySchedName;
DWORD dwType = REG_DWORD;
DWORD dwDataSize = sizeof(DWORD);
DWORD dwHidden = FALSE;
int iTaskNameLen;
int i = 0;
TCHAR ptstrRegName[MAX_PATH + 1];
TCHAR ptstrNewName[MAX_PATH + 1];
ConvertString(ptstrNewName, (WCHAR *) pwstrTaskName, MAX_PATH);
//Truncate off the .job extension of the schedule name
iTaskNameLen = lstrlen(ptstrNewName);
if (iTaskNameLen < 4)
{
return FALSE;
}
ptstrNewName[iTaskNameLen -4] = TEXT('\0');
hKeyUser = RegGetCurrentUserKey(SYNCTYPE_SCHEDULED,KEY_READ,FALSE);
if (NULL == hKeyUser)
{
return FALSE;
}
do
{
sc = RegEnumKey( hKeyUser, i++, ptstrRegName, MAX_PATH);
//This is the schedule
if (0 == lstrcmp(ptstrRegName,ptstrNewName))
{
break;
}
} while (sc == S_OK);
//we couldn't find the schedule
if (sc != S_OK)
{
RegCloseKey(hKeyUser);
return FALSE;
}
//schedule found, get the hidden flag
if (ERROR_SUCCESS != (sc = RegOpenKeyEx (hKeyUser, ptstrRegName, 0,KEY_READ,
&hkeySchedName)))
{
RegCloseKey(hKeyUser);
return FALSE;
}
sc = RegQueryValueEx(hkeySchedName,TEXT("ScheduleHidden"),NULL, &dwType,
(LPBYTE) &dwHidden, &dwDataSize);
RegCloseKey(hkeySchedName);
RegCloseKey(hKeyUser);
if (dwHidden)
{
return TRUE;
}
return FALSE;
}
//+------------------------------------------------------------------------------
//
// Class: CSyncSchedule
//
//
// FUNCTION: CSyncSchedule::CSyncSchedule()
//
// PURPOSE: CSyncSchedule constructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CSyncSchedule::CSyncSchedule(ITask *pITask, LPTSTR ptstrGUIDName, LPTSTR ptstrFriendlyName)
{
TRACE("CSyncSchedule::CSyncSchedule()\r\n");
++g_cRefThisDll;
m_cRef = 1;
m_HndlrQueue = NULL;
m_fCleanReg = FALSE;
m_pITask = pITask;
m_pITask->AddRef();
m_iTrigger = 0;
m_pITrigger = NULL;
m_fNewSchedule = FALSE;
m_pFirstCacheEntry = NULL;
lstrcpy(m_ptstrGUIDName,ptstrGUIDName);
ConvertString(m_pwszFriendlyName,ptstrFriendlyName, MAX_PATH);
}
//+------------------------------------------------------------------------------
//
// Class: CSyncSchedule
//
//
// FUNCTION: CSyncSchedule::~CSyncSchedule()
//
// PURPOSE: CSyncSchedule destructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CSyncSchedule::~CSyncSchedule()
{
TRACE("CSyncSchedule::~CSyncSchedule()\r\n");
if (m_pITask)
{
m_pITask->Release();
}
if (m_pITrigger)
{
m_pITrigger->Release();
}
--g_cRefThisDll;
}
//+------------------------------------------------------------------------------
//
// Class: CSyncSchedule
//
//
// FUNCTION: CSyncSchedule::SetDefaultCredentials()
//
// PURPOSE: CSyncSchedule credential intialization
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::SetDefaultCredentials()
{
SCODE sc = S_OK;
//Set the default credentials
WCHAR pwszDomainAndUserName[MAX_DOMANDANDMACHINENAMESIZE];
DWORD dwSize = MAX_DOMANDANDMACHINENAMESIZE;
GetDefaultDomainAndUserName(pwszDomainAndUserName, TEXT("\\"), dwSize);
if (FAILED(sc = m_pITask->SetFlags(TASK_FLAG_RUN_ONLY_IF_LOGGED_ON)))
{
return sc;
}
if (FAILED(sc = m_pITask->SetAccountInformation(pwszDomainAndUserName,NULL)))
{
return sc;
}
return sc;
}
//+------------------------------------------------------------------------------
//
// Class: CSyncSchedule
//
//
// FUNCTION: CSyncSchedule::Initialize()
//
// PURPOSE: CSyncSchedule intialization
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::Initialize()
{
SCODE sc = S_OK;
TRACE("CSyncSchedule::Initialize()\r\n");
Assert(m_pITask);
// Form the application name/path and command line params.
//initialize the syncmgr application name
TCHAR ptszFileName[MAX_PATH + 1];
WCHAR pwszAppName[MAX_PATH + 1];
WCHAR pwszSchedName[MAX_PATH + 1];
if (!LoadString(g_hmodThisDll, IDS_SYNCMGR_EXE_NAME, ptszFileName, MAX_PATH))
{
return E_OUTOFMEMORY;
}
ConvertString(pwszAppName, ptszFileName, MAX_PATH);
ConvertString(pwszSchedName, m_ptstrGUIDName, MAX_PATH);
m_pITask->SetApplicationName(pwszAppName);
lstrcpy(pwszAppName,SCHED_COMMAND_LINE_ARG);
lstrcat(pwszAppName, L"\""); // put quotes to handle friendly names
lstrcat(pwszAppName, pwszSchedName);
lstrcat(pwszAppName, L"\"");
if (FAILED(sc = m_pITask->SetParameters(pwszAppName)))
{
AssertSz(0,"m_pITask->SetParameters() failed");
return sc;
}
// Specify the creator name. SyncMGr uses this to identify syncmgr tasks
if (FAILED(sc = m_pITask->SetCreator(CREATOR_SYNCMGR_TASK)))
{
AssertSz(0,"m_pITask->SetCreator() failed");
return sc;
}
//Set up the Trigger
WORD wTriggerCount;
if (FAILED(sc = m_pITask->GetTriggerCount(&wTriggerCount)))
{
AssertSz(0,"m_pITask->GetTriggerCount() failed");
return sc;
}
if (wTriggerCount == 0)
{
if (FAILED(sc = m_pITask->CreateTrigger(&m_iTrigger, &m_pITrigger)))
{
AssertSz(0,"m_pITask->CreateTrigger() failed");
return sc;
}
}
else if (FAILED(sc = m_pITask->GetTrigger(m_iTrigger, &m_pITrigger)))
{
AssertSz(0,"m_pITask->GetTrigger() failed");
return sc;
}
//Create a new connectionSettings for this schedule and hand off to the handler queue
// who will free it
m_pConnectionSettings = (LPCONNECTIONSETTINGS)
ALLOC(sizeof(CONNECTIONSETTINGS));
if (!m_pConnectionSettings)
{
return E_OUTOFMEMORY;
}
// If the connection name isn't in the registry, we know this is a new schedule.
// We set the name to the default connection name and return FALSE if it wasn't there,
// True if it was located in the registry
if (!RegGetSchedConnectionName(m_ptstrGUIDName,
m_pConnectionSettings->pszConnectionName,
MAX_PATH))
{
m_fNewSchedule = TRUE;
}
//this set defaults before quering registry, so if it can't read the reg,
//we will just get defaults.
RegGetSchedSyncSettings(m_pConnectionSettings, m_ptstrGUIDName);
//Save the Connection name and type on this obj
ConvertString(m_pwszConnectionName, m_pConnectionSettings->pszConnectionName, MAX_PATH);
m_dwConnType = m_pConnectionSettings->dwConnType;
if (!m_HndlrQueue)
{
m_HndlrQueue = new CHndlrQueue(QUEUETYPE_SETTINGS);
if (!m_HndlrQueue)
{
return E_OUTOFMEMORY;
}
if (FAILED(sc = m_HndlrQueue->InitSchedSyncSettings(m_pConnectionSettings)))
{
return sc;
}
}
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::LoadOneHandler(REFCLSID pHandlerID)
//
// PURPOSE: Initialize and load this handler
//
// History: 9-Oct-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::LoadOneHandler(REFCLSID pHandlerID)
{
SCODE sc = NOERROR;
WORD wHandlerID;
Assert(m_HndlrQueue);
if (NOERROR == (sc = m_HndlrQueue->AddHandler(pHandlerID, &wHandlerID)))
{
if (FAILED(sc = m_HndlrQueue->CreateServer(wHandlerID,&pHandlerID)))
{
return sc;
}
// Initialize the handlers.
// If the Handler doesn't want to play on this schedule, remove him.
if (S_FALSE == m_HndlrQueue->Initialize(wHandlerID,0,SYNCMGRFLAG_SETTINGS,0,NULL))
{
m_HndlrQueue->RemoveHandler(wHandlerID);
return SYNCMGR_E_HANDLER_NOT_LOADED;
}
if (FAILED(sc = m_HndlrQueue->AddHandlerItemsToQueue(wHandlerID)))
{
return sc;
}
//this set defaults before quering registry, so if it can't read the reg,
//we will just get defaults.
m_HndlrQueue->ReadSchedSyncSettingsOnConnection(wHandlerID, m_ptstrGUIDName);
//Apply all the cached changed to the newly loaded handler
ApplyCachedItemsCheckState(pHandlerID);
//Clear out the list of changes to this handler's items
PurgeCachedItemsCheckState(pHandlerID);
}
if (sc == S_FALSE)
{
return S_OK;
}
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::LoadAllHandlers()
//
// PURPOSE: Initialize and load all the handlers
//
// History: 6-Oct-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::LoadAllHandlers()
{
SCODE sc = NOERROR;
TCHAR lpName[MAX_PATH];
DWORD cbName = MAX_PATH;
HKEY hkSyncMgr;
CLSID clsid;
WORD wHandlerID;
Assert(m_HndlrQueue);
// loop through the reg getting the handlers and trying to
// create them.
hkSyncMgr = RegGetHandlerTopLevelKey(KEY_READ);
if (hkSyncMgr)
{
DWORD dwIndex = 0;
// if loading all handlers and got handler key open then can clean
// up old reg entries for this schedule
m_fCleanReg = TRUE;
while ( ERROR_SUCCESS == RegEnumKey(hkSyncMgr,dwIndex,
lpName,cbName) )
{
WCHAR wcName[MAX_PATH + 1];
ConvertString(wcName, lpName, MAX_PATH);
if (NOERROR == CLSIDFromString(wcName,&clsid) )
{
if (NOERROR == m_HndlrQueue->AddHandler(clsid, &wHandlerID))
{
HRESULT hrInit;
// Initialize the handlers.
// If the Handler fails to create or
// doesn't want to play on this schedule, remove him.
hrInit = m_HndlrQueue->CreateServer(wHandlerID,&clsid);
if (NOERROR == hrInit)
{
hrInit = m_HndlrQueue->Initialize(wHandlerID,0
,SYNCMGRFLAG_SETTINGS,0,NULL);
}
if (NOERROR != hrInit)
{
m_HndlrQueue->RemoveHandler(wHandlerID);
}
}
}
dwIndex++;
}
RegCloseKey(hkSyncMgr);
}
// loop through adding items
sc = m_HndlrQueue->FindFirstHandlerInState (HANDLERSTATE_ADDHANDLERTEMS,&wHandlerID);
while (sc == S_OK)
{
//ignore failures here and move on. Could be the handler just fails to addItems,
//and we don't want to fail the whole load over that
m_HndlrQueue->AddHandlerItemsToQueue(wHandlerID);
//this set defaults before quering registry, so if it can't read the reg,
//we will just get defaults.
m_HndlrQueue->ReadSchedSyncSettingsOnConnection(wHandlerID, m_ptstrGUIDName);
sc = m_HndlrQueue->FindNextHandlerInState(wHandlerID,
HANDLERSTATE_ADDHANDLERTEMS,
&wHandlerID);
}
//Apply all the chached changed to all the newly loaded handlers
ApplyCachedItemsCheckState(GUID_NULL);
//Clear out the list of changes to all handler items that occurred before loading
PurgeCachedItemsCheckState(GUID_NULL);
if (sc == S_FALSE)
{
return S_OK;
}
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::CacheItemCheckState(REFCLSID phandlerID,
// SYNCMGRITEMID itemID,
// DWORD dwCheckState)
//
// PURPOSE: Cache the check state of an item for a handler that is not yet loaded
//
// History: 12-02-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::CacheItemCheckState(REFCLSID phandlerID,
SYNCMGRITEMID itemID,
DWORD dwCheckState)
{
CACHELIST *pCurCacheEntry = m_pFirstCacheEntry;
while (pCurCacheEntry)
{
if ( (phandlerID == pCurCacheEntry->phandlerID) &&
(itemID == pCurCacheEntry->itemID) )
{
pCurCacheEntry->dwCheckState = dwCheckState;
return S_OK;
}
pCurCacheEntry = pCurCacheEntry->pNext;
}
//Not found in the list, insert it now
pCurCacheEntry = (CACHELIST *) ALLOC(sizeof(CACHELIST));
if (NULL == pCurCacheEntry)
{
return E_OUTOFMEMORY;
}
memset(pCurCacheEntry,0,sizeof(CACHELIST));
pCurCacheEntry->phandlerID = phandlerID;
pCurCacheEntry->itemID = itemID;
pCurCacheEntry->dwCheckState = dwCheckState;
pCurCacheEntry->pNext = m_pFirstCacheEntry;
m_pFirstCacheEntry = pCurCacheEntry;
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::RetreiveCachedItemCheckState(REFCLSID phandlerID,
// SYNCMGRITEMID itemID,
// DWORD *pdwCheckState)
//
// PURPOSE: Retreive the cached the check state (if any) of an item for
// a handler that is not yet loaded
//
// History: 12-02-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::RetreiveCachedItemCheckState(REFCLSID phandlerID,
SYNCMGRITEMID itemID,
DWORD *pdwCheckState)
{
CACHELIST *pCurCacheEntry = m_pFirstCacheEntry;
while (pCurCacheEntry)
{
if ( (phandlerID == pCurCacheEntry->phandlerID) &&
(itemID == pCurCacheEntry->itemID) )
{
*pdwCheckState = pCurCacheEntry->dwCheckState;
return S_OK;
}
pCurCacheEntry = pCurCacheEntry->pNext;
}
// no problem if we didn't find it, it has already been
// set to either what was in the registry, or if it wasn't in the registry,
// to the default check state
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::ApplyCachedItemsCheckState(REFCLSID pHandlerID)
//
// PURPOSE: Apply any check state changes that occurred before the handler was loaded
//
// History: 12-02-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::ApplyCachedItemsCheckState(REFCLSID phandlerID)
{
CACHELIST *pCurCacheEntry = m_pFirstCacheEntry;
while (pCurCacheEntry)
{
if ( (phandlerID == pCurCacheEntry->phandlerID) ||
(phandlerID == GUID_NULL) )
{
SetItemCheck( pCurCacheEntry->phandlerID,
&pCurCacheEntry->itemID,
pCurCacheEntry->dwCheckState);
}
pCurCacheEntry = pCurCacheEntry->pNext;
}
// no problem if we didn't find it, it has already been
// set to either what was in the registry, or if it wasn't in the registry,
// to the default check state
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::WriteOutAndPurgeCache()
//
// PURPOSE: If we never loaded the handlers before save, write the settings to the registry
//
// History: 12-02-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::WriteOutAndPurgeCache(void)
{
CACHELIST *pCurCacheEntry = m_pFirstCacheEntry;
CACHELIST *pTemp;
while (pCurCacheEntry)
{
RegSetSyncItemSettings(SYNCTYPE_SCHEDULED,
pCurCacheEntry->phandlerID,
pCurCacheEntry->itemID,
m_pwszConnectionName,
pCurCacheEntry->dwCheckState,
m_ptstrGUIDName);
pTemp = pCurCacheEntry;
pCurCacheEntry= pCurCacheEntry->pNext;
FREE(pTemp);
pTemp = NULL;
}
m_pFirstCacheEntry = NULL;
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::PurgeCachedItemsCheckState(REFCLSID pHandlerID)
//
// PURPOSE: Free from the list any check state changes that occurred before the handler was loaded
//
// History: 12-02-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::PurgeCachedItemsCheckState(REFCLSID phandlerID)
{
CACHELIST StartNode;
CACHELIST *pCur = NULL,
*pPrev = &StartNode;
pPrev->pNext = m_pFirstCacheEntry;
while (pPrev->pNext)
{
pCur = pPrev->pNext;
if ( (phandlerID == pCur->phandlerID) ||
(phandlerID == GUID_NULL) )
{
pPrev->pNext = pCur->pNext;
FREE(pCur);
}
else
{
pPrev = pCur;
}
}
m_pFirstCacheEntry = StartNode.pNext;
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::QueryInterface(REFIID riid, LPVOID FAR *ppv)
//
// PURPOSE: QI
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
*ppv = NULL;
if (IsEqualIID(riid, IID_IUnknown))
{
TRACE("CSyncSchedule::QueryInterface()==>IID_IUknown\r\n");
*ppv = (LPUNKNOWN)this;
}
else if (IsEqualIID(riid, IID_ISyncSchedule))
{
TRACE("CSyncSchedule::QueryInterface()==>IID_ISyncSchedule\r\n");
*ppv = (LPSYNCSCHEDULE) this;
}
else if (IsEqualIID(riid, IID_ISyncSchedulep))
{
TRACE("CSyncSchedule::QueryInterface()==>IID_ISyncSchedulep\r\n");
*ppv = (LPSYNCSCHEDULEP) this;
}
if (*ppv)
{
AddRef();
return NOERROR;
}
TRACE("CSyncSchedule::QueryInterface()==>Unknown Interface!\r\n");
return E_NOINTERFACE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::AddRef()
//
// PURPOSE: AddRef
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CSyncSchedule::AddRef()
{
TRACE("CSyncSchedule::AddRef()\r\n");
if (m_HndlrQueue)
m_HndlrQueue->AddRef();
return ++m_cRef;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::Release()
//
// PURPOSE: Release
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CSyncSchedule::Release()
{
TRACE("CSyncSchedule::Release()\r\n");
if (m_HndlrQueue)
m_HndlrQueue->Release();
if (--m_cRef)
return m_cRef;
delete this;
return 0L;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetFlags(DWORD *pdwFlags)
//
// PURPOSE: Get the flags for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetFlags(DWORD *pdwFlags)
{
if (!pdwFlags)
{
return E_INVALIDARG;
}
*pdwFlags = 0;
Assert(m_HndlrQueue);
if (m_HndlrQueue->GetCheck(IDC_AUTOHIDDEN, 0))
{
*pdwFlags |= SYNCSCHEDINFO_FLAGS_HIDDEN;
}
if (m_HndlrQueue->GetCheck(IDC_AUTOREADONLY, 0))
{
*pdwFlags |= SYNCSCHEDINFO_FLAGS_READONLY;
}
if (m_HndlrQueue->GetCheck(IDC_AUTOCONNECT, 0))
{
*pdwFlags |= SYNCSCHEDINFO_FLAGS_AUTOCONNECT;
}
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::SetFlags(DWORD dwFlags)
//
// PURPOSE: Set the flags for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::SetFlags(DWORD dwFlags)
{
SCODE sc;
Assert(m_HndlrQueue);
if (FAILED(sc = m_HndlrQueue->SetConnectionCheck(IDC_AUTOREADONLY,
(dwFlags & SYNCSCHEDINFO_FLAGS_READONLY) ? TRUE : FALSE, 0)))
{
return sc;
}
if (FAILED (sc = m_HndlrQueue->SetConnectionCheck(IDC_AUTOHIDDEN,
(dwFlags & SYNCSCHEDINFO_FLAGS_HIDDEN) ? TRUE : FALSE, 0)))
{
return sc;
}
sc = m_HndlrQueue->SetConnectionCheck(IDC_AUTOCONNECT,
(dwFlags & SYNCSCHEDINFO_FLAGS_AUTOCONNECT) ? TRUE : FALSE,0);
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetConnection(DWORD *pcbSize,
// LPWSTR pwszConnectionName,
// DWORD *pdwConnType)
//
// PURPOSE: Get the connection name for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetConnection(DWORD *pcbSize,
LPWSTR pwszConnectionName,
DWORD *pdwConnType)
{
if (!pcbSize || !pwszConnectionName || !pdwConnType)
{
return E_INVALIDARG;
}
if ( ((int) *pcbSize) <= lstrlen(m_pwszConnectionName))
{
*pcbSize = lstrlen(m_pwszConnectionName) + 1;
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
lstrcpy(pwszConnectionName, m_pwszConnectionName);
*pdwConnType = m_dwConnType;
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::SetConnection(LPCWSTR pwszConnectionName, DWORD dwConnType)
//
// PURPOSE: Set the connection for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::SetConnection(LPCWSTR pwszConnectionName, DWORD dwConnType)
{
SCODE sc = S_OK;
if (((dwConnType == SYNCSCHEDINFO_FLAGS_CONNECTION_WAN) && (!pwszConnectionName)) ||
((dwConnType != SYNCSCHEDINFO_FLAGS_CONNECTION_WAN) &&
(dwConnType != SYNCSCHEDINFO_FLAGS_CONNECTION_LAN) ) )
{
return E_INVALIDARG;
}
if (!m_fNewSchedule)
{
if (FAILED(sc = LoadAllHandlers()))
return sc;
}
if (pwszConnectionName && (lstrlen(pwszConnectionName) > MAX_PATH))
{
return E_INVALIDARG;
}
m_dwConnType = dwConnType;
if (!pwszConnectionName)
{
if (!LoadString(g_hmodThisDll, IDS_LAN_CONNECTION,
m_pwszConnectionName,ARRAY_SIZE(m_pwszConnectionName)))
{
m_pwszConnectionName[0] = NULL;
return E_UNEXPECTED;
}
}
else
{
lstrcpy(m_pwszConnectionName, pwszConnectionName);
}
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetScheduleName(DWORD *pcbSize,
// LPWSTR pwszScheduleName)
//
// PURPOSE: Get the friendly name for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetScheduleName(DWORD *pcbSize,
LPWSTR pwszScheduleName)
{
if (!pcbSize || !pwszScheduleName)
{
return E_INVALIDARG;
}
if ( ((int) *pcbSize) <= lstrlen(m_pwszFriendlyName))
{
*pcbSize = lstrlen(m_pwszFriendlyName) + 1;
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
lstrcpy(pwszScheduleName, m_pwszFriendlyName);
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::SetScheduleName(LPCWSTR pwszScheduleName)
//
// PURPOSE: Set the friendly name for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::SetScheduleName(LPCWSTR pwszScheduleName)
{
TCHAR ptszFriendlyName[MAX_PATH+1];
TCHAR ptszScheduleName[MAX_PATH+1];
TCHAR *ptszWorker = NULL;
WCHAR *pwszWorker = NULL;
int iName;
DWORD dwSize = MAX_PATH;
if (!pwszScheduleName)
{
return E_INVALIDARG;
}
if (lstrlen(pwszScheduleName) > MAX_PATH)
{
return E_INVALIDARG;
}
ConvertString(ptszFriendlyName, (WCHAR *) pwszScheduleName, MAX_PATH);
//strip trailing white space off name
iName = lstrlen(ptszFriendlyName);
if (iName)
{
ptszWorker = iName + ptszFriendlyName -1;
}
while (iName && (*ptszWorker == TEXT(' ')))
{
*ptszWorker = TEXT('\0');
--ptszWorker;
iName--;
}
//don't allow empty string schedule names
if (iName == 0)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_NAME);
}
lstrcpy(ptszScheduleName, m_ptstrGUIDName);
if (IsFriendlyNameInUse(ptszScheduleName, ptszFriendlyName))
{
//make sure it is in use by this schedule
if (0 != lstrcmp(ptszScheduleName, m_ptstrGUIDName))
{
return SYNCMGR_E_NAME_IN_USE;
}
}
// only copy up to first leading space
lstrcpyn(m_pwszFriendlyName, pwszScheduleName,iName);
pwszWorker = m_pwszFriendlyName + iName;
*pwszWorker = TEXT('\0');
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetScheduleCookie(SYNCSCHEDULECOOKIE *pSyncSchedCookie)
//
// PURPOSE: Set the schedule cookie
//
// History: 14-Mar-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetScheduleCookie(SYNCSCHEDULECOOKIE *pSyncSchedCookie)
{
WCHAR pwszSchedName[MAX_PATH +1];
if (!pSyncSchedCookie)
{
return E_INVALIDARG;
}
ConvertString(pwszSchedName, m_ptstrGUIDName, MAX_PATH);
pwszSchedName[GUIDSTR_MAX] = NULL;
GUIDFromString(pwszSchedName, pSyncSchedCookie);
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::SetAccountInformation(LPCWSTR pwszAccountName,
// LPCWSTR pwszPassword)
//
// PURPOSE: Set the credentials for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::SetAccountInformation(LPCWSTR pwszAccountName,
LPCWSTR pwszPassword)
{
Assert(m_pITask);
return m_pITask->SetAccountInformation(pwszAccountName, pwszPassword);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetAccountInformation(DWORD *pcbSize,
// LPWSTR pwszAccountName)
//
// PURPOSE: Get the credentials for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetAccountInformation(DWORD *pcbSize,
LPWSTR pwszAccountName)
{
Assert(m_pITask);
SCODE sc;
WCHAR *pwszAccount;
if (!pcbSize || !pwszAccountName)
{
return E_INVALIDARG;
}
if (FAILED(sc = m_pITask->GetAccountInformation(&pwszAccount)))
{
return sc;
}
if (lstrlen(pwszAccount) > (*pcbSize) )
{
CoTaskMemFree(pwszAccount);
*pcbSize = lstrlen(pwszAccount) + 1;
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
lstrcpy(pwszAccountName, pwszAccount);
CoTaskMemFree(pwszAccount);
return S_OK;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetTrigger(ITaskTrigger ** ppTrigger)
//
// PURPOSE: Return the ITaskTrigger interface for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetTrigger(ITaskTrigger ** ppTrigger)
{
SCODE sc = S_OK;
Assert(m_pITask);
Assert (m_pITrigger);
if (!ppTrigger)
{
return E_INVALIDARG;
}
*ppTrigger = m_pITrigger;
m_pITrigger->AddRef();
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetNextRunTime(SYSTEMTIME * pstNextRun)
//
// PURPOSE: return the next time this schedule will run
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetNextRunTime(SYSTEMTIME * pstNextRun)
{
Assert(m_pITask);
return m_pITask->GetNextRunTime(pstNextRun);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetMostRecentRunTime(SYSTEMTIME * pstRecentRun)
//
// PURPOSE: return the last time this schedule ran
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetMostRecentRunTime(SYSTEMTIME * pstRecentRun)
{
Assert(m_pITask);
return m_pITask->GetMostRecentRunTime(pstRecentRun);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::EditSyncSchedule(HWND hParent,
// DWORD dwReserved)
//
// PURPOSE: Launch the propery sheets for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::EditSyncSchedule(HWND hParent,
DWORD dwReserved)
{
SCODE sc;
IProvideTaskPage * pIProvideTaskPage;
PROPSHEETHEADER PropSheetHdr;
HPROPSHEETPAGE *psp;
int iCurPage = 0;
int iNumPages = 2;
INT_PTR iRet;
BOOL fReadOnlySchedule;
BOOL fSavedItems = FALSE;
BOOL fSavedCredentials = FALSE;
WCHAR pwszScheduleName[MAX_PATH + 1];
TCHAR ptszScheduleName[MAX_PATH + 1];
DWORD dwSize = MAX_PATH;
CSelectItemsPage *pItemsPage = NULL;
#ifdef _CREDENTIALS
CCredentialsPage *pCredentialsPage = NULL;
#endif // _CREDENTIALS
CWizPage *pSchedPage = NULL;
Assert (m_HndlrQueue);
if (FAILED(sc = StartScheduler()))
{
return sc;
}
fReadOnlySchedule = m_HndlrQueue->GetCheck(IDC_AUTOREADONLY, 0);
if (!fReadOnlySchedule)
{
//AutoAdd new items if the schedule is not ReadOnly
iNumPages = 4;
}
#ifdef _CREDENTIALS
if (g_dwPlatformId == VER_PLATFORM_WIN32_NT)
{
iNumPages++;
}
#endif // #ifdef _CREDENTIALS
psp = (HPROPSHEETPAGE *) ALLOC(iNumPages*sizeof(HPROPSHEETPAGE));
if (!psp)
{
return E_OUTOFMEMORY;
}
ZeroMemory(psp,iNumPages*sizeof(HPROPSHEETPAGE));
ZeroMemory(&PropSheetHdr,sizeof(PropSheetHdr));
smMemTo(EH_Err1, pSchedPage = new CEditSchedPage(g_hmodThisDll,
this,
&psp[iCurPage]));
smMemTo(EH_Err2, pItemsPage = new CSelectItemsPage(g_hmodThisDll,
&fSavedItems,
this,
&psp[++iCurPage],
IDD_SCHEDPAGE_ITEMS));
if (!fReadOnlySchedule)
{
// Obtain the IProvideTaskPage interface from the task object.
smChkTo(EH_Err3, m_pITask->QueryInterface( IID_IProvideTaskPage,
(VOID **)&pIProvideTaskPage));
smChkTo(EH_Err4, pIProvideTaskPage->GetPage(TASKPAGE_SCHEDULE, TRUE,
&psp[++iCurPage]));
smChkTo(EH_Err4, pIProvideTaskPage->GetPage(TASKPAGE_SETTINGS, TRUE,
&psp[++iCurPage]));
}
#ifdef _CREDENTIALS
if (g_dwPlatformId == VER_PLATFORM_WIN32_NT)
{
smMemTo(EH_Err4, pCredentialsPage = new CCredentialsPage(g_hmodThisDll,
&fSavedCredentials,
this,
&psp[++iCurPage]));
}
else
{
pCredentialsPage = NULL;
}
#endif // #ifdef _CREDENTIALS
GetScheduleName(&dwSize, pwszScheduleName);
ConvertString(ptszScheduleName,pwszScheduleName, MAX_PATH);
PropSheetHdr.dwSize = sizeof(PROPSHEETHEADER);
PropSheetHdr.dwFlags = PSH_DEFAULT;
PropSheetHdr.hwndParent = hParent;
PropSheetHdr.hInstance = NULL;
PropSheetHdr.pszCaption = ptszScheduleName;
PropSheetHdr.phpage = psp;
PropSheetHdr.nPages = iNumPages;
PropSheetHdr.nStartPage = 0;
iRet = PropertySheet(&PropSheetHdr);
if ((iRet > 0) && (fSavedItems || fSavedCredentials))
{
// Changes were made
sc = S_OK;
}
else if (iRet >= 0)
{
// The user hit OK or Cancel but
// nothing was changed
sc = S_FALSE;
}
else
{
// play taps...
sc = E_FAIL;
}
#ifdef _CREDENTIALS
if ( (g_dwPlatformId == VER_PLATFORM_WIN32_NT) && pCredentialsPage)
{
delete pCredentialsPage;
}
#endif // #ifdef _CREDENTIALS
EH_Err4:
if (!fReadOnlySchedule)
{
pIProvideTaskPage->Release();
}
EH_Err3:
delete pItemsPage;
EH_Err2:
delete pSchedPage;
EH_Err1:
FREE(psp);
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::AddItem(LPSYNC_HANDLER_ITEM_INFO pHandlerItemInfo);
//
// PURPOSE: Add a handler item to the schedule
//
// History: 27-Feb-98 susia Created.
// 9-Oct-98 susia Added delay loading of handler
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::AddItem(LPSYNC_HANDLER_ITEM_INFO pHandlerItemInfo)
{
SCODE sc = NOERROR;
if (!pHandlerItemInfo)
{
return E_INVALIDARG;
}
sc = m_HndlrQueue->AddHandlerItem(pHandlerItemInfo);
//if the handler is not yet loaded, just write through to the registry
if (sc == SYNCMGR_E_HANDLER_NOT_LOADED)
{
sc = CacheItemCheckState(pHandlerItemInfo->handlerID,
pHandlerItemInfo->itemID,
pHandlerItemInfo->dwCheckState);
}
return sc;
}
STDMETHODIMP CSyncSchedule::RegisterItems( REFCLSID pHandlerID,
SYNCMGRITEMID *pItemID)
{
//eliminated because unused and overly complicated
return E_NOTIMPL;
}
STDMETHODIMP CSyncSchedule::UnregisterItems( REFCLSID pHandlerID,
SYNCMGRITEMID *pItemID)
{
//eliminated because unused and overly complicated
return E_NOTIMPL;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::SetItemCheck(REFGUID pHandlerID,
// SYNCMGRITEMID *pItemID, DWORD dwCheckState)
//
// PURPOSE: Set the Item CheckState
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::SetItemCheck(REFCLSID pHandlerID,
SYNCMGRITEMID *pItemID, DWORD dwCheckState)
{
SCODE sc = NOERROR;
if ((!pItemID) || (pHandlerID == GUID_NULL))
{
return E_INVALIDARG;
}
sc = m_HndlrQueue->SetItemCheck(pHandlerID,pItemID, dwCheckState);
if (sc == SYNCMGR_E_HANDLER_NOT_LOADED)
{
sc = CacheItemCheckState(pHandlerID,
*pItemID,
dwCheckState);
}
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetItemCheck(REFCLSID pHandlerID,
// SYNCMGRITEMID *pItemID, DWORD *pdwCheckState);
//
// PURPOSE: Set the Item CheckState
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetItemCheck(REFCLSID pHandlerID,
SYNCMGRITEMID *pItemID, DWORD *pdwCheckState)
{
SCODE sc = NOERROR;
if ((!pItemID) || (pHandlerID == GUID_NULL) || (!pdwCheckState))
{
return E_INVALIDARG;
}
sc = m_HndlrQueue->GetItemCheck(pHandlerID, pItemID, pdwCheckState);
if (sc == SYNCMGR_E_HANDLER_NOT_LOADED)
{
TCHAR pszConnectionName[RAS_MaxEntryName + 1];
ConvertString(pszConnectionName, m_pwszConnectionName,ARRAY_SIZE(pszConnectionName));
//if we fail setting this in the registry, ignore it and move on.
// we will lose this item settings.
RegGetSyncItemSettings(SYNCTYPE_SCHEDULED,
pHandlerID,
*pItemID,
pszConnectionName,
pdwCheckState,
FALSE,
m_ptstrGUIDName);
//Now check if there have been any changes to the check state
sc = RetreiveCachedItemCheckState(pHandlerID,
*pItemID,
pdwCheckState);
}
return sc;
}
//+------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::Save()
//
// PURPOSE: CSyncSchedule save, commits the sync schedule.
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::Save()
{
SCODE sc = NOERROR;
TRACE("CSyncSchedule::Save()\r\n");
TCHAR ptszConnectionName[RAS_MaxEntryName + 1];
TCHAR ptszScheduleName[MAX_PATH + 1];
TCHAR ptszFriendlyName[MAX_PATH + 1];
WCHAR *pwszScheduleName;
Assert(m_pITask);
//protect the Save path in a mutex
CMutex CMutexSchedule(NULL, FALSE,SZ_SCHEDULEMUTEXNAME);
CMutexSchedule.Enter();
//See if this schedule name has been used
ConvertString(ptszFriendlyName, m_pwszFriendlyName, MAX_PATH);
lstrcpy(ptszScheduleName, m_ptstrGUIDName);
if (IsFriendlyNameInUse(ptszScheduleName, ptszFriendlyName))
{
//make sure it is in use by this schedule
if (0 != lstrcmp(ptszScheduleName, m_ptstrGUIDName))
{
CMutexSchedule.Leave();
return SYNCMGR_E_NAME_IN_USE;
}
}
//Save the schedule to a file
IPersistFile *pIPersistFile;
if (FAILED(sc = m_pITask->QueryInterface(IID_IPersistFile, (VOID **)&pIPersistFile)))
{
CMutexSchedule.Leave();
return sc;
}
//Save the settings for this schedule in the registry
// todo: ADD code to back out the reg writing if for
// some reason TS fails.
ConvertString(ptszConnectionName, m_pwszConnectionName,ARRAY_SIZE(ptszConnectionName));
if (m_HndlrQueue)
{
sc = m_HndlrQueue->CommitSchedSyncChanges(m_ptstrGUIDName,
ptszFriendlyName,
ptszConnectionName,
m_dwConnType,
m_fCleanReg);
}
//if we never loaded the handler, then save the cached info to the reg.
WriteOutAndPurgeCache();
RegRegisterForScheduledTasks(TRUE);
if ((FAILED(sc) || FAILED(sc = pIPersistFile->Save(NULL, FALSE))))
{
pIPersistFile->Release();
// if failed save clear out the registry.
RegRemoveScheduledTask(m_ptstrGUIDName);
CMutexSchedule.Leave();
return sc;
}
//Now set the file attributes to hidden so we won't show up in the normal TS UI.
if (FAILED(sc = pIPersistFile->GetCurFile(&pwszScheduleName)))
{
pIPersistFile->Release();
CMutexSchedule.Leave();
return sc;
}
pIPersistFile->Release();
if (!SetFileAttributes(pwszScheduleName, FILE_ATTRIBUTE_HIDDEN))
{
CMutexSchedule.Leave();
return GetLastError();
}
CoTaskMemFree(pwszScheduleName);
CMutexSchedule.Leave();
return sc;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::EnumItems(REFGUID pHandlerID,
// IEnumSyncItems **ppEnumItems)
//
// PURPOSE: Enumerate the handler items on this sync schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::EnumItems(REFGUID pHandlerID,
IEnumSyncItems **ppEnumItems)
{
SCODE sc = S_OK;
if (!ppEnumItems)
{
return E_INVALIDARG;
}
if (pHandlerID != GUID_NULL)
{
if (FAILED(sc = LoadOneHandler(pHandlerID)))
{
return sc;
}
}
else if (FAILED(sc = LoadAllHandlers()))
{
return sc;
}
*ppEnumItems = new CEnumSyncItems(pHandlerID, m_HndlrQueue);
if (*ppEnumItems)
{
return S_OK;
}
return E_OUTOFMEMORY;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetITask(ITask ** ppITask)
//
// PURPOSE: Return the ITask interface for this schedule
//
// Notes: We really should have this private.
//
// History: 15-Mar-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetITask(ITask ** ppITask)
{
Assert(m_pITask);
*ppITask = m_pITask;
m_pITask->AddRef();
return S_OK;
}
//--------------------------------------------------------------------------------
//
// member: CSyncSchedule::GetHandlerInfo, private
//
// PURPOSE: returns handler infor for the item. Used so can display UI,
//
//
// History: 11-Aug-98 rogerg Created.
//
//-------------------------------------------------------------------------------
STDMETHODIMP CSyncSchedule::GetHandlerInfo(REFCLSID pHandlerID,LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
{
HRESULT hr = E_UNEXPECTED;
LPSYNCMGRHANDLERINFO pHandlerInfo = NULL;
if (!ppSyncMgrHandlerInfo)
{
Assert(ppSyncMgrHandlerInfo);
return E_INVALIDARG;
}
if (FAILED(hr = LoadOneHandler(pHandlerID)))
{
return hr;
}
if (pHandlerInfo = (LPSYNCMGRHANDLERINFO) CoTaskMemAlloc(sizeof(SYNCMGRHANDLERINFO)))
{
hr = m_HndlrQueue->GetHandlerInfo(pHandlerID,pHandlerInfo);
}
*ppSyncMgrHandlerInfo = (NOERROR == hr) ? pHandlerInfo : NULL;
return hr;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CSyncSchedule::GetScheduleGUIDName(DWORD *pcbSize,
// LPTSTR pwszScheduleName)
//
// PURPOSE: Get the GUID name for this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CSyncSchedule::GetScheduleGUIDName(DWORD *pcbSize,
LPTSTR ptszScheduleName)
{
if (!pcbSize || !ptszScheduleName)
{
return E_INVALIDARG;
}
if (*pcbSize <= (ULONG) lstrlen(m_ptstrGUIDName))
{
*pcbSize = lstrlen(m_ptstrGUIDName) + 1;
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
lstrcpy(ptszScheduleName, m_ptstrGUIDName);
return S_OK;
}
//+------------------------------------------------------------------------------
//
// Class: CEnumSyncItems
//
// FUNCTION: CEnumSyncItems::CEnumSyncItems()
//
// PURPOSE: Constructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CEnumSyncItems::CEnumSyncItems(REFCLSID pHandlerId, CHndlrQueue *pHndlrQueue)
{
TRACE("CEnumSyncItems::CEnumSyncItems()\r\n");
++g_cRefThisDll;
Assert(pHndlrQueue);
m_HndlrQueue = pHndlrQueue;
m_HndlrQueue->AddRef();
if (pHandlerId == GUID_NULL)
{
m_fAllHandlers = TRUE;
}
else
{
m_fAllHandlers = FALSE;
}
m_HndlrQueue->GetHandlerIDFromClsid(pHandlerId, &m_wHandlerId);
m_HandlerId = pHandlerId;
m_wItemId = 0;
m_cRef = 1;
}
//+------------------------------------------------------------------------------
//
// Class: CEnumSyncItems
//
// FUNCTION: CEnumSyncItems::~CEnumSyncItems()
//
// PURPOSE: Destructor
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
CEnumSyncItems::~CEnumSyncItems()
{
--g_cRefThisDll;
Assert(0 == m_cRef);
TRACE("CEnumSyncItems::CEnumSyncItems()\r\n");
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::QueryInterface(REFIID riid, LPVOID FAR *ppv)
//
// PURPOSE: QI for the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncItems::QueryInterface(REFIID riid, LPVOID FAR *ppv)
{
*ppv = NULL;
if (IsEqualIID(riid, IID_IUnknown))
{
TRACE("CEnumSyncItems::QueryInterface()==>IID_IUknown\r\n");
*ppv = (LPUNKNOWN)this;
}
else if (IsEqualIID(riid, IID_IEnumSyncItems))
{
TRACE("CSyncScheduleMgr::QueryInterface()==>IID_IEnumSyncItems\r\n");
*ppv = (LPENUMSYNCITEMS) this;
}
if (*ppv)
{
AddRef();
return NOERROR;
}
TRACE("CEnumSyncItems::QueryInterface()==>Unknown Interface!\r\n");
return E_NOINTERFACE;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::AddRef()
//
// PURPOSE: Addref the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumSyncItems::AddRef()
{
TRACE("CEnumSyncItems::AddRef()\r\n");
m_HndlrQueue->AddRef();
return ++m_cRef;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::Release()
//
// PURPOSE: Release the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumSyncItems::Release()
{
TRACE("CEnumSyncItems::Release()\r\n");
m_HndlrQueue->Release();
if (--m_cRef)
return m_cRef;
delete this;
return 0L;
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::Next(ULONG celt,
// LPSYNC_HANDLER_ITEM_INFO rgelt,
// ULONG * pceltFetched)
//
// PURPOSE: Next handler item on this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncItems::Next(ULONG celt,
LPSYNC_HANDLER_ITEM_INFO rgelt,
ULONG * pceltFetched)
{
SCODE sc;
UINT i;
GUID handlerID;
SYNCMGRITEMID itemID;
DWORD dwCheckState;
Assert(m_HndlrQueue);
if ((0 == celt) ||
((celt > 1) && (NULL == pceltFetched)) ||
(NULL == rgelt))
{
return E_INVALIDARG;
}
if (pceltFetched)
{
*pceltFetched = 0;
}
i = 0;
while (i < celt)
{
sc = m_HndlrQueue->FindNextItemOnConnection
(NULL,m_wHandlerId,m_wItemId,
&handlerID,&itemID,&m_wHandlerId,&m_wItemId, m_fAllHandlers,
&dwCheckState);
if (sc != S_OK)
{
break;
}
rgelt[i].handlerID = handlerID;
rgelt[i].itemID = itemID;
rgelt[i].dwCheckState = dwCheckState;
m_HndlrQueue->GetItemIcon(m_wHandlerId, m_wItemId, &(rgelt[i].hIcon));
m_HndlrQueue->GetItemName(m_wHandlerId, m_wItemId, rgelt[i].wszItemName);
i++;
}
if (SUCCEEDED(sc))
{
if (pceltFetched)
{
*pceltFetched = i;
}
if (i == celt)
{
return S_OK;
}
return S_FALSE;
}
else
{
return sc;
}
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::Skip(ULONG celt)
//
// PURPOSE: Skip celt items on this schedule
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncItems::Skip(ULONG celt)
{
SCODE sc;
UINT i;
GUID handlerID;
SYNCMGRITEMID itemID;
DWORD dwCheckState;
Assert(m_HndlrQueue);
i = 0;
while (i< celt)
{
sc = m_HndlrQueue->FindNextItemOnConnection
(NULL,m_wHandlerId,m_wItemId,
&handlerID,&itemID,&m_wHandlerId,&m_wItemId, m_fAllHandlers,
&dwCheckState);
if (sc != S_OK)
{
break;
}
i++;
}
if (SUCCEEDED(sc))
{
return S_OK;
}
else
{
return sc;
}
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::Reset(void)
//
// PURPOSE: Reset the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncItems::Reset(void)
{
TRACE("CEnumSyncItems::Reset()\r\n");
m_wItemId = 0;
return m_HndlrQueue->GetHandlerIDFromClsid(m_HandlerId, &m_wHandlerId);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::Clone(IEnumSyncItems ** ppEnumSyncItems)
//
// PURPOSE: Clone the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
STDMETHODIMP CEnumSyncItems::Clone(IEnumSyncItems ** ppEnumSyncItems)
{
if (!ppEnumSyncItems)
{
return E_INVALIDARG;
}
*ppEnumSyncItems = new CEnumSyncItems(m_HandlerId, m_HndlrQueue);
if (!(*ppEnumSyncItems))
{
return E_OUTOFMEMORY;
}
return ((LPENUMSYNCITEMS) (*ppEnumSyncItems))->SetHandlerAndItem
(m_wHandlerId, m_wItemId);
}
//--------------------------------------------------------------------------------
//
// FUNCTION: CEnumSyncItems::SetHandlerAndItem(WORD wHandlerID, WORD wItemID)
//
// PURPOSE: Used when Cloning the enumerator
//
// History: 27-Feb-98 susia Created.
//
//--------------------------------------------------------------------------------
SCODE CEnumSyncItems::SetHandlerAndItem(WORD wHandlerID, WORD wItemID)
{
m_wHandlerId = wHandlerID;
m_wItemId = wItemID;
return S_OK;
}