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.
734 lines
21 KiB
734 lines
21 KiB
/**********************************************************************/
|
|
/** Microsoft Passport **/
|
|
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
ppnotificationthread.cpp
|
|
implement the methods runing a separte thread watching for registry
|
|
changes, and timer for CCD refresh
|
|
|
|
|
|
FILE HISTORY:
|
|
|
|
*/
|
|
#include "precomp.h"
|
|
|
|
PassportLockedInteger PpNotificationThread::m_NextHandle;
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
|
|
PpNotificationThread::PpNotificationThread()
|
|
{
|
|
LocalConfigurationUpdated();
|
|
|
|
AddLocalConfigClient(dynamic_cast<IConfigurationUpdate*>(this), NULL);
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
|
|
|
|
PpNotificationThread::~PpNotificationThread()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Add a CCD client to the notification list.
|
|
//
|
|
|
|
HRESULT
|
|
PpNotificationThread::AddCCDClient(
|
|
tstring& strCCDName,
|
|
ICCDUpdate* piUpdate,
|
|
HANDLE* phClientHandle)
|
|
{
|
|
HRESULT hr;
|
|
NOTIFICATION_CLIENT clientInfo;
|
|
|
|
try
|
|
{
|
|
clientInfo.dwNotificationType = NOTIF_CCD;
|
|
clientInfo.NotificationInterface.piCCDUpdate = piUpdate;
|
|
clientInfo.strCCDName = strCCDName;
|
|
clientInfo.hClientHandle = (HANDLE)(LONG_PTR)(++m_NextHandle);
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_ClientListLock);
|
|
m_ClientList.push_back(clientInfo);
|
|
}
|
|
|
|
if(phClientHandle != NULL)
|
|
{
|
|
*phClientHandle = clientInfo.hClientHandle;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Add a configuration client to the notification list
|
|
//
|
|
|
|
HRESULT
|
|
PpNotificationThread::AddLocalConfigClient(
|
|
IConfigurationUpdate* piUpdate,
|
|
HANDLE* phClientHandle)
|
|
{
|
|
HRESULT hr;
|
|
NOTIFICATION_CLIENT clientInfo;
|
|
|
|
clientInfo.dwNotificationType = NOTIF_CONFIG;
|
|
clientInfo.NotificationInterface.piConfigUpdate = piUpdate;
|
|
clientInfo.hClientHandle = (HANDLE)(LONG_PTR)(++m_NextHandle);
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_ClientListLock);
|
|
try
|
|
{
|
|
m_ClientList.push_back(clientInfo);
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Ret;
|
|
}
|
|
}
|
|
|
|
if(phClientHandle != NULL)
|
|
{
|
|
*phClientHandle = clientInfo.hClientHandle;
|
|
}
|
|
|
|
hr = S_OK;
|
|
Ret:
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Remove a client (either type) from the notification list.
|
|
//
|
|
|
|
HRESULT
|
|
PpNotificationThread::RemoveClient(
|
|
HANDLE hClientHandle)
|
|
{
|
|
HRESULT hr;
|
|
PassportGuard<PassportLock> guard(m_ClientListLock);
|
|
|
|
for(CLIENT_LIST::iterator it = m_ClientList.begin(); it != m_ClientList.end(); it++)
|
|
{
|
|
if((*it).hClientHandle == hClientHandle)
|
|
{
|
|
m_ClientList.erase(it);
|
|
hr = S_OK;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
hr = E_FAIL;
|
|
|
|
Cleanup:
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Do a manual refresh of a CCD.
|
|
//
|
|
|
|
HRESULT
|
|
PpNotificationThread::GetCCD(
|
|
tstring& strCCDName,
|
|
IXMLDocument** ppiXMLDocument,
|
|
BOOL bForceFetch)
|
|
{
|
|
HRESULT hr;
|
|
PpShadowDocument* pShadowDoc;
|
|
CCD_INFO ccdInfo;
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_CCDInfoLock);
|
|
|
|
// Get the CCD Information for the requested CCD
|
|
if(!GetCCDInfo(strCCDName, ccdInfo))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
pShadowDoc = NULL;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Create a new shadow document for the CCD
|
|
if(ccdInfo.strCCDLocalFile.empty())
|
|
pShadowDoc = new PpShadowDocument(ccdInfo.strCCDURL);
|
|
else
|
|
pShadowDoc = new PpShadowDocument(ccdInfo.strCCDURL, ccdInfo.strCCDLocalFile);
|
|
}
|
|
|
|
if(!pShadowDoc)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the update.
|
|
hr = pShadowDoc->GetDocument(ppiXMLDocument, bForceFetch);
|
|
|
|
//BUGBUG This is weird because currently other clients of this CCD will NOT get
|
|
// notified. I don't want to loop through the notification list here for
|
|
// two reasons:
|
|
//
|
|
// 1. The caller might be in the notification list and I don't to notify
|
|
// unnecessarily.
|
|
// 2. Don't want to put the overhead of notifying all clients on the
|
|
// caller's thread.
|
|
//
|
|
// The ideal solution would be to wake up our dedicated thread and have it
|
|
// do the notification. I haven't been able to find a way to signal a
|
|
// waitable time though.
|
|
|
|
Cleanup:
|
|
|
|
if(pShadowDoc != NULL)
|
|
delete pShadowDoc;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
//
|
|
// register configure change notification
|
|
// register CCD update timeer
|
|
// call client notification sink
|
|
//
|
|
//
|
|
void
|
|
PpNotificationThread::run(void)
|
|
{
|
|
{
|
|
HANDLE* pHandleArray = NULL;
|
|
LONG lResult;
|
|
PassportEvent RegChangeEvent(FALSE,FALSE);
|
|
DWORD dwCurCCDInfo;
|
|
DWORD dwCurArrayLen;
|
|
DWORD dwWaitResult;
|
|
DWORD dwError;
|
|
CCD_INFO_LIST::iterator it;
|
|
CRegKey PassportKey;
|
|
BOOL bKeyOpened;
|
|
HRESULT hr;
|
|
|
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
|
_ASSERT(hr != S_FALSE);
|
|
|
|
lResult = PassportKey.Open(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Passport"), KEY_NOTIFY);
|
|
bKeyOpened = (lResult == ERROR_SUCCESS);
|
|
|
|
m_StartupThread.Set();
|
|
|
|
while(WaitForSingleObject(m_ShutdownThread, 0) != WAIT_OBJECT_0)
|
|
{
|
|
if(bKeyOpened)
|
|
{
|
|
lResult = RegNotifyChangeKeyValue((HKEY)PassportKey, TRUE,
|
|
REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET,
|
|
(HANDLE)RegChangeEvent,
|
|
TRUE);
|
|
if(lResult != ERROR_SUCCESS)
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_CCDInfoLock);
|
|
|
|
dwCurArrayLen = m_aciCCDInfoList.size() + 2;
|
|
|
|
pHandleArray = new HANDLE[dwCurArrayLen];
|
|
if(pHandleArray == NULL)
|
|
{
|
|
// BUGBUG Throw a low-memory alert here?
|
|
continue;
|
|
}
|
|
|
|
pHandleArray[0] = (HANDLE)m_ShutdownThread; // Handle 0 always contains the thread shutdown signal.
|
|
pHandleArray[1] = (HANDLE)RegChangeEvent; // Handle 1 always contains the registry change event.
|
|
|
|
for(it = m_aciCCDInfoList.begin(), dwCurCCDInfo = 0; it != m_aciCCDInfoList.end(); it++, dwCurCCDInfo++)
|
|
{
|
|
pHandleArray[dwCurCCDInfo + 2] = (*it).hCCDTimer;
|
|
}
|
|
}
|
|
|
|
dwWaitResult = WaitForMultipleObjects(dwCurArrayLen,
|
|
pHandleArray,
|
|
FALSE,
|
|
INFINITE);
|
|
switch(dwWaitResult)
|
|
{
|
|
case WAIT_FAILED:
|
|
|
|
dwError = GetLastError();
|
|
|
|
break;
|
|
|
|
// Thread shutdown has been signalled. Exit this thread.
|
|
case WAIT_OBJECT_0:
|
|
goto Cleanup;
|
|
|
|
// Registry change has been signalled. Notify all local config clients.
|
|
case WAIT_OBJECT_0 + 1:
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_ClientListLock);
|
|
|
|
CLIENT_LIST::iterator cl_iter;
|
|
for(cl_iter = m_ClientList.begin(); cl_iter != m_ClientList.end(); cl_iter++)
|
|
{
|
|
if((*cl_iter).dwNotificationType == NOTIF_CONFIG)
|
|
{
|
|
(*cl_iter).NotificationInterface.piConfigUpdate->LocalConfigurationUpdated();
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
// One of the CCD timers has been signalled. Read the CCD and notify all CCD clients.
|
|
default:
|
|
|
|
{
|
|
IXMLDocumentPtr xmlDoc;
|
|
PpShadowDocument ShadowDoc;
|
|
DWORD dwInfoIndex = dwWaitResult - WAIT_OBJECT_0 - 2;
|
|
|
|
//
|
|
// Due to the ugly nature of the code an allocation can fail within a constructor
|
|
// and cause AVs in this code. So unfortunately we'll wrap this code to
|
|
// account for that.
|
|
//
|
|
try
|
|
{
|
|
m_CCDInfoLock.acquire();
|
|
CCD_INFO_LIST aciTempCCDInfoList(m_aciCCDInfoList);
|
|
m_CCDInfoLock.release();
|
|
|
|
m_aciCCDInfoList[dwInfoIndex].SetTimer();
|
|
|
|
// Fetch the CCD
|
|
ShadowDoc.SetURL(aciTempCCDInfoList[dwInfoIndex].strCCDURL);
|
|
if(!aciTempCCDInfoList[dwInfoIndex].strCCDLocalFile.empty())
|
|
ShadowDoc.SetLocalFile(aciTempCCDInfoList[dwInfoIndex].strCCDLocalFile);
|
|
|
|
if(ShadowDoc.GetDocument(&xmlDoc) == S_OK)
|
|
{
|
|
PassportGuard<PassportLock> guard(m_ClientListLock);
|
|
|
|
LPCTSTR pszUpdatedName = aciTempCCDInfoList[dwInfoIndex].strCCDName.c_str();
|
|
|
|
// Loop through client list and call any clients registered for the CCD that
|
|
// changed.
|
|
CLIENT_LIST::iterator cl_iter;
|
|
for(cl_iter = m_ClientList.begin(); cl_iter != m_ClientList.end(); cl_iter++)
|
|
{
|
|
if(lstrcmpi(pszUpdatedName, (*cl_iter).strCCDName.c_str()) == 0)
|
|
{
|
|
(*cl_iter).NotificationInterface.piCCDUpdate->CCDUpdated(
|
|
pszUpdatedName,
|
|
(IXMLDocument*)xmlDoc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
if (g_pAlert)
|
|
{
|
|
g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_CCD_NOT_LOADED, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delete [] pHandleArray;
|
|
pHandleArray = NULL;
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if(pHandleArray != NULL)
|
|
delete [] pHandleArray;
|
|
|
|
CoUninitialize();
|
|
}
|
|
m_ShutdownAck.Set();
|
|
}
|
|
|
|
//
|
|
// Update our configuration. This is called from the constructor, and
|
|
// from the notification thread whenever the registry changes.
|
|
//
|
|
|
|
void
|
|
PpNotificationThread::LocalConfigurationUpdated()
|
|
{
|
|
CRegKey NexusRegKey;
|
|
LONG lResult;
|
|
DWORD dwIndex;
|
|
DWORD dwNameLen;
|
|
DWORD dwDefaultRefreshInterval;
|
|
TCHAR achNameBuf[64];
|
|
|
|
lResult = NexusRegKey.Open(HKEY_LOCAL_MACHINE,
|
|
TEXT("Software\\Microsoft\\Passport\\Nexus"),
|
|
KEY_READ);
|
|
if(lResult != ERROR_SUCCESS)
|
|
{
|
|
//BUGBUG This is a required reg key, throw an event.
|
|
return;
|
|
}
|
|
|
|
// Get the default refresh interval.
|
|
lResult = NexusRegKey.QueryDWORDValue(TEXT("CCDRefreshInterval"), dwDefaultRefreshInterval);
|
|
if(lResult != ERROR_SUCCESS)
|
|
{
|
|
//BUGBUG This is a required reg value, throw an event.
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Lock down the list.
|
|
//
|
|
|
|
{
|
|
PassportGuard<PassportLock> guard(m_CCDInfoLock);
|
|
|
|
//
|
|
// Loop through existing list and remove any items whose corresponding keys
|
|
// have been removed.
|
|
//
|
|
|
|
CCD_INFO_LIST::iterator it;
|
|
for(it = m_aciCCDInfoList.begin(); it != m_aciCCDInfoList.end(); )
|
|
{
|
|
CRegKey CCDRegKey;
|
|
|
|
lResult = CCDRegKey.Open((HKEY)NexusRegKey, (*it).strCCDName.c_str(), KEY_READ);
|
|
if(lResult != ERROR_SUCCESS)
|
|
{
|
|
it = m_aciCCDInfoList.erase(it);
|
|
}
|
|
else
|
|
it++;
|
|
}
|
|
|
|
//
|
|
// Loop through each subkey and add/update the CCD info therein.
|
|
//
|
|
|
|
dwIndex = 0;
|
|
dwNameLen = sizeof(achNameBuf) / sizeof(achNameBuf[0]);
|
|
|
|
while(RegEnumKeyEx((HKEY)NexusRegKey, dwIndex,achNameBuf, &dwNameLen, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS)
|
|
{
|
|
CRegKey CCDRegKey;
|
|
|
|
lResult = CCDRegKey.Open((HKEY)NexusRegKey, achNameBuf, KEY_READ);
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
ReadCCDInfo(tstring(achNameBuf), dwDefaultRefreshInterval, CCDRegKey);
|
|
}
|
|
|
|
dwIndex++;
|
|
dwNameLen = sizeof(achNameBuf);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// This method starts the thread and then wait for the thread to get going.
|
|
//
|
|
|
|
bool
|
|
PpNotificationThread::start(void)
|
|
{
|
|
m_StartupThread.Reset();
|
|
|
|
bool bReturn = PassportThread::start();
|
|
|
|
//
|
|
// Now wait for the thread to start.
|
|
//
|
|
|
|
WaitForSingleObject((HANDLE)m_StartupThread, INFINITE);
|
|
return bReturn;
|
|
}
|
|
|
|
//
|
|
// This method just signals the shutdown event causing the thread to terminate immediately.
|
|
//
|
|
|
|
void
|
|
PpNotificationThread::stop(void)
|
|
{
|
|
m_ShutdownThread.Set();
|
|
WaitForSingleObject(m_ShutdownAck, 1000);
|
|
// give it a chance to terminate
|
|
Sleep(20);
|
|
}
|
|
|
|
//
|
|
// Private method for reading the CCD info for a single CCD subkey from
|
|
// the registry.
|
|
//
|
|
|
|
BOOL
|
|
PpNotificationThread::ReadCCDInfo(
|
|
tstring& strCCDName,
|
|
DWORD dwDefaultRefreshInterval,
|
|
CRegKey& CCDRegKey
|
|
)
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
LONG lResult;
|
|
DWORD dwBufLen = 0;
|
|
DWORD dwType;
|
|
CCD_INFO_LIST::iterator it;
|
|
LPTSTR pszRemoteFile = NULL;
|
|
LPTSTR pszLocalFile = TEXT("");
|
|
BOOL fLocalFileAllocated = FALSE;
|
|
DWORD dwCCDRefreshInterval;
|
|
LPTSTR pszTempFile = NULL;
|
|
|
|
//
|
|
// Read in the remote path to the CCD.
|
|
// CCDRemoteFile is the only required value. If it's not there, return FALSE.
|
|
//
|
|
|
|
lResult = CCDRegKey.QueryStringValue(TEXT("CCDRemoteFile"), NULL, &dwBufLen);
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
pszRemoteFile = (LPTSTR)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, dwBufLen * sizeof(TCHAR));
|
|
if (NULL == pszRemoteFile)
|
|
{
|
|
bReturn = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
CCDRegKey.QueryStringValue(TEXT("CCDRemoteFile"), pszRemoteFile, &dwBufLen);
|
|
while(*pszRemoteFile && _istspace(*pszRemoteFile))
|
|
pszRemoteFile++;
|
|
}
|
|
else
|
|
{
|
|
bReturn = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Read in the refresh interval for this CCD.
|
|
//
|
|
|
|
lResult = CCDRegKey.QueryDWORDValue(TEXT("CCDRefreshInterval"), dwCCDRefreshInterval);
|
|
if(lResult != ERROR_SUCCESS)
|
|
dwCCDRefreshInterval = 0xFFFFFFFF;
|
|
|
|
//
|
|
// Read in local (backup) path for the CCD. This is an optional value. Use
|
|
// empty string (initialized above) as the default.
|
|
//
|
|
|
|
lResult = CCDRegKey.QueryValue(TEXT("CCDLocalFile"), &dwType, NULL, &dwBufLen);
|
|
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
pszTempFile = (LPTSTR) LocalAlloc(LMEM_FIXED, dwBufLen);
|
|
|
|
if (pszTempFile)
|
|
{
|
|
lResult = CCDRegKey.QueryValue(TEXT("CCDLocalFile"), &dwType, pszTempFile, &dwBufLen);
|
|
|
|
if (lResult == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Expand out the environment variable
|
|
//
|
|
|
|
TCHAR tszTemp;
|
|
|
|
dwBufLen = ExpandEnvironmentStrings(pszTempFile, &tszTemp, 1);
|
|
|
|
if (dwBufLen > 1)
|
|
{
|
|
DWORD dwChars;
|
|
|
|
pszLocalFile = (LPTSTR)LocalAlloc(LMEM_FIXED, dwBufLen * sizeof(TCHAR));
|
|
if (NULL == pszLocalFile)
|
|
{
|
|
bReturn = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
fLocalFileAllocated = TRUE;
|
|
}
|
|
|
|
dwChars = ExpandEnvironmentStrings(pszTempFile, pszLocalFile, dwBufLen);
|
|
|
|
if (dwChars > dwBufLen)
|
|
{
|
|
LocalFree(pszLocalFile);
|
|
fLocalFileAllocated = FALSE;
|
|
pszLocalFile = TEXT("");
|
|
}
|
|
|
|
while(*pszLocalFile && _istspace(*pszLocalFile)) pszLocalFile++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (dwType == REG_SZ)
|
|
{
|
|
pszLocalFile = (LPTSTR)LocalAlloc(LMEM_FIXED, dwBufLen * sizeof(TCHAR));
|
|
if (NULL == pszLocalFile)
|
|
{
|
|
bReturn = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
fLocalFileAllocated = TRUE;
|
|
}
|
|
|
|
if (CCDRegKey.QueryValue(TEXT("CCDLocalFile"), &dwType, pszLocalFile, &dwBufLen) != ERROR_SUCCESS)
|
|
{
|
|
LocalFree(pszLocalFile);
|
|
fLocalFileAllocated = FALSE;
|
|
pszLocalFile = TEXT("");
|
|
}
|
|
|
|
while(*pszLocalFile && _istspace(*pszLocalFile)) pszLocalFile++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this CCD is already in the list, then update it.
|
|
//
|
|
|
|
for(it = m_aciCCDInfoList.begin(); it != m_aciCCDInfoList.end(); it++)
|
|
{
|
|
if(lstrcmp((*it).strCCDName.c_str(), strCCDName.c_str()) == 0)
|
|
{
|
|
// Check to see if the information has changed.
|
|
if(lstrcmpi(pszRemoteFile, (*it).strCCDURL.c_str()) != 0 ||
|
|
lstrcmpi(pszLocalFile, (*it).strCCDLocalFile.c_str()) != 0 ||
|
|
dwCCDRefreshInterval != (*it).dwCCDRefreshInterval ||
|
|
dwDefaultRefreshInterval != (*it).dwDefaultRefreshInterval
|
|
)
|
|
{
|
|
DWORD dwOldRefreshInterval = ((*it).dwCCDRefreshInterval == 0xFFFFFFFF ?
|
|
(*it).dwDefaultRefreshInterval :
|
|
(*it).dwCCDRefreshInterval);
|
|
DWORD dwNewRefreshInterval = (dwCCDRefreshInterval == 0xFFFFFFFF ?
|
|
dwDefaultRefreshInterval :
|
|
dwCCDRefreshInterval);
|
|
|
|
(*it).strCCDURL = pszRemoteFile;
|
|
(*it).strCCDLocalFile = pszLocalFile;
|
|
(*it).dwCCDRefreshInterval = dwCCDRefreshInterval;
|
|
(*it).dwDefaultRefreshInterval = dwDefaultRefreshInterval;
|
|
|
|
if(dwOldRefreshInterval != dwNewRefreshInterval)
|
|
(*it).SetTimer();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// This is a new CCD, add it to the list.
|
|
//
|
|
|
|
if(it == m_aciCCDInfoList.end())
|
|
{
|
|
CCD_INFO ccdInfo;
|
|
|
|
ccdInfo.strCCDName = strCCDName;
|
|
ccdInfo.strCCDURL = pszRemoteFile;
|
|
ccdInfo.strCCDLocalFile = pszLocalFile;
|
|
ccdInfo.dwCCDRefreshInterval = dwCCDRefreshInterval;
|
|
ccdInfo.dwDefaultRefreshInterval = dwDefaultRefreshInterval;
|
|
|
|
ccdInfo.SetTimer();
|
|
|
|
try
|
|
{
|
|
m_aciCCDInfoList.push_back(ccdInfo);
|
|
}
|
|
catch(...)
|
|
{
|
|
bReturn = FALSE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
bReturn = TRUE;
|
|
|
|
Cleanup:
|
|
if (pszTempFile)
|
|
{
|
|
LocalFree(pszTempFile);
|
|
}
|
|
|
|
if (pszRemoteFile)
|
|
{
|
|
LocalFree(pszRemoteFile);
|
|
}
|
|
|
|
if (fLocalFileAllocated && pszLocalFile)
|
|
{
|
|
LocalFree(pszLocalFile);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
//
|
|
// Private method for retrieving a CCD_INFO structure given the CCD name.
|
|
//
|
|
|
|
BOOL
|
|
PpNotificationThread::GetCCDInfo(
|
|
tstring& strCCDName,
|
|
CCD_INFO& ccdInfo
|
|
)
|
|
{
|
|
CCD_INFO_LIST::iterator it;
|
|
|
|
for(it = m_aciCCDInfoList.begin(); it != m_aciCCDInfoList.end(); it++)
|
|
{
|
|
if(lstrcmpi((*it).strCCDName.c_str(), strCCDName.c_str()) == 0)
|
|
{
|
|
ccdInfo = (*it);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|