windows-nt/Source/XPSP1/NT/multimedia/directx/applicationmanager/cominterface/informationmanager.cpp
2020-09-26 16:20:57 +08:00

5806 lines
170 KiB
C++

//////////////////////////////////////////////////////////////////////////////////////////////
//
// InformationManager.cpp
//
// Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
//
// Abstract :
//
// This is the implementation of CInformationManager
//
// History :
//
// 05/06/1999 luish Created
//
//////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <string.h>
#include <ntverp.h>
#include "Resource.h"
#include "ApplicationManager.h"
#include "AppPropertyRules.h"
#include "ExceptionHandler.h"
#include "Win32API.h"
#include "RegistryKey.h"
#include "Lock.h"
#include "AppManDebug.h"
#include "Global.h"
#include "StructIdentifiers.h"
#ifdef DBG_MODULE
#undef DBG_MODULE
#endif
#define DBG_MODULE DBG_INFOMAN
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns the number of elapsed minutes since October 25th 1968 (my birthday)
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD GetAgingCountInSeconds(LPAGING_INFO lpAgingInfo)
{
FUNCTION(" ::GetAgingCountInSeconds (LPSYSTEMTIME lpSystemTime)");
DWORD dwElapsedDays = 0;
DWORD dwElapsedMinutes;
DWORD dwElapsedSeconds;
dwElapsedDays += (lpAgingInfo->stLastUsedDate.wYear - 1980) * 366;
dwElapsedDays += lpAgingInfo->stLastUsedDate.wMonth * 31;
dwElapsedDays += lpAgingInfo->stLastUsedDate.wDay;
dwElapsedMinutes = (dwElapsedDays * 1440) + (lpAgingInfo->stLastUsedDate.wHour * 60) + lpAgingInfo->stLastUsedDate.wMinute;
dwElapsedSeconds = (dwElapsedMinutes * 60) + (lpAgingInfo->stLastUsedDate.wSecond);
return dwElapsedSeconds;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CInformationManager::CInformationManager(void)
{
FUNCTION("CInformationManager::CInformationManager (void)");
m_lInitializationIndex = 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CInformationManager::~CInformationManager(void)
{
FUNCTION("CInformationManager::~CInformationManager (void)");
Shutdown();
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::Initialize(void)
{
FUNCTION("CInfoMgr::Initialize ()");
HRESULT hResult = S_OK;
CLock sLock(&m_CriticalSection);
//
// Initialize the information manager if it is not already initialized
//
if (0 == InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
{
//
// Before we proceed any further we need to initialize a system wide 'critical section'
// and lock it. This ensures that any further processing past the function call is
// exclusive to this process
//
m_CriticalSection.Initialize(TRUE, "W7407540-46a4-11d2-8d53-00c04f8f8b94");
//
// Did we create the critical section. If we did, we have to initialize the data in the
// registry.
//
if (S_OK == m_CriticalSection.IsCreator())
{
//
// Well if we are the creator we should initialize the registry and be the first to
// AddRef()
//
RegInitialize();
}
//
// Everything is ready
//
InterlockedIncrement(&m_lInitializationIndex);
AddRef();
m_CriticalSection.Leave();
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::Shutdown(void)
{
FUNCTION("CInfoMgr::Shutdown ()");
m_CriticalSection.Shutdown();
InterlockedDecrement(&m_lInitializationIndex);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CInformationManager::AddRef(void)
{
FUNCTION("CInfoMgr::AddRef ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwReferenceCount, dwBufferSize, dwValueType;
sLock.Lock();
//
// By default the dwReturnCount = BAD_REFERENCE_COUNT
//
dwReferenceCount = BAD_REFERENCE_COUNT;
if (0 < InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
{
//
// Open the AppMan registry key
//
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan");
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_ALL_ACCESS);
//
// Get the current value of ReferenceCount. Make sure it is a DWORD
//
dwBufferSize = sizeof(dwReferenceCount);
sRegistryKey.GetValue(TEXT("ReferenceCount"), &dwValueType, (LPBYTE) &dwReferenceCount, &dwBufferSize);
if (REG_DWORD != dwValueType)
{
THROW(E_UNEXPECTED);
}
//
// Increment the ReferenceCount and write it to the Registry
//
dwReferenceCount++;
sRegistryKey.SetValue(TEXT("ReferenceCount"), REG_DWORD, (LPBYTE) &dwReferenceCount, dwBufferSize);
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
}
sLock.UnLock();
return (ULONG) dwReferenceCount;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CInformationManager::Release(void)
{
FUNCTION("CInfoMgr::Release ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwReferenceCount = 0, dwBufferSize, dwValueType;
HRESULT hResult = S_OK;
sLock.Lock();
//
// By default the dwReturnCount = BAD_REFERENCE_COUNT
//
dwReferenceCount = BAD_REFERENCE_COUNT;
if (0 < InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
{
//
// Open the AppMan registry key
//
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan");
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_ALL_ACCESS);
//
// Get the current value of ReferenceCount. Make sure it is a DWORD
//
dwBufferSize = sizeof(dwReferenceCount);
sRegistryKey.GetValue(TEXT("ReferenceCount"), &dwValueType, (LPBYTE) &dwReferenceCount, &dwBufferSize);
if (REG_DWORD != dwValueType)
{
THROW(E_UNEXPECTED);
}
//
// Decrement the ReferenceCount and write it to the Registry
//
if (0 < dwReferenceCount)
{
dwReferenceCount--;
sRegistryKey.SetValue(TEXT("ReferenceCount"), REG_DWORD, (LPBYTE) &dwReferenceCount, dwBufferSize);
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
}
sLock.UnLock();
return (ULONG) dwReferenceCount;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetAdvancedMode(LPDWORD lpdwAdvancedMode)
{
FUNCTION("CInfoMgr::GetAdvancedMode ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
DWORD dwType, dwSize;
HRESULT hResult = S_OK;
sLock.Lock();
//
// If we cannot create/open the root AppMan key then this is a catastrophic failure
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
//
// Get the APPLICATION_MANAGER_RECORD
//
dwSize = sizeof(APPLICATION_MANAGER_RECORD);
sRegistryKey.GetValue("Vector000", &dwType, (LPBYTE) &sApplicationManagerRecord, &dwSize);
if ((REG_BINARY != dwType)||(sizeof(APPLICATION_MANAGER_RECORD) != dwSize))
{
THROW(APPMAN_E_REGISTRYCORRUPT);
}
*lpdwAdvancedMode = sApplicationManagerRecord.dwAdvancedMode;
sRegistryKey.CloseKey();
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::SetAdvancedMode(DWORD dwAdvancedMode)
{
FUNCTION("CInfoMgr::SetAdvancedMode ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
DWORD dwType, dwSize;
sLock.Lock();
//
// If we cannot create/open the root AppMan key then this is a catastrophic failure
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_ALL_ACCESS);
//
// Get the APPLICATION_MANAGER_RECORD
//
dwSize = sizeof(APPLICATION_MANAGER_RECORD);
sRegistryKey.GetValue("Vector000", &dwType, (LPBYTE) &sApplicationManagerRecord, &dwSize);
if ((REG_BINARY != dwType)||(sizeof(APPLICATION_MANAGER_RECORD) != dwSize))
{
THROW(APPMAN_E_REGISTRYCORRUPT);
}
sApplicationManagerRecord.dwAdvancedMode = dwAdvancedMode;
sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &sApplicationManagerRecord, sizeof(APPLICATION_MANAGER_RECORD));
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetOptimalAvailableSpace(const DWORD dwApplicationCategory, LPDWORD lpdwOptimalKilobytes)
{
FUNCTION("CInfoMgr::GetOptimalAvailableSpace ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
DWORD dwDeviceIndex;
DWORD dwOptimalKilobytes;
HRESULT hResult = S_OK;
sLock.Lock();
//
// Initialize the parameter to it's default value
//
*(lpdwOptimalKilobytes) = 0;
//
// Traverse all the local drives
//
for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
GetDeviceOptimalSpaceWithIndex(dwDeviceIndex, &dwOptimalKilobytes);
//
// Consider the device space info if it does not exclude dwApplicationCategory
//
if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
{
if ((*(lpdwOptimalKilobytes)) < dwOptimalKilobytes)
{
*(lpdwOptimalKilobytes) = dwOptimalKilobytes;
}
}
}
}
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetMaximumAvailableSpace(const DWORD dwApplicationCategory, LPDWORD lpdwMaximumKilobytes)
{
FUNCTION("CInfoMgr::GetMaximumAvailableSpace ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
DWORD dwDeviceIndex;
DWORD dwMaximumKilobytes;
sLock.Lock();
//
// Initialize the parameter to it's default value
//
*(lpdwMaximumKilobytes) = 0;
//
// Traverse all the local drives
//
for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
GetDeviceMaximumSpaceWithIndex(dwDeviceIndex, &dwMaximumKilobytes);
//
// Consider the device space info if it does not exclude dwApplicationCategory
//
if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
{
if ((*(lpdwMaximumKilobytes)) < dwMaximumKilobytes)
{
*(lpdwMaximumKilobytes) = dwMaximumKilobytes;
}
}
}
}
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetSpace(const DWORD dwApplicationCategory, const DWORD dwRequiredKilobytes, LPDWORD lpdwDeviceIndex)
{
FUNCTION("CInfoMgr::GetSpace ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
DWORD dwDeviceIndex, dwTargetDeviceIndex;
DWORD dwKilobytes, dwTargetKilobytes;
HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
sLock.Lock();
//
// Initialize the startup parameters
//
*(lpdwDeviceIndex) = dwTargetDeviceIndex = 0xffffffff;
dwTargetKilobytes = 0;
//
// Get the device with the most available Kilobytes. We attempt to do this for an optimal target
//
for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
//
// Get the device information
//
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// Process devices that are not excluded
//
if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
{
GetDeviceOptimalSpaceWithIndex(dwDeviceIndex, &dwKilobytes);
if ((dwRequiredKilobytes <= dwKilobytes)&&(dwTargetKilobytes < dwKilobytes))
{
dwTargetDeviceIndex = dwDeviceIndex;
dwTargetKilobytes = dwKilobytes;
}
}
}
}
//
// If we failed to find an optimal fit, then we will go for a maximal fit
//
if (0xffffffff == dwTargetDeviceIndex)
{
for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
//
// Get the device information
//
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// Process devices that are not excluded
//
if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
{
GetDeviceMaximumSpaceWithIndex(dwDeviceIndex, &dwKilobytes);
if ((dwRequiredKilobytes <= dwKilobytes)&&(dwTargetKilobytes < dwKilobytes))
{
dwTargetDeviceIndex = dwDeviceIndex;
dwTargetKilobytes = dwKilobytes;
}
}
}
}
}
//
// Did we find a target drive ?
//
if (0xffffffff == dwTargetDeviceIndex)
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
//
// Make sure to unlock before we try and free up the space
//
sLock.UnLock();
//
// Free up the space on the target device. Make sure that FreeSpaceOnDeviceWithIndex()
// is called outside of a locking region
//
hResult = FreeSpaceOnDeviceWithIndex(dwTargetDeviceIndex, dwRequiredKilobytes);
if (SUCCEEDED(hResult))
{
//
// Record the target device to lpdwDeviceIndex
//
*(lpdwDeviceIndex) = dwTargetDeviceIndex;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::FreeSpaceOnDevice(const GUID * lpDeviceGuid, const DWORD dwRequiredKilobytes)
{
FUNCTION("CInfoMgr::FreeSpaceOnDevice ()");
DEVICE_RECORD sDeviceRecord;
HRESULT hResult;
//
// Translate the device guid into a device index
//
ZeroMemory(&sDeviceRecord, sizeof(DEVICE_RECORD));
memcpy(&(sDeviceRecord.sDeviceGuid), lpDeviceGuid, sizeof(GUID));
hResult = GetDeviceInfo(&sDeviceRecord);
if (SUCCEEDED(hResult))
{
hResult = FreeSpaceOnDeviceWithIndex(GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial), dwRequiredKilobytes);
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns the number of elapsed minutes since October 25th 1968 (my birthday)
//
//////////////////////////////////////////////////////////////////////////////////////////////
//STDMETHODIMP_(DWORD) CInformationManager::GetApplicationAge(LPAPPLICATION_DATA lpApplicationData)
//{
// FUNCTION("CInfoMgr::GetApplicationAge ()");
//
// return GetAgingCount(lpApplicationData);
//}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::CheckApplicationExistance(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::CheckApplicationExistance ()");
CLock sLock(&m_CriticalSection);
HRESULT hResult = S_FALSE;
DWORD dwApplicationIndex;
APPLICATION_DATA sApplicationData;
sLock.Lock();
dwApplicationIndex = 0;
while ((S_FALSE == hResult)&&(SUCCEEDED(GetApplicationDataWithIndex(dwApplicationIndex, &sApplicationData))))
{
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
if (0 == memcmp((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID)))
{
hResult = S_OK;
}
}
else
{
if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
{
if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], MAX_PATH_CHARCOUNT+1))
{
if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], sApplicationData.wszStringProperty[APP_STRING_SIGNATURE], MAX_PATH_CHARCOUNT+1))
{
hResult = S_OK;
}
}
}
else
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
dwApplicationIndex++;
}
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
BOOL CInformationManager::IsApplicationPinned(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::IsApplicationPinned ()");
CLock sLock(&m_CriticalSection);
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationData;
DWORD dwIndex;
BOOL fResult = FALSE;
//
// Lock the information manager to prevent other processes from using it
//
sLock.Lock();
//
// First we make sure the root path is not pinned itself
//
fResult = lpApplicationData->sBaseInfo.dwPinState;
//
// Lock this application and all of it's parents
//
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex = 0;
while ((FALSE == fResult)&&(S_OK == EnumAssociations(dwIndex, &sAssociationData)))
{
if (0 == memcmp((LPVOID) &(sAssociationData.sParentGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// We have found an association parented by lpApplicationData
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sChildGuid), sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(GetApplicationData(&sApplicationData)))
{
fResult = IsApplicationPinned(&sApplicationData);
}
}
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex++;
}
//
// Now that we are done, unlock the Information Manager
//
sLock.UnLock();
return fResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::IsInstanceGuidStillAlive(const GUID * lpGuid)
{
FUNCTION("CInfoMgr::IsInstanceGuidStillAlive ()");
CLock sLock(&m_CriticalSection);
HANDLE hMutex;
CHAR szString[MAX_PATH];
HRESULT hResult = S_OK;
sLock.Lock();
//
// Create a named mutex
//
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", lpGuid->Data1, lpGuid->Data2, lpGuid->Data3, lpGuid->Data4[0], lpGuid->Data4[1], lpGuid->Data4[2], lpGuid->Data4[3], lpGuid->Data4[4], lpGuid->Data4[5], lpGuid->Data4[6], lpGuid->Data4[7]);
hMutex = CreateMutex(NULL, FALSE, szString);
if (NULL == hMutex)
{
THROW(E_UNEXPECTED);
}
//
// Did we create the mutex
//
if (ERROR_ALREADY_EXISTS == GetLastError())
{
//
// If we get WAIT_TIMEOUT then the thread is still alive
// If we get WAIT_OBJECT_0 then the thread is the current one using this function
// If we get WAIT_ABANDONNED then the thread died
//
switch (WaitForSingleObject(hMutex, 0))
{
case WAIT_TIMEOUT
: hResult = S_OK;
break;
case WAIT_OBJECT_0
: hResult = S_OK;
break;
case WAIT_ABANDONED
: hResult = S_FALSE;
break;
}
}
else
{
//
// We created the mutex. This means that instance is no longer alive
//
hResult = S_FALSE;
}
//
// Close the mutex handle
//
CloseHandle(hMutex);
//
// Now that we are done, unlock the Information Manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::IsApplicationLocked(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::IsApplicationLocked ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
GUID sEncryptedGuid;
CHAR szString[40];
HRESULT hResult;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Open the AppMan\\Lock registry entry
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
//
// What would be the encrypted guid for this application. This value will be used as the
// Value Name of the registry entry
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Is the application already locked
//
hResult = sRegistryKey.CheckForExistingValue(szString);
if (S_OK == hResult)
{
LOCK_INFO sLockInfo;
DWORD dwDataType, dwDataLen;
//
// Well the application is locked, but is the lock still valid, let's check
//
dwDataLen = sizeof(sLockInfo);
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo))||(S_FALSE == IsInstanceGuidStillAlive(&sLockInfo.guidInstanceGuid)))
{
//
// The lock is invalid
//
if (S_OK == sRegistryKey.CheckForExistingValue(szString))
{
sRegistryKey.DeleteValue(szString);
}
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
hResult = S_FALSE;
}
}
//
// Close the registry
//
sRegistryKey.CloseKey();
//
// Unlock the information manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::LockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::LockApplicationData ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
LOCK_INFO sLockInfo;
GUID sEncryptedGuid;
DWORD dwIndex, dwDataType, dwDataLen;
CHAR szGuid[40];
HRESULT hResult = S_OK;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Open the AppMan\\Lock registry entry
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
//
// What would be the encrypted guid for this application. This value will be used as the
// Value Name of the registry entry
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Is the application already locked
//
if (S_OK == IsApplicationLocked(lpApplicationData))
{
//
// Get the lock info for this application
//
dwDataLen = sizeof(sLockInfo);
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
//
// Make sure the data that we have retrieved makes sense
//
if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo)))
{
//
// The registry entry isnt very good.
//
sRegistryKey.DeleteValue(szGuid);
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
}
//
// Handle depending on reentry case or wait state
//
if (0 == memcmp((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID)))
{
//
// Reentry case
//
sLockInfo.dwLockCount++;
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
}
else
{
DWORD dwStartTime;
//
// Other instance has the object locked. We have to wait for lock to go away
//
dwStartTime = GetTickCount();
sLock.UnLock();
hResult = APPMAN_E_OBJECTLOCKED;
dwIndex = 0;
do
{
//
// Give the lock owner thread a chance to relinquish the lock
//
Sleep(100);
if (S_FALSE == IsApplicationLocked(lpApplicationData))
{
hResult = S_OK;
}
//
// Each time we increment dwIndex, 1/10 of a second went by.
//
dwIndex++;
//
// Did we run out of time
//
if (10000 > (GetTickCount() - dwStartTime))
{
THROW(APPMAN_E_APPLICATIONALREADYLOCKED);
}
}
while (FAILED(hResult));
}
}
else
{
//
// There is no lock on this object
//
sLockInfo.dwSize = sizeof(sLockInfo);
sLockInfo.dwStructId = LOCK_STRUCT;
sLockInfo.dwLockCount = 1;
memcpy((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID));
//
// Write out the new lock info to the registry
//
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
}
//
// Close the registry key
//
sRegistryKey.CloseKey();
//
// Make sure the information manager unlocked
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnlockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::UnlockApplicationData ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
LOCK_INFO sLockInfo;
DWORD dwDataType, dwDataLen;
GUID sEncryptedGuid;
CHAR szGuid[40];
HRESULT hResult = S_OK;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Open the AppMan\\Lock registry entry
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
//
// What would be the encrypted guid for this application. This value will be used as the
// Value Name of the registry entry
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Is the application already locked
//
if (S_OK == IsApplicationLocked(lpApplicationData))
{
//
// Get the lock info for this application
//
dwDataLen = sizeof(sLockInfo);
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
//
// Make sure the data that we have retrieved makes sense
//
if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo)))
{
//
// The registry entry isnt very good.
//
sRegistryKey.DeleteValue(szGuid);
}
else
{
//
// Make sure that we do own this lock
//
if (0 == memcmp((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID)))
{
sLockInfo.dwLockCount--;
if (0 == sLockInfo.dwLockCount)
{
//
// The lock is over. Delete the registry entry
//
sRegistryKey.DeleteValue(szGuid);
}
else
{
//
// We still own the lock. Write out the new registry information with the updated
// lock count
//
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
}
}
}
}
//
// Close the registry key
//
sRegistryKey.CloseKey();
//
// Make sure the information manager unlocked
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ForceUnlockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::UnlockApplicationData ()");
CLock sLock(&m_CriticalSection);
HRESULT hResult = S_OK;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Is the application already locked
//
if (S_OK == IsApplicationLocked(lpApplicationData))
{
CRegistryKey sRegistryKey;
GUID sEncryptedGuid;
CHAR szString[MAX_PATH];
LOCK_INFO sLockInfo;
DWORD dwDataType, dwDataLen;
//
// Open the AppMan\\Lock registry entry
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
//
// What would be the encrypted guid for this application. This value will be used as the
// Value Name of the registry entry
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Well the application is locked, but do we own the lock ?
//
dwDataLen = sizeof(sLockInfo);
ZeroMemory(&sLockInfo, sizeof(sLockInfo));
sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
if (0 == memcmp(&sLockInfo.guidInstanceGuid, lpInstanceGuid, sizeof(GUID)))
{
//
// We own the lock so let's kill it
//
sRegistryKey.DeleteValue(szString);
}
//
// Close the registry key
//
sRegistryKey.CloseKey();
}
//
// Make sure the information manager unlocked
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::LockApplicationData(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::LockApplicationData ()");
GUID sZeroGuid;
ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
return LockApplicationData(lpApplicationData, &sZeroGuid);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnlockApplicationData(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::UnlockApplicationData ()");
GUID sZeroGuid;
ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
return UnlockApplicationData(lpApplicationData, &sZeroGuid);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::LockParentApplications(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::LockParentApplications ()");
CLock sLock(&m_CriticalSection);
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationData;
DWORD dwIndex;
HRESULT hResult = S_OK;
//
// Lock the information manager to prevent other processes from using it
//
sLock.Lock();
//
// Lock this application and all of it's parents
//
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationData))
{
if (0 == memcmp((LPVOID) &(sAssociationData.sChildGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// We have found a parent application. There can only be one parent per application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sParentGuid), sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(GetApplicationData(&sApplicationData)))
{
hResult = LockParentApplications(&sApplicationData, lpInstanceGuid);
}
}
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex++;
}
//
// If everything is going ok, lock this applications
//
if (SUCCEEDED(hResult))
{
hResult = LockApplicationData(lpApplicationData, lpInstanceGuid);
}
//
// Now that we are done, unlock the Information Manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnlockParentApplications(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::UnlockParentApplications ()");
CLock sLock(&m_CriticalSection);
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationData;
DWORD dwIndex;
HRESULT hResult = S_OK;
//
// Lock the information manager to prevent other processes from using it
//
sLock.Lock();
//
// Unlock this application and all of it's parents
//
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationData))
{
if (0 == memcmp((LPVOID) &(sAssociationData.sChildGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// We have found a parent application. There can only be one parent per application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sParentGuid), sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(GetApplicationData(&sApplicationData)))
{
hResult = UnlockParentApplications(&sApplicationData, lpInstanceGuid);
}
}
ZeroMemory(&sAssociationData, sizeof(sAssociationData));
dwIndex++;
}
//
// If everything is going ok, lock this applications
//
if (SUCCEEDED(hResult))
{
hResult = UnlockApplicationData(lpApplicationData, lpInstanceGuid);
}
//
// Now that we are done, unlock the Information Manager
//
sLock.Lock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::LockParentApplications(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::LockParentApplications ()");
GUID sZeroGuid;
ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
return LockParentApplications(lpApplicationData, &sZeroGuid);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnlockParentApplications(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::UnlockParentApplications ()");
GUID sZeroGuid;
ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
return UnlockParentApplications(lpApplicationData, &sZeroGuid);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::AddApplicationData(LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::AddApplicationData ()");
CLock sLock(&m_CriticalSection);
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Make sure the SIGNATURE and COMPANYNAME properties are set
//
if ((S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))||(S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Does the application already exist
//
if (S_OK == CheckApplicationExistance(lpApplicationData))
{
THROW(APPMAN_E_APPLICATIONALREADYEXISTS);
}
//
// Assign a new GUID to the application record
//
if (FAILED(CoCreateGuid(&(lpApplicationData->sBaseInfo.sApplicationGuid))))
{
THROW(E_UNEXPECTED);
}
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, lpApplicationData);
//
// Set the application record
//
SetApplicationData(lpApplicationData, lpInstanceGuid);
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RemoveApplicationData(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::RemoveApplicationData ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
APPLICATION_DATA sApplicationData;
CHAR szString[MAX_PATH_CHARCOUNT];
GUID sEncryptedGuid;
BOOL fEraseSetupRoot = TRUE;
DWORD dwIndex;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// In order to remove an application, we must have DATA_FIELD_GUID validated
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Does the application already exist
//
if (S_OK == CheckApplicationExistance(lpApplicationData))
{
//
// Make sure we have a fully populated application object
//
if (SUCCEEDED(GetApplicationData(lpApplicationData)))
{
ASSOCIATION_INFO sAssociationInfo;
//
// Remove related associations from system
//
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
{
RemoveAssociation(&sAssociationInfo);
}
else if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
{
RemoveAssociation(&sAssociationInfo);
}
dwIndex++;
}
//
// Delete the application record
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
{
sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
}
//
// Find out if any other applications are using this directory
//
dwIndex = 0;
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if (0 == wcscmp(sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
fEraseSetupRoot = FALSE;
}
dwIndex++;
}
//
// Delete the setup root directory.
//
if (fEraseSetupRoot)
{
if (FAILED(DeleteDirectoryTree(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH])))
{
RegFutureDirectoryCleanup(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]);
}
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
}
}
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetApplicationDataWithIndex(const DWORD dwApplicationIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::GetApplicationDataWithIndex ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
CWin32API sWin32API;
CRegistryKey sRegistryKey;
CHAR szString[MAX_PATH_CHARCOUNT+1];
DWORD dwIndex, dwTargetIndex;
DWORD dwValueType, dwValueLen;
DWORD dwStringLen, dwStringIndex;
HRESULT hResult = S_OK;
BOOL fRemoveApp = FALSE;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// First we need to open the application root key
//
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications");
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_READ);
//
// Because of the way the registry works, we have to start enumerating keys with
// a starting index of 0 and increment constantly until we get to the desired index
//
dwTargetIndex = dwApplicationIndex;
dwIndex = 0;
while ((dwIndex <= dwTargetIndex)&&(SUCCEEDED(hResult)))
{
dwStringLen = sizeof(szString);
if (S_OK == sRegistryKey.EnumKeys(dwIndex, szString, &dwStringLen))
{
ZeroMemory(lpApplicationData, sizeof(APPLICATION_DATA));
if (!StringToGuidA(szString, &lpApplicationData->sBaseInfo.sApplicationGuid))
{
dwTargetIndex++;
}
}
else
{
hResult = APPMAN_E_INVALIDINDEX;
}
dwIndex++;
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
//
// Did we find a candidate application
//
if (SUCCEEDED(hResult))
{
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (S_FALSE == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Open the application registry key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_READ);
//
// Read in the binary data
//
dwValueLen = sizeof(lpApplicationData->sBaseInfo);
sRegistryKey.GetValue("Vector000", &dwValueType, (LPBYTE) &lpApplicationData->sBaseInfo, &dwValueLen);
if (sizeof(lpApplicationData->sBaseInfo) != dwValueLen)
{
THROW(E_UNEXPECTED);
}
dwValueLen = sizeof(lpApplicationData->sAgingInfo);
sRegistryKey.GetValue("Vector001", &dwValueType, (LPBYTE) &lpApplicationData->sAgingInfo, &dwValueLen);
if (sizeof(lpApplicationData->sAgingInfo) != dwValueLen)
{
THROW(E_UNEXPECTED);
}
dwValueLen = sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]);
sRegistryKey.GetValue("Vector002", &dwValueType, (LPBYTE) lpApplicationData->wszStringProperty[APP_STRING_CRYPTO], &dwValueLen);
if (sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]) != dwValueLen)
{
THROW(E_UNEXPECTED);
}
//
// Read in the string data
//
for (dwIndex = 0; dwIndex < PROPERTY_COUNT; dwIndex++)
{
//
// If the property is set, is it a string ?
//
if ((S_OK == IsApplicationPropertyInitializedWithIndex(dwIndex, lpApplicationData))&&(APP_STRING_NONE != gPropertyInfo[dwIndex].dwStringId))
{
//
// Get the encrypted string from the registry
//
sprintf(szString, "Vector%03x", gPropertyInfo[dwIndex].dwStringId + 2);
dwValueLen = (MAX_PATH_CHARCOUNT+1)*2;
sRegistryKey.GetValue(szString, &dwValueType, (LPBYTE) lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId], &dwValueLen);
//
// Decrypt the string
//
for (dwStringIndex = 0; dwStringIndex < MAX_PATH_CHARCOUNT+1; dwStringIndex++)
{
lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringIndex] ^= lpApplicationData->wszStringProperty[APP_STRING_CRYPTO][dwStringIndex];
}
}
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
//
// Compensate for a changing device index (i.e. problem with SCSI pluggins)
//
ZeroMemory(&sDeviceRecord, sizeof(sDeviceRecord));
memcpy(&sDeviceRecord.sDeviceGuid, &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID));
GetDeviceInfo(&sDeviceRecord);
//
// Get the device index of the device using the volume serial passed in
//
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_EXECUTECMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_EXECUTECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
}
//
// If the application is in a ready state and the setup root path is gone, this is not so bad
//
if (APP_STATE_READY == lpApplicationData->sBaseInfo.dwState)
{
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
{
fRemoveApp = TRUE;
}
}
}
else
{
if ((APP_STATE_DOWNSIZING | APP_STATE_DOWNSIZED | APP_STATE_REINSTALLING | APP_STATE_UNINSTALLING | APP_STATE_SELFTESTING) && lpApplicationData->sBaseInfo.dwState)
{
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
fRemoveApp = TRUE;
}
}
}
//
// Should we remove the application
//
if (fRemoveApp)
{
ASSOCIATION_INFO sAssociationInfo;
//
// Well there's no sense in keeping the application lying around since both of it's root paths
// are gone. Let's delete the record
//
EncryptGuid(&lpApplicationData->sBaseInfo.sApplicationGuid);
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
{
sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
}
//
// Remove related associations from system
//
DecryptGuid(&lpApplicationData->sBaseInfo.sApplicationGuid);
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
{
RemoveAssociation(&sAssociationInfo);
}
else if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
{
RemoveAssociation(&sAssociationInfo);
}
dwIndex++;
}
//
// Recursively call
//
hResult = GetApplicationDataWithIndex(dwApplicationIndex, lpApplicationData);
}
}
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetApplicationData(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::GetApplicationData ()");
CLock sLock(&m_CriticalSection);
HRESULT hResult = S_FALSE;
DWORD dwApplicationIndex;
APPLICATION_DATA sApplicationData;
assert(NULL != lpApplicationData);
sLock.Lock();
dwApplicationIndex = 0;
while ((S_FALSE == hResult)&&(SUCCEEDED(GetApplicationDataWithIndex(dwApplicationIndex, &sApplicationData))))
{
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
if (0 == memcmp((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID)))
{
memcpy((LPVOID) lpApplicationData, (LPVOID) &sApplicationData, sizeof(APPLICATION_DATA));
hResult = S_OK;
}
}
else
{
if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
{
if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], MAX_PATH_CHARCOUNT+1))
{
if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], sApplicationData.wszStringProperty[APP_STRING_SIGNATURE], MAX_PATH_CHARCOUNT+1))
{
memcpy((LPVOID) lpApplicationData, (LPVOID) &sApplicationData, sizeof(APPLICATION_DATA));
hResult = S_OK;
}
}
}
else
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
dwApplicationIndex++;
}
sLock.UnLock();
//
// Did we find the application we were looking for ?
//
if (S_FALSE == hResult)
{
hResult = APPMAN_E_UNKNOWNAPPLICATION;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::SetApplicationData(LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::SetApplicationData ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
GUID sApplicationGuid;
CHAR szString[MAX_PATH_CHARCOUNT+1];
DWORD dwStringLen, dwIndex;
WCHAR wszEncryptedString[MAX_PATH_CHARCOUNT+1];
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Record the instance guid
//
if (NULL != lpInstanceGuid)
{
memcpy(&lpApplicationData->sBaseInfo.sInstanceGuid, lpInstanceGuid, sizeof(GUID));
}
else
{
ZeroMemory(&lpApplicationData->sBaseInfo.sInstanceGuid, sizeof(GUID));
}
//
// First we need to determine how the encrypted GUID is going to look like
//
memcpy(&sApplicationGuid, &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID));
EncryptGuid(&sApplicationGuid);
//
// Now that we have the encrypted GUID, we need to build the root registry entry for this
// application.
//
sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sApplicationGuid.Data1, sApplicationGuid.Data2, sApplicationGuid.Data3, sApplicationGuid.Data4[0], sApplicationGuid.Data4[1], sApplicationGuid.Data4[2], sApplicationGuid.Data4[3], sApplicationGuid.Data4[4], sApplicationGuid.Data4[5], sApplicationGuid.Data4[6], sApplicationGuid.Data4[7]);
if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
{
sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
}
//
// Open the application registry key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, szString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, NULL);
//
// Write out the binary data
//
sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &lpApplicationData->sBaseInfo, sizeof(lpApplicationData->sBaseInfo));
sRegistryKey.SetValue("Vector001", REG_BINARY, (LPBYTE) &lpApplicationData->sAgingInfo, sizeof(lpApplicationData->sAgingInfo));
sRegistryKey.SetValue("Vector002", REG_BINARY, (LPBYTE) lpApplicationData->wszStringProperty[APP_STRING_CRYPTO], sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]));
//
// Write out the string data
//
for (dwIndex = 0; dwIndex < PROPERTY_COUNT; dwIndex++)
{
//
// If the property is set, is it a string ?
//
if ((S_OK == IsApplicationPropertyInitializedWithIndex(dwIndex, lpApplicationData))&&(APP_STRING_NONE != gPropertyInfo[dwIndex].dwStringId))
{
//
// First determine how many bytes we want to write out to the registry
//
ZeroMemory(wszEncryptedString, sizeof(wszEncryptedString));
dwStringLen = 0;
do
{
wszEncryptedString[dwStringLen] = lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringLen];
wszEncryptedString[dwStringLen] ^= lpApplicationData->wszStringProperty[APP_STRING_CRYPTO][dwStringLen];
dwStringLen++;
}
while (0 != lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringLen-1]);
//
// Write out the encrypted string into a binary buffer into the registry
//
sprintf(szString, "Vector%03x", gPropertyInfo[dwIndex].dwStringId + 2);
sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) wszEncryptedString, dwStringLen*2);
}
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::SetApplicationState(const LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::SetApplicationState ()");
CLock sLock(&m_CriticalSection);
APPLICATION_DATA sApplicationData;
assert(NULL != lpApplicationData);
sLock.Lock();
memcpy(&sApplicationData, lpApplicationData, sizeof(APPLICATION_DATA));
if (SUCCEEDED(GetApplicationData(&sApplicationData)))
{
sApplicationData.sBaseInfo.dwState = lpApplicationData->sBaseInfo.dwState;
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_STATE, &sApplicationData);
SetApplicationData(&sApplicationData, lpInstanceGuid);
}
else
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::AssignDeviceToApplication(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::AssignDeviceToApplication ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
assert(NULL != lpApplicationData);
sLock.Lock();
//
// Make sure that dwDeviceIndex points to a valid device
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_UNEXPECTED);
}
//
// Get the device record
//
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// Update the lpApplicationData
//
memcpy(&(lpApplicationData->sBaseInfo.sDeviceGuid), &(sDeviceRecord.sDeviceGuid), sizeof(GUID));
//
// Validate the field
//
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_DEVICEGUID, lpApplicationData);
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::DownsizeApplication(const DWORD dwRequiredKilobytes, const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::DownsizeApplication ()");
HRESULT hResult = E_FAIL;
CHAR szExeLine[MAX_PATH_CHARCOUNT];
CHAR szCmdLine[MAX_PATH_CHARCOUNT];
PROCESS_INFORMATION sProcessInformation;
assert(NULL != lpApplicationData);
//
// Make sure the application is not locked
//
if (S_FALSE == IsApplicationLocked(lpApplicationData))
{
//
// Make sure the setup root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
DisableApplication(lpApplicationData);
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Make sure the application is in a proper state
//
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
{
//
// Make sure the application is not pinned
//
if (FALSE == IsApplicationPinned(lpApplicationData))
{
//
// Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
//
ZeroMemory(szExeLine, sizeof(szExeLine));
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE]), szExeLine, sizeof(szExeLine));
}
else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
}
if (1 < StrLenA(szExeLine))
{
//
// Trigger the wait event
//
if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_DOWNSIZE)))
{
//
// Construct the downsize command line
//
sprintf(szCmdLine, "%s /action=DOWNSIZE /size=%d /guid={%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} /silent", szExeLine, dwRequiredKilobytes, lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
{
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_DOWNSIZE, 150000, 150000);
}
else
{
KillWaitEvent(lpApplicationData, WAIT_FINALIZE_DOWNSIZE);
}
}
}
}
else
{
hResult = S_OK;
}
}
}
else
{
hResult = APPMAN_E_OBJECTLOCKED;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ReInstallApplication(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::ReInstallApplication ()");
HRESULT hResult = E_FAIL;
CHAR szExeLine[MAX_PATH_CHARCOUNT];
CHAR szCmdLine[MAX_PATH_CHARCOUNT];
PROCESS_INFORMATION sProcessInformation;
assert(NULL != lpApplicationData);
//
// Make sure the application is in a proper state
//
if ((APP_STATE_READY | APP_STATE_DOWNSIZED | APP_STATE_DOWNSIZING) & lpApplicationData->sBaseInfo.dwState)
{
//
// Make sure the application root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
{
m_Win32API.CreateDirectory(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH], TRUE);
}
//
// Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
//
ZeroMemory(szExeLine, sizeof(szExeLine));
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
}
else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
}
if (1 < StrLenA(szExeLine))
{
//
// Trigger the wait event
//
if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_REINSTALL)))
{
//
// Construct the downsize command line
//
sprintf(szCmdLine, "%s /guid={%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} /action=REINSTALL", szExeLine, lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
{
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_REINSTALL, 40000, 0xffffffff);
}
else
{
KillWaitEvent(lpApplicationData, WAIT_FINALIZE_REINSTALL);
}
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnInstallApplication(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::UnInstallApplication ()");
HRESULT hResult = E_FAIL;
CHAR szExeLine[MAX_PATH_CHARCOUNT];
CHAR szCmdLine[MAX_PATH_CHARCOUNT];
PROCESS_INFORMATION sProcessInformation;
assert(NULL != lpApplicationData);
//
// Make sure the setup root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
DisableApplication(lpApplicationData);
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Are we using the APP_STRING_UNINSTALLCMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
//
ZeroMemory(szExeLine, sizeof(szExeLine));
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
}
else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
}
if (1 < StrLenA(szExeLine))
{
//
// Trigger the wait event
//
sprintf(szCmdLine, "%s /guid={%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} /action=UNINSTALL", szExeLine, lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
{
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UnInstallApplicationWait(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInformationManager::UnInstallApplicationWait (const LPAPPLICATION_DATA lpApplicationData)");
HRESULT hResult = E_FAIL;
CHAR szExeLine[MAX_PATH_CHARCOUNT];
CHAR szCmdLine[MAX_PATH_CHARCOUNT];
PROCESS_INFORMATION sProcessInformation;
assert(NULL != lpApplicationData);
//
// Make sure the setup root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
DisableApplication(lpApplicationData);
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
//
ZeroMemory(szExeLine, sizeof(szExeLine));
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
}
else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
}
if (1 < StrLenA(szExeLine))
{
//
// Trigger the wait event
//
if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_UNINSTALL)))
{
//
// Construct the downsize command line
//
sprintf(szCmdLine, "%s /guid={%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} /action=UNINSTALL", szExeLine, lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
{
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_UNINSTALL, 40000, 0xffffffff);
}
else
{
KillWaitEvent(lpApplicationData, WAIT_FINALIZE_UNINSTALL);
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::SelfTestApplication(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::SelfTestApplication ()");
HRESULT hResult = E_FAIL;
CHAR szExeLine[MAX_PATH_CHARCOUNT];
CHAR szCmdLine[MAX_PATH_CHARCOUNT];
PROCESS_INFORMATION sProcessInformation;
assert(NULL != lpApplicationData);
//
// Make sure the setup root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
DisableApplication(lpApplicationData);
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Make sure the application root path exists
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
{
THROW(E_UNEXPECTED);
}
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
{
m_Win32API.CreateDirectory(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH], TRUE);
}
//
// Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
//
ZeroMemory(szExeLine, sizeof(szExeLine));
if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE]), szExeLine, sizeof(szExeLine));
}
else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
{
m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
}
if (1 < StrLenA(szExeLine))
{
//
// Trigger the wait event
//
if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_SELFTEST)))
{
//
// Construct the downsize command line
//
sprintf(szCmdLine, "%s /guid={%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} /action=SELFTEST", szExeLine, lpApplicationData->sBaseInfo.sApplicationGuid.Data1, lpApplicationData->sBaseInfo.sApplicationGuid.Data2, lpApplicationData->sBaseInfo.sApplicationGuid.Data3, lpApplicationData->sBaseInfo.sApplicationGuid.Data4[0], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[1], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[2], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[3], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[4], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[5], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[6], lpApplicationData->sBaseInfo.sApplicationGuid.Data4[7]);
if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
{
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_SELFTEST, 40000, 0xffffffff);
}
else
{
KillWaitEvent(lpApplicationData, WAIT_FINALIZE_SELFTEST);
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RunApplication(const LPAPPLICATION_DATA lpApplicationData, const DWORD dwRunFlags, const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CInfoMgr::RunApplication ()");
HRESULT hResult = S_OK;
APPLICATION_DATA sApplicationData;
WCHAR wszParameters[MAX_PATH_CHARCOUNT];
WCHAR wszCommandLine[MAX_PATH_CHARCOUNT];
CWin32API sWin32API;
BOOL fRunning = FALSE;
PROCESS_INFORMATION sProcessInformation;
//
// Make a local copy of the application object
//
memcpy((LPVOID) &sApplicationData, (LPVOID) lpApplicationData, sizeof(sApplicationData));
hResult = GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(hResult);
}
//
// Ready the application
//
ReadyApplication(&sApplicationData);
//
// Build the command line parameters
//
ZeroMemory(wszParameters, sizeof(wszParameters));
if ((APP_PROPERTY_STR_ANSI == dwStringMask)||(APP_PROPERTY_STR_UNICODE == dwStringMask))
{
//
// Check to make sure the parameters are valid
//
if (NULL != lpData)
{
if (IsBadReadPtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (0 < dwDataLen)
{
//
// Make sure the command line parameters are converted to unicode
//
if (APP_PROPERTY_STR_ANSI == dwStringMask)
{
if (MAX_PATH_CHARCOUNT < StrLenA((LPCSTR) lpData))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
else
{
sWin32API.MultiByteToWideChar((LPCSTR) lpData, dwDataLen, wszParameters, MAX_PATH_CHARCOUNT);
}
}
else
{
if (MAX_PATH_CHARCOUNT < StrLenW((LPCWSTR) lpData))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
else
{
memcpy(wszParameters, lpData, StrLenW((LPCWSTR) lpData) * 2);
}
}
}
}
}
else
{
if (0 != dwStringMask)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
//
// Construct the command line
//
if (1 < StrLenW(wszParameters))
{
//
// Make sure the total lenght does not exceed MAX_PATH_CHARCOUNT
//
if (MAX_PATH_CHARCOUNT < (StrLenW(sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE])+StrLenW(wszParameters)))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
wcscpy(wszCommandLine, sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
wcscat(wszCommandLine, L" /AppManStarted ");
wcscat(wszCommandLine, wszParameters);
}
else
{
wcscpy(wszCommandLine, sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
wcscat(wszCommandLine, L" /AppManStarted");
}
//
// Run it
//
if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
{
fRunning = TRUE;
}
else
{
if (SUCCEEDED(SelfTestApplication(&sApplicationData)))
{
if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
{
fRunning = TRUE;
}
else
{
THROW(E_FAIL);
}
}
else
{
THROW(E_FAIL);
}
}
if (fRunning)
{
sApplicationData.sAgingInfo.dwUsageCount++;
GetLocalTime(&(sApplicationData.sAgingInfo.stLastUsedDate));
SetApplicationData(&sApplicationData, NULL);
if (APP_RUN_BLOCK & dwRunFlags)
{
do
{
//
// Make sure to prevent message pump starvation
//
MSG Message;
while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
//
// Give other threads/processes the time to do stuff
//
Sleep(100);
}
while (WAIT_TIMEOUT == WaitForSingleObject(sProcessInformation.hProcess, 0));
}
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = S_OK;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::PinApplication(const LPAPPLICATION_DATA lpApplicationData, BOOL * lpfPinState)
{
FUNCTION("CInfoMgr::PinApplication ()");
CLock sLock(&m_CriticalSection);
HRESULT hResult = E_FAIL;
APPLICATION_DATA sApplicationData;
BOOL fPinState;
//
// Lock the application manager
//
sLock.Lock();
//
// Define the target pin state
//
if (NULL == lpfPinState)
{
fPinState = FALSE;
}
else
{
if (FALSE == *lpfPinState)
{
fPinState = FALSE;
}
else
{
fPinState = TRUE;
}
}
//
// Make a local copy of the application data in order to get the latest information
//
memcpy(&sApplicationData, lpApplicationData, sizeof(APPLICATION_DATA));
if (FAILED(GetApplicationData(&sApplicationData)))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
if ((APP_STATE_READY == sApplicationData.sBaseInfo.dwState)||(APP_STATE_DOWNSIZED == sApplicationData.sBaseInfo.dwState))
{
//
// Update the application data with the new pin state
//
sApplicationData.sBaseInfo.dwPinState = fPinState;
hResult = SetApplicationData(&sApplicationData, NULL);
}
else
{
hResult = APPMAN_E_INVALIDSTATE;
}
//
// Unlock the application manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ReadyApplication(const LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::ReadyApplication ()");
ASSOCIATION_INFO sAssociationInfo;
HRESULT hResult = E_FAIL;
DWORD dwIndex;
assert(NULL != lpApplicationData);
//
// Find out if any other applications are using this directory
//
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
{
APPLICATION_DATA sApplicationData;
//
// Check to make sure the parent is in a ready state
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (FAILED(GetApplicationData(&sApplicationData)))
{
THROW(E_UNEXPECTED);
}
hResult = ReadyApplication(&sApplicationData);
if (FAILED(hResult))
{
THROW(hResult);
}
else
{
if (FAILED(GetApplicationData(&sApplicationData)))
{
THROW(E_UNEXPECTED);
}
else
{
if (sApplicationData.sBaseInfo.dwState != APP_STATE_READY)
{
THROW(APPMAN_E_PARENTAPPNOTREADY);
}
}
}
}
dwIndex++;
}
//
// Make sure the application is in a proper state
//
if (APP_STATE_READY != lpApplicationData->sBaseInfo.dwState)
{
if (SUCCEEDED(ReInstallApplication(lpApplicationData)))
{
if (FAILED(GetApplicationData(lpApplicationData)))
{
THROW(E_UNEXPECTED);
}
else
{
if (APP_STATE_READY != lpApplicationData->sBaseInfo.dwState)
{
THROW(APPMAN_E_PARENTAPPNOTREADY);
}
}
}
else
{
THROW(APPMAN_E_PARENTAPPNOTREADY);
}
}
else
{
//
// Well the application reports that it is in a ready state but is it ? Check to make sure
// the root paths exist. If both are gone, remove the application from the registry
// and throw APPMAN_E_UNKNOWNAPPLICATION. If the root path is missing, call selftest on
// the application and ready it.
//
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
{
if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
RemoveApplicationData(lpApplicationData);
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
else
{
if (FAILED(SelfTestApplication(lpApplicationData)))
{
THROW(APPMAN_E_PARENTAPPNOTREADY);
}
ReadyApplication(lpApplicationData);
}
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::DisableApplication(const LPAPPLICATION_DATA lpApplicationData)
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
HRESULT hResult;
//
// Disable this application
//
lpApplicationData->sBaseInfo.dwReservedKilobytes = 0;
lpApplicationData->sBaseInfo.dwRemovableKilobytes = 0;
lpApplicationData->sBaseInfo.dwNonRemovableKilobytes = 0;
lpApplicationData->sBaseInfo.dwState |= APP_STATE_UNSTABLE;
hResult = SetApplicationData(lpApplicationData, NULL);
//
// Disable all of the children of this application
//
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sParentGuid), sizeof(GUID)))
{
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(GetApplicationData(&sApplicationData)))
{
hResult = DisableApplication(&sApplicationData);
}
}
dwIndex++;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(DWORD) CInformationManager::GetPropertyIndex(const DWORD dwProperty)
{
FUNCTION("CInfoMgr::GetPropertyIndex ()");
DWORD dwIndex;
DWORD dwPropertyIndex;
dwIndex = 0;
dwPropertyIndex = INVALID_PROPERTY_INDEX;
while ((PROPERTY_COUNT > dwIndex)&&(INVALID_PROPERTY_INDEX == dwPropertyIndex))
{
if (gPropertyInfo[dwIndex].dwProperty == dwProperty)
{
dwPropertyIndex = dwIndex;
}
dwIndex++;
}
return dwPropertyIndex;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::IsValidApplicationProperty(const DWORD dwProperty)
{
FUNCTION("CInfoMgr::IsValidApplicationProperty ()");
HRESULT hResult = S_FALSE;
DWORD dwFilteredProperty, dwPropertyModifiers;
DWORD dwPropertyIndex;
//
// What is the base property
//
dwFilteredProperty = dwProperty & 0x0000ffff;
dwPropertyModifiers = dwProperty & 0xffff0000;
dwPropertyIndex = GetPropertyIndex(dwFilteredProperty);
if (INVALID_PROPERTY_INDEX != dwPropertyIndex)
{
if ((APP_PROPERTY_STR_ANSI == dwPropertyModifiers)||(APP_PROPERTY_STR_UNICODE == dwPropertyModifiers)||(0 == dwPropertyModifiers))
{
hResult = S_OK;
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ValidateApplicationPropertyWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::ValidateApplicationPropertyWithIndex ()");
lpApplicationData->sBaseInfo.dwLowPropertyMask |= gPropertyInfo[dwPropertyIndex].dwLowPropertyMask;
lpApplicationData->sBaseInfo.dwHighPropertyMask |= gPropertyInfo[dwPropertyIndex].dwHighPropertyMask;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::InvalidateApplicationPropertyWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::InvalidateApplicationPropertyWithIndex ()");
lpApplicationData->sBaseInfo.dwLowPropertyMask &= ~(gPropertyInfo[dwPropertyIndex].dwLowPropertyMask);
lpApplicationData->sBaseInfo.dwHighPropertyMask &= ~(gPropertyInfo[dwPropertyIndex].dwHighPropertyMask);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::IsApplicationPropertyInitializedWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::IsApplicationPropertyInitializedWithIndex ()");
HRESULT hResult = S_FALSE;
if ((lpApplicationData->sBaseInfo.dwLowPropertyMask & gPropertyInfo[dwPropertyIndex].dwLowPropertyMask)||(lpApplicationData->sBaseInfo.dwHighPropertyMask & gPropertyInfo[dwPropertyIndex].dwHighPropertyMask))
{
hResult = S_OK;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::DeleteDirectoryTree(LPCSTR lpszDirectory)
{
FUNCTION("CInfoMgr::DeleteDirectoryTree ()");
HRESULT hResult = E_FAIL;
if (m_Win32API.RemoveDirectory(lpszDirectory))
{
hResult = S_OK;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::DeleteDirectoryTree(LPCWSTR lpwszDirectory)
{
FUNCTION("CInfoMgr::DeleteDirectoryTree ()");
HRESULT hResult = E_FAIL;
CHAR szString[MAX_PATH_CHARCOUNT];
if (m_Win32API.WideCharToMultiByte(lpwszDirectory, MAX_PATH_CHARCOUNT, szString, MAX_PATH_CHARCOUNT))
{
hResult = DeleteDirectoryTree(szString);
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// The InitializeRegistry() method ensures the following things :
//
// (1) That all the required registry entries are initialized properly
// (2) That the registry entries are in synch with the backup file (if applicable)
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RegInitialize(void)
{
FUNCTION("CInfoMgr::RegInitialize ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
APPLICATION_DATA sApplicationData;
DWORD dwKeyDisposition, dwDWORD;
TEMP_SPACE_RECORD sTempSpaceRecord;
CHAR szValueName[MAX_PATH_CHARCOUNT];
WCHAR wszDirectory[MAX_PATH_CHARCOUNT];
DWORD dwIndex, dwCounter;
DWORD dwDataType, dwDataLen, dwDataValue, dwValueLen;
sLock.Lock();
//
// Open the root key
//
if (S_FALSE == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan"))
{
//
// Hum the root key doesn't exist, let's see if we can create it. Otherwise return APPMAN_E_REINSTALLDX
//
THROW(APPMAN_E_REINSTALLDX);
}
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_ALL_ACCESS);
//
// Make sure the AppMan version is the right version
//
if (S_OK == sRegistryKey.CheckForExistingValue("AppManVersion"))
{
dwDataLen = sizeof(dwDataValue);
sRegistryKey.GetValue("AppManVersion", &dwDataType, (BYTE *) &dwDataValue, &dwDataLen);
if (REG_VERSION > dwDataValue)
{
THROW(APPMAN_E_REINSTALLDX);
}
}
//
// Initialize the AppMan\ReferenceCounter value
//
dwDWORD = 0;
sRegistryKey.SetValue("ReferenceCount", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
//
// Initialize the AppMan\Version value
//
if (S_FALSE == sRegistryKey.CheckForExistingValue("AppManVersion"))
{
dwDWORD = REG_VERSION;
sRegistryKey.SetValue("AppManVersion", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
}
//
// Initialize wait event extra wait vars
//
if (S_FALSE == sRegistryKey.CheckForExistingValue("WaitEntryEventExtraTime"))
{
dwDWORD = 0;
sRegistryKey.SetValue("WaitEntryEventExtraTime", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
}
if (S_FALSE == sRegistryKey.CheckForExistingValue("WaitLeaveEventExtraTime"))
{
dwDWORD = 0;
sRegistryKey.SetValue("WaitLeaveEventExtraTime", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
}
//
// Initialize the AppMan\DefaultCacheSize
//
if (S_FALSE == sRegistryKey.CheckForExistingValue("DefaultPercentCacheSize"))
{
dwDWORD = DEFAULT_PERCENT_CACHE_SIZE;
sRegistryKey.SetValue("DefaultPercentCacheSize", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
}
//
// Insert the original APPLICATION_MANAGER_RECORD
//
if (S_FALSE == sRegistryKey.CheckForExistingValue("Vector000"))
{
APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
sApplicationManagerRecord.dwSize = sizeof(APPLICATION_MANAGER_RECORD);
sApplicationManagerRecord.dwStructId = APPLICATION_MANAGER_STRUCT;
if (FAILED(CoCreateGuid(&sApplicationManagerRecord.sSystemGuid)))
{
THROW(E_UNEXPECTED);
}
sApplicationManagerRecord.dwAdvancedMode = FALSE;
sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &sApplicationManagerRecord, sizeof(APPLICATION_MANAGER_RECORD));
}
//
// Create the AppMan\Devices key.
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Create the AppMan\Applications key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Create the AppMan\Associations key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Create the AppMan\TempAllocation key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Create the AppMan\Cleanup key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Get rid of any leftover locks
//
if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock"))
{
sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock");
}
//
// Create the AppMan\Lock key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Make sure that any leftover wait events are deleted
//
if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent"))
{
sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent");
}
//
// Create the AppMan\Lock key
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
//
// Clean up the directories if required
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", KEY_ALL_ACCESS);
dwIndex = 0;
ZeroMemory(szValueName, sizeof(szValueName));
ZeroMemory(wszDirectory, sizeof(wszDirectory));
dwValueLen = sizeof(szValueName);
dwDataLen = sizeof(wszDirectory);
while (S_OK == sRegistryKey.EnumValues(dwIndex, szValueName, &dwValueLen, &dwDataType, (LPBYTE) wszDirectory, &dwDataLen))
{
//
// Decrypt the cleanup directory
//
for (dwCounter = 0; dwCounter < (dwDataLen/2)-1; dwCounter++)
{
wszDirectory[dwCounter] ^= 0xffffffff;
}
//
// Attempt to delete the directory to be cleaned up
//
if (1 < StrLenW(wszDirectory))
{
m_Win32API.RemoveDirectory(wszDirectory);
if (!m_Win32API.FileExists(wszDirectory))
{
sRegistryKey.DeleteValue(szValueName);
}
else
{
dwIndex++;
}
}
//
// Get ready for the next loop
//
ZeroMemory(szValueName, sizeof(szValueName));
ZeroMemory(wszDirectory, sizeof(wszDirectory));
dwValueLen = sizeof(szValueName);
dwDataLen = sizeof(wszDirectory);
}
//
// Scan through each application record and make sure that none of them have
// any reserved space assigned to them
//
dwIndex = 0;
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if (0 < sApplicationData.sBaseInfo.dwReservedKilobytes)
{
sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
InvalidateApplicationPropertyWithIndex(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES, &sApplicationData);
SetApplicationData(&sApplicationData, NULL);
}
dwIndex++;
}
//
// Scan through the temporary directories and delete them
//
dwIndex = 0;
while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
{
if (FAILED(RemoveTempSpace(&sTempSpaceRecord)))
{
dwIndex++;
}
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
//
// Scan through the devices and update their information
//
ScanDevices();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RegFutureDirectoryCleanup(LPCWSTR lpwszDirectory)
{
FUNCTION("CInfoMgr::RegFutureDirectoryCleanup ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
DWORD dwDefaultValue, dwIndex;
GUID sGuid;
HRESULT hResult = E_FAIL;
CHAR szValueName[64];
WCHAR wszDirectory[MAX_PATH_CHARCOUNT+1];
sLock.Lock();
//
// Encrypt the key.
//
dwIndex = 0;
while (0 != lpwszDirectory[dwIndex])
{
wszDirectory[dwIndex] = (WCHAR)(lpwszDirectory[dwIndex] ^ 0xffffffff);
dwIndex++;
}
wszDirectory[dwIndex] = 0;
//
// Generate a unique value name for the key
//
if (FAILED(CoCreateGuid(&sGuid)))
{
THROW(E_UNEXPECTED);
}
sprintf(szValueName, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sGuid.Data1, sGuid.Data2, sGuid.Data3, sGuid.Data4[0], sGuid.Data4[1], sGuid.Data4[2], sGuid.Data4[3], sGuid.Data4[4], sGuid.Data4[5], sGuid.Data4[6], sGuid.Data4[7]);
//
// Add the directory name to the AppMan\Cleanup registry key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", KEY_ALL_ACCESS);
dwDefaultValue = 1;
sRegistryKey.SetValue(szValueName, REG_BINARY, (LPBYTE) wszDirectory, (dwIndex+1)*2);
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::InitializeWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
{
FUNCTION("CInfoMgr::InitializeWaitEvent()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
WAIT_INFO sWaitInfo;
GUID sEncryptedGuid;
CHAR szGuid[40];
DWORD dwDataType, dwDataSize;
HRESULT hResult = E_FAIL;
//
// Make sure that lpApplicationData and dwWaitEvent are valid
//
if ((NULL == lpApplicationData)||(IsBadReadPtr(lpApplicationData, sizeof(APPLICATION_DATA)))||(WAIT_EVENT_COUNT <= dwWaitEvent))
{
THROW(E_UNEXPECTED);
}
//
// Lock the information manager
//
sLock.Lock();
//
// Open the root registry key for the wait events
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
//
// Make sure we have a valid application guid within lpApplicationData
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Computer the encrypted guid for lpApplicationData
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Initialize the local sWaitEvent to Zero
//
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
//
// Is there an existing event initialized for lpApplicationGuid
//
if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
{
//
// There is already a wait event in the system. Let's check to see if the wait event
// conflicts with this one or whether or not we can just add to it.
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
//
// The registry entry is bogus, delete it
//
sRegistryKey.DeleteValue(szGuid);
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
}
}
//
// Initialize the wait event if possible
//
if (0 != sWaitInfo.dwEventCount[dwWaitEvent])
{
THROW(E_UNEXPECTED);
}
else
{
sWaitInfo.dwEventCount[dwWaitEvent] = 0xffffffff;
}
//
// Write out the event
//
sWaitInfo.dwSize = sizeof(sWaitInfo);
sWaitInfo.dwStructId = WAIT_STRUCT;
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
//
// Close the registry
//
sRegistryKey.CloseKey();
//
// unlock the information manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::EnterWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent, const GUID * lpInstanceGuid)
{
FUNCTION("CInfoMgr::EnterWaitEvent()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
WAIT_INFO sWaitInfo;
GUID sEncryptedGuid;
CHAR szGuid[40];
DWORD dwDataType, dwDataSize;
HRESULT hResult = E_FAIL;
//
// Lock the information manager
//
sLock.Lock();
//
// Open the root registry key for the wait events
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
//
// Make sure we have a valid application guid within lpApplicationData
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Computer the encrypted guid for lpApplicationData
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Initialize the local sWaitEvent to Zero
//
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
//
// Is there an existing event initialized for lpApplicationGuid
//
if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
{
//
// There is already a wait event in the system. Let's check to see if the wait event
// conflicts with this one or whether or not we can just add to it.
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
THROW(E_UNEXPECTED);
}
//
// Initialize the wait event if possible
//
if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
{
sWaitInfo.dwEventCount[dwWaitEvent] = 1;
}
else if (0 < sWaitInfo.dwEventCount[dwWaitEvent])
{
(sWaitInfo.dwEventCount[dwWaitEvent])++;
}
//
// Save the instance guid
//
if (NULL != lpInstanceGuid)
{
memcpy(&sWaitInfo.guidInstanceGuid, lpInstanceGuid, sizeof(GUID));
}
//
// Write out the event
//
sWaitInfo.dwSize = sizeof(sWaitInfo);
sWaitInfo.dwStructId = WAIT_STRUCT;
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
}
//
// Close the registry
//
sRegistryKey.CloseKey();
//
// unlock the information manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::LeaveWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
{
FUNCTION("CInfoMgr::LeaveWaitEvent()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
WAIT_INFO sWaitInfo;
GUID sEncryptedGuid;
CHAR szGuid[40];
DWORD dwDataType, dwDataSize;
HRESULT hResult = E_FAIL;
//
// Lock the information manager
//
sLock.Lock();
//
// Open the root registry key for the wait events
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
//
// Make sure we have a valid application guid within lpApplicationData
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Computer the encrypted guid for lpApplicationData
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Initialize the local sWaitEvent to Zero
//
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
//
// Is there an existing event initialized for lpApplicationGuid
//
if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
{
//
// There is already a wait event in the system. Let's check to see if the wait event
// conflicts with this one or whether or not we can just add to it.
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
THROW(E_UNEXPECTED);
}
//
// Initialize the wait event if possible
//
if ((0 < sWaitInfo.dwEventCount[dwWaitEvent])&&(0xffffffff != sWaitInfo.dwEventCount[dwWaitEvent]))
{
sWaitInfo.dwEventCount[dwWaitEvent]--;
}
//
// Write out the event
//
sWaitInfo.dwSize = sizeof(sWaitInfo);
sWaitInfo.dwStructId = WAIT_STRUCT;
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
}
//
// Close the registry
//
sRegistryKey.CloseKey();
//
// unlock the information manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::WaitForEventCompletion(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent, const DWORD dwEntryMilliseconds, const DWORD dwExitMilliseconds)
{
FUNCTION("CInfoMgr::WaitForEventCompletion()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
WAIT_INFO sWaitInfo;
GUID sEncryptedGuid;
CHAR szGuid[40];
DWORD dwStartTime;
DWORD dwDataType, dwDataSize;
DWORD dwEntryTime, dwExitTime;
BOOL fDone;
HRESULT hResult = E_FAIL;
//
// Open the root registry key for the wait events
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
//
// Make sure we have a valid application guid within lpApplicationData
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Computer the encrypted guid for lpApplicationData
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Initialize the local sWaitEvent to Zero
//
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
//
// Add bias to wait times
//
dwEntryTime = dwEntryMilliseconds + GetExtraWaitEventEntryTime();
dwExitTime = dwExitMilliseconds + GetExtraWaitEventExitTime();
//
// Wait for the event to start
//
dwStartTime = GetTickCount();
fDone = FALSE;
do
{
//
// Lock the information manager
//
sLock.Lock();
//
// Read in the event record
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
THROW(E_UNEXPECTED);
}
//
// unlock the information manager
//
sLock.UnLock();
//
// Is the event started
//
if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
{
//
// Make sure to prevent message pump starvation
//
MSG Message;
while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
//
// Give other threads/processes the time to do stuff
//
Sleep(100);
}
else if (0 <= sWaitInfo.dwEventCount[dwWaitEvent])
{
fDone = TRUE;
}
}
while ((FALSE == fDone)&&(dwEntryTime > (GetTickCount() - dwStartTime)));
if (TRUE == fDone)
{
//
// Wait for the event to end
//
dwStartTime = GetTickCount();
fDone = FALSE;
do
{
//
// Lock the information manager
//
sLock.Lock();
//
// Read in the event record
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
THROW(E_UNEXPECTED);
}
//
// Is the event over
//
if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
{
THROW(E_UNEXPECTED);
}
else if (0 == sWaitInfo.dwEventCount[dwWaitEvent])
{
fDone = TRUE;
//
// Should we delete the wait event from the registry
//
if (0 == (sWaitInfo.dwEventCount[WAIT_FINALIZE_DOWNSIZE] + sWaitInfo.dwEventCount[WAIT_FINALIZE_REINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_UNINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_SELFTEST]))
{
sRegistryKey.DeleteValue(szGuid);
}
//
// Did the owner thread die on us
//
if (S_FALSE == IsInstanceGuidStillAlive(&sWaitInfo.guidInstanceGuid))
{
if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
{
sRegistryKey.DeleteValue(szGuid);
}
}
}
//
// unlock the information manager
//
sLock.UnLock();
//
// Should we sleep ?
//
if (FALSE == fDone)
{
//
// Make sure to prevent message pump starvation
//
MSG Message;
while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
//
// Give other threads/processes the time to do stuff
//
Sleep(100);
}
}
while ((FALSE == fDone)&&(dwExitTime > (GetTickCount() - dwStartTime)));
//
// Did the event finish
//
if (TRUE == fDone)
{
hResult = S_OK;
}
}
else
{
//
// The wait event has expired unsuccessfully. We will now delete the wait event since it
// will no longer be used
//
sRegistryKey.DeleteValue(szGuid);
}
//
// Close the registry
//
sRegistryKey.CloseKey();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::KillWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
{
FUNCTION("CInfoMgr::KillWaitEvent()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
WAIT_INFO sWaitInfo;
GUID sEncryptedGuid;
CHAR szGuid[40];
DWORD dwDataType, dwDataSize;
HRESULT hResult = E_FAIL;
//
// Lock the information manager
//
sLock.Lock();
//
// Open the root registry key for the wait events
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
//
// Make sure we have a valid application guid within lpApplicationData
//
if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Computer the encrypted guid for lpApplicationData
//
memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
EncryptGuid(&sEncryptedGuid);
sprintf(szGuid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sEncryptedGuid.Data1, sEncryptedGuid.Data2, sEncryptedGuid.Data3, sEncryptedGuid.Data4[0], sEncryptedGuid.Data4[1], sEncryptedGuid.Data4[2], sEncryptedGuid.Data4[3], sEncryptedGuid.Data4[4], sEncryptedGuid.Data4[5], sEncryptedGuid.Data4[6], sEncryptedGuid.Data4[7]);
//
// Initialize the local sWaitEvent to Zero
//
ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
//
// Is there an existing event initialized for lpApplicationGuid
//
if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
{
//
// There is already a wait event in the system. Let's check to see if the wait event
// conflicts with this one or whether or not we can just add to it.
//
dwDataSize = sizeof(sWaitInfo);
sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
{
THROW(E_UNEXPECTED);
}
//
// Initialize the wait event if possible
//
if (0xffffffff != sWaitInfo.dwEventCount[dwWaitEvent])
{
THROW(E_UNEXPECTED);
}
else
{
sWaitInfo.dwEventCount[dwWaitEvent] = 0;
}
}
//
// Should we delete the event or write the update record to the registry
//
if (0 == (sWaitInfo.dwEventCount[WAIT_FINALIZE_DOWNSIZE] + sWaitInfo.dwEventCount[WAIT_FINALIZE_REINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_UNINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_SELFTEST]))
{
sRegistryKey.DeleteValue(szGuid);
}
else
{
//
// Write out the event
//
sWaitInfo.dwSize = sizeof(sWaitInfo);
sWaitInfo.dwStructId = WAIT_STRUCT;
hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
}
//
// Close the registry
//
sRegistryKey.CloseKey();
//
// unlock the information manager
//
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::CheckDeviceExistance(const DWORD dwDeviceIndex)
{
FUNCTION("CInfoMgr::CheckDeviceExistance ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
HRESULT hResult = S_FALSE;
sLock.Lock();
//
// Open the AppMan\Devices key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
//
// Add the device record to the registry
//
sprintf(szString, "[0x%08x]", dwDeviceIndex);
hResult = sRegistryKey.CheckForExistingValue(szString);
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CInformationManager::GetDeviceIndex(const DWORD dwVolumeSerial)
{
CHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwDeviceIndex, dwReturnValue, dwTempVolumeSerial;
dwDeviceIndex = 0;
dwReturnValue = 0xffffffff;
while ((0xffffffff == dwReturnValue)&&(MAX_DEVICES > dwDeviceIndex))
{
sprintf(szString, "%c:\\", dwDeviceIndex + 65);
if (DRIVE_FIXED == m_Win32API.GetDriveType(szString))
{
if (m_Win32API.IsDriveFormatted(szString))
{
if ((m_Win32API.GetVolumeInformation(szString, NULL, 0, &dwTempVolumeSerial))&&(dwVolumeSerial == dwTempVolumeSerial))
{
dwReturnValue = dwDeviceIndex;
}
}
}
dwDeviceIndex++;
}
return dwReturnValue;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::AddDeviceWithIndex(const DWORD dwDeviceIndex)
{
FUNCTION("CInfoMgr::AddDeviceIndex ()");
CLock sLock(&m_CriticalSection);
TCHAR szString[10];
DEVICE_RECORD sDeviceRecord;
sLock.Lock();
//
// Initialize the device info
//
sprintf(szString, "%c:\\", dwDeviceIndex + 65);
if (!m_Win32API.GetVolumeInformation(szString, NULL, 0, &(sDeviceRecord.sDeviceInfo.dwVolumeSerial)))
{
THROW(E_UNEXPECTED);
}
//
// create the device record
//
if (FAILED(CoCreateGuid(&(sDeviceRecord.sDeviceGuid))))
{
THROW(E_UNEXPECTED);
}
sDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
sDeviceRecord.sDeviceInfo.dwDeviceFlags = DRIVE_FIXED;
sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask = 0;
sDeviceRecord.sDeviceInfo.dwPercentCacheSize = DEFAULT_PERCENT_CACHE_SIZE;
sDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize = 100;
sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
//
// Set the device info
//
SetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RemoveDeviceWithIndex(const DWORD dwDeviceIndex)
{
FUNCTION("CInfoMgr::RemoveDeviceIndex ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
sLock.Lock();
//
// Open the AppMan\Devices key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
//
// Get the GUID of the device at dwDeviceIndex
//
sprintf(szString, "[0x%08x]", dwDeviceIndex);
if (S_OK == sRegistryKey.CheckForExistingValue(szString))
{
sRegistryKey.DeleteValue(szString);
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::UpdateDeviceInfoWithIndex(const DWORD dwDeviceIndex)
{
FUNCTION("CInfoMgr::UpdateDeviceInfoWithIndex ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
APPLICATION_DATA sApplicationData;
DWORD dwIndex;
WCHAR wszString[MAX_PATH_CHARCOUNT];
CWin32API sWin32API;
sLock.Lock();
//
// Make sure the device really exists
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_UNEXPECTED);
}
swprintf(wszString, L"%c:\\", dwDeviceIndex + 65);
if (m_Win32API.IsDriveFormatted(wszString))
{
//
// Get the device record
//
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// Initialize the sDeviceRecord
//
sDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
sDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
//
// Enumerate all of the applications on the system and verify that they do really exist
// (i.e. both setup root path and application root path are there). If the setup root
// path is missin, remove the game from the cache
//
dwIndex = 0;
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, &sApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &sApplicationData)))
{
if (FALSE == sWin32API.FileExists(sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
DisableApplication(&sApplicationData);
}
}
dwIndex++;
}
//
// Enumerate all of the applications on the system and consider those that belong
// to this device
//
dwIndex = 0;
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
//
// Is the application assigned to this device
//
if (!memcmp(&(sApplicationData.sBaseInfo.sDeviceGuid), &(sDeviceRecord.sDeviceGuid), sizeof(GUID)))
{
//
// Is the application in an installing state ?
//
if (APP_STATE_INSTALLING != sApplicationData.sBaseInfo.dwState)
{
//
// Update the device information
//
if (FALSE == sApplicationData.sBaseInfo.dwPinState)
{
sDeviceRecord.sDeviceInfo.dwRemovableKilobytes += sApplicationData.sBaseInfo.dwRemovableKilobytes;
sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes += sApplicationData.sBaseInfo.dwNonRemovableKilobytes;
}
else
{
sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes += sApplicationData.sBaseInfo.dwNonRemovableKilobytes + sApplicationData.sBaseInfo.dwRemovableKilobytes;
}
if ((0 < sApplicationData.sBaseInfo.dwReservedKilobytes)&&(S_FALSE == IsInstanceGuidStillAlive(&sApplicationData.sBaseInfo.sInstanceGuid)))
{
//
// The application has some reserved space assigned to it but it is no longer valid
//
sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
SetApplicationData(&sApplicationData, NULL);
}
sDeviceRecord.sDeviceInfo.dwReservedKilobytes += sApplicationData.sBaseInfo.dwReservedKilobytes;
}
else
{
if ((0 < sApplicationData.sBaseInfo.dwReservedKilobytes)&&(S_FALSE == IsInstanceGuidStillAlive(&sApplicationData.sBaseInfo.sInstanceGuid)))
{
//
// The application has some reserved space assigned to it but it is no longer valid
//
sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
SetApplicationData(&sApplicationData, NULL);
}
sDeviceRecord.sDeviceInfo.dwReservedKilobytes += sApplicationData.sBaseInfo.dwReservedKilobytes;
}
}
dwIndex++;
}
//
// Update the device record
//
SetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
}
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ScanDevices(void)
{
FUNCTION("CInfoMgr::ScanDevices ()");
CLock sLock(&m_CriticalSection);
HRESULT hResult;
sLock.Lock();
hResult = ScanDevices(0);
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::ScanDevices(const DWORD dwDeviceIndex)
{
FUNCTION("CInfoMgr::ScanDevices ()");
HRESULT hResult = S_OK;
if (MAX_DEVICES > dwDeviceIndex)
{
CHAR szString[MAX_PATH_CHARCOUNT];
DEVICE_RECORD sDeviceRecord;
DEVICE_RECORD sExistingDeviceRecord;
BOOL fGuidAlreadyAssigned = FALSE;
DWORD dwIndex;
ZeroMemory(&sExistingDeviceRecord, sizeof(sExistingDeviceRecord));
//
// What does the system say about the device at dwDeviceIndex
//
sprintf(szString, "%c:\\", dwDeviceIndex + 65);
if (DRIVE_FIXED == m_Win32API.GetDriveType(szString))
{
//
// Get the volume serial of the device if it is formatted
//
if (m_Win32API.IsDriveFormatted(szString))
{
//
// Initialize the existing device record
//
ZeroMemory(&(sExistingDeviceRecord.sDeviceGuid), sizeof(GUID));
sExistingDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
sExistingDeviceRecord.sDeviceInfo.dwDeviceFlags = DRIVE_FIXED;
sExistingDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask = 0;
sExistingDeviceRecord.sDeviceInfo.dwPercentCacheSize = DEFAULT_PERCENT_CACHE_SIZE;
sExistingDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize = 100;
sExistingDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
sExistingDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
sExistingDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
sExistingDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
//
// Get the volume serial information
//
m_Win32API.GetVolumeInformation(szString, NULL, 0, &sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial);
//
// Enumerate the devices recorded inside AppMan and figure out if one of them already
// has this volume serial. Record the Guid of the device for later use
//
for (dwIndex = 0; dwIndex < MAX_DEVICES; dwIndex++)
{
if (S_OK == CheckDeviceExistance(dwIndex))
{
//
// Get the existing record
//
hResult = GetDeviceInfoWithIndex(dwIndex, &sDeviceRecord);
if (FAILED(hResult))
{
THROW(E_UNEXPECTED);
}
//
// Is the currently enumerated device the target record we are looking for
//
if (sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial == sDeviceRecord.sDeviceInfo.dwVolumeSerial)
{
fGuidAlreadyAssigned = TRUE;
memcpy(&sExistingDeviceRecord, &sDeviceRecord, sizeof(sDeviceRecord));
sExistingDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
}
}
}
}
}
//
// Recursively go to the next device
//
ScanDevices(dwDeviceIndex + 1);
RemoveDeviceWithIndex(dwDeviceIndex);
if (SUCCEEDED(hResult))
{
if (0 != sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial)
{
if (TRUE == fGuidAlreadyAssigned)
{
SetDeviceInfoWithIndex(dwDeviceIndex, &sExistingDeviceRecord);
UpdateDeviceInfoWithIndex(dwDeviceIndex);
}
else
{
if (m_Win32API.IsDriveFormatted(szString))
{
AddDeviceWithIndex(dwDeviceIndex);
}
}
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetDeviceInfo(LPDEVICE_RECORD lpDeviceRecord)
{
FUNCTION("CInfoMgr::GetDeviceInfo ()");
DEVICE_RECORD sDeviceRecord;
DWORD dwDeviceIndex;
HRESULT hResult = E_FAIL;
assert(NULL != lpDeviceRecord);
//
// Enumerate all of the devices and find the one that matches
//
dwDeviceIndex = 0;
while ((FAILED(hResult))&&(MAX_DEVICES > dwDeviceIndex))
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
if (!memcmp(&(sDeviceRecord.sDeviceGuid), &(lpDeviceRecord->sDeviceGuid), sizeof(GUID)))
{
memcpy(lpDeviceRecord, &sDeviceRecord, sizeof(DEVICE_RECORD));
hResult = S_OK;
}
}
dwDeviceIndex++;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetDeviceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_RECORD lpDeviceRecord)
{
FUNCTION("CInfoMgr::GetDeviceInfoWithIndex ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwDataType, dwDataLen;
assert(NULL != lpDeviceRecord);
//
// Does the device exist
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_FAIL);
}
sLock.Lock();
//
// Open the AppMan\Devices key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
//
// Get the GUID of the device at dwDeviceIndex
//
sprintf(szString, "[0x%08x]", dwDeviceIndex);
if (S_FALSE == sRegistryKey.CheckForExistingValue(szString))
{
THROW(E_UNEXPECTED);
}
//
// Get the device info from the registry and make sure it is valid
//
dwDataLen = sizeof(DEVICE_RECORD);
sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) lpDeviceRecord, &dwDataLen);
if ((REG_BINARY != dwDataType)||(sizeof(DEVICE_RECORD) != dwDataLen))
{
THROW(E_UNEXPECTED);
}
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::SetDeviceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_RECORD lpDeviceRecord)
{
FUNCTION("CInfoMgr::SetDeviceInfoWithIndex ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TCHAR szString[MAX_PATH_CHARCOUNT];
assert(NULL != lpDeviceRecord);
sLock.Lock();
//
// Open the AppMan\Devices key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
//
// Get the GUID of the device at dwDeviceIndex
//
sprintf(szString, "[0x%08x]", dwDeviceIndex);
sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpDeviceRecord, sizeof(DEVICE_RECORD));
//
// Close sRegistryKey
//
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetDeviceSpaceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_SPACE_INFO lpDeviceSpaceInfo)
{
FUNCTION("CInfoMgr::GetDeviceSpaceInfoWithIndex ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
TEMP_SPACE_RECORD sTempSpaceRecord;
TCHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwTheoreticalMaximumAvailableKilobytes, dwIndex;
sLock.Lock();
//
// Make sure the device really exists
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_UNEXPECTED);
}
//
// update and retrieve the device information
//
UpdateDeviceInfoWithIndex(dwDeviceIndex);
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// How much temporary reserved space is there ?
//
lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes = 0;
lpDeviceSpaceInfo->dwTotalUsedTemporaryKilobytes = 0;
dwIndex = 0;
while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sTempSpaceRecord.sDeviceGuid, sizeof(GUID)))
{
lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes += sTempSpaceRecord.dwKilobytes;
lpDeviceSpaceInfo->dwTotalUsedTemporaryKilobytes += m_Win32API.GetDirectorySize(sTempSpaceRecord.wszDirectory);
}
dwIndex++;
}
//
// Get the basic numbers
//
sprintf(szString, "%c:\\", dwDeviceIndex + 65);
lpDeviceSpaceInfo->dwTotalKilobytes = m_Win32API.GetDriveSize(szString);
lpDeviceSpaceInfo->dwTotalFreeKilobytes = m_Win32API.GetDriveFreeSpace(szString);
lpDeviceSpaceInfo->dwCacheSizeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentCacheSize * (lpDeviceSpaceInfo->dwTotalKilobytes / 100);
lpDeviceSpaceInfo->dwMinimumFreeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize * (lpDeviceSpaceInfo->dwTotalKilobytes / 100);
lpDeviceSpaceInfo->dwTotalRemovableKilobytes = sDeviceRecord.sDeviceInfo.dwRemovableKilobytes;
lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes = sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes + sDeviceRecord.sDeviceInfo.dwReservedKilobytes + lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes;
lpDeviceSpaceInfo->dwOptimalRemovableKilobytes = lpDeviceSpaceInfo->dwTotalRemovableKilobytes >> 1;
lpDeviceSpaceInfo->dwCacheUsedKilobytes = lpDeviceSpaceInfo->dwTotalRemovableKilobytes + lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes;
//
// How many free kilobytes do we have in the cache and if not how many kilobytes are spilling over
// in the slack space
//
if (lpDeviceSpaceInfo->dwCacheSizeKilobytes > lpDeviceSpaceInfo->dwCacheUsedKilobytes)
{
lpDeviceSpaceInfo->dwCacheFreeKilobytes = min(lpDeviceSpaceInfo->dwCacheSizeKilobytes - lpDeviceSpaceInfo->dwCacheUsedKilobytes, (lpDeviceSpaceInfo->dwTotalFreeKilobytes - (sDeviceRecord.sDeviceInfo.dwReservedKilobytes + lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes)));
lpDeviceSpaceInfo->dwSlackUsedKilobytes = 0;
}
else
{
lpDeviceSpaceInfo->dwCacheFreeKilobytes = 0;
lpDeviceSpaceInfo->dwSlackUsedKilobytes = lpDeviceSpaceInfo->dwCacheUsedKilobytes - lpDeviceSpaceInfo->dwCacheSizeKilobytes;
}
//
// How big is the slack space
//
if (lpDeviceSpaceInfo->dwTotalFreeKilobytes > (lpDeviceSpaceInfo->dwMinimumFreeKilobytes + lpDeviceSpaceInfo->dwCacheFreeKilobytes))
{
lpDeviceSpaceInfo->dwSlackSizeKilobytes = lpDeviceSpaceInfo->dwSlackUsedKilobytes + lpDeviceSpaceInfo->dwTotalFreeKilobytes - (lpDeviceSpaceInfo->dwMinimumFreeKilobytes + lpDeviceSpaceInfo->dwCacheFreeKilobytes);
}
else
{
lpDeviceSpaceInfo->dwSlackSizeKilobytes = 0;
}
//
// How much free slack space do we have left over
//
if (lpDeviceSpaceInfo->dwSlackSizeKilobytes > lpDeviceSpaceInfo->dwSlackUsedKilobytes)
{
lpDeviceSpaceInfo->dwSlackFreeKilobytes = min(lpDeviceSpaceInfo->dwSlackSizeKilobytes - lpDeviceSpaceInfo->dwSlackUsedKilobytes, lpDeviceSpaceInfo->dwTotalFreeKilobytes);
}
else
{
lpDeviceSpaceInfo->dwSlackFreeKilobytes = 0;
}
//
// What is the theoretical maximum amount of kilobytes that could be made available
//
if ((lpDeviceSpaceInfo->dwCacheSizeKilobytes + lpDeviceSpaceInfo->dwSlackSizeKilobytes) < lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes )
{
dwTheoreticalMaximumAvailableKilobytes = 0;
}
else
{
dwTheoreticalMaximumAvailableKilobytes = lpDeviceSpaceInfo->dwCacheSizeKilobytes + lpDeviceSpaceInfo->dwSlackSizeKilobytes - lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes;
}
//
// Compute the final values
//
lpDeviceSpaceInfo->dwTotalUsableFreeKilobytes = lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes;
lpDeviceSpaceInfo->dwMaximumUsableKilobytes = min((lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes + lpDeviceSpaceInfo->dwTotalRemovableKilobytes), dwTheoreticalMaximumAvailableKilobytes);
lpDeviceSpaceInfo->dwOptimalUsableKilobytes = min((lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes + lpDeviceSpaceInfo->dwOptimalRemovableKilobytes), dwTheoreticalMaximumAvailableKilobytes);
lpDeviceSpaceInfo->dwTotalReservedKilobytes = sDeviceRecord.sDeviceInfo.dwReservedKilobytes;
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetDeviceOptimalSpaceWithIndex(const DWORD dwDeviceIndex, LPDWORD lpdwKilobytes)
{
FUNCTION("CInfoMgr::GetDeviceOptimalSpaceWithIndex ()");
DEVICE_SPACE_INFO sDeviceSpaceInfo;
//
// Make sure the device really exists
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_UNEXPECTED);
}
//
// update and retrieve the device information
//
GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
//
// Calculate the optimal size available
//
*lpdwKilobytes = sDeviceSpaceInfo.dwOptimalUsableKilobytes;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetDeviceMaximumSpaceWithIndex(const DWORD dwDeviceIndex, LPDWORD lpdwKilobytes)
{
FUNCTION("CInfoMgr::GetDeviceMaximumSpaceWithIndex()");
DEVICE_SPACE_INFO sDeviceSpaceInfo;
//
// Make sure the device really exists
//
if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
{
THROW(E_UNEXPECTED);
}
//
// update and retrieve the device information
//
GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
//
// Calculate the maximum size available
//
*lpdwKilobytes = sDeviceSpaceInfo.dwMaximumUsableKilobytes;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::FreeSpaceOnDeviceWithIndex(const DWORD dwDeviceIndex, const DWORD dwRequiredKilobytes)
{
FUNCTION("CInfoMgr::FreeSpaceOnDeviceWithIndex ()");
APPLICATION_DATA sApplicationData;
DEVICE_SPACE_INFO sDeviceSpaceInfo;
DWORD dwNeededKilobytes = 0;
HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
//
// Get the device space information
//
GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
//
// Check to see whether or not we even have a chance at getting the space in the first place
//
if (dwRequiredKilobytes > sDeviceSpaceInfo.dwMaximumUsableKilobytes)
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
//
// Compute the amount of Kilobytes that are needed
//
if (dwRequiredKilobytes > sDeviceSpaceInfo.dwTotalUsableFreeKilobytes)
{
dwNeededKilobytes = dwRequiredKilobytes - sDeviceSpaceInfo.dwTotalUsableFreeKilobytes;
//
// We start off with the oldest application in the system
//
if (S_OK == GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData))
{
do
{
//
// Downsize sApplicationRecord
//
if (0 < sApplicationData.sBaseInfo.dwRemovableKilobytes)
{
if (S_FALSE == IsApplicationLocked(&sApplicationData))
{
DownsizeApplication(dwNeededKilobytes, &sApplicationData);
}
}
//
// Recomputer the amount of Kilobytes needed
//
GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
if (dwRequiredKilobytes > sDeviceSpaceInfo.dwTotalUsableFreeKilobytes)
{
dwNeededKilobytes = dwRequiredKilobytes - sDeviceSpaceInfo.dwTotalUsableFreeKilobytes;
}
else
{
dwNeededKilobytes = 0;
}
}
while ((0 < dwNeededKilobytes)&&(S_OK == GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)));
}
}
//
// Did we succeed ?
//
if (0 == dwNeededKilobytes)
{
hResult = S_OK;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::FixCacheOverrun(const GUID * lpDeviceGuid, const DWORD dwExtraKilobytes)
{
FUNCTION("CInfoMgr::FixCacheOverrun()");
APPLICATION_DATA sApplicationData = {0};
DEVICE_RECORD sDeviceRecord = {0};
DEVICE_SPACE_INFO sDeviceSpaceInfo = {0};
DWORD dwDeviceIndex;
DWORD dwNeededKilobytes, dwCacheUsedKilobytes, dwCacheSizeKilobytes;
HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
//
// Enumerate all of the devices and find the one that matches
//
dwDeviceIndex = 0;
while ((FAILED(hResult))&&(MAX_DEVICES > dwDeviceIndex))
{
if (S_OK == CheckDeviceExistance(dwDeviceIndex))
{
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
if (!memcmp(&(sDeviceRecord.sDeviceGuid), lpDeviceGuid, sizeof(GUID)))
{
hResult = S_OK;
break;
}
}
dwDeviceIndex++;
}
if (SUCCEEDED(hResult))
{
//
// Get the device space information
//
hResult = GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
if (SUCCEEDED(hResult))
{
//
// What is the maximum possible cache size ?
//
dwCacheSizeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentCacheSize * (sDeviceSpaceInfo.dwTotalKilobytes / 100);
dwCacheUsedKilobytes = sDeviceSpaceInfo.dwCacheUsedKilobytes + dwExtraKilobytes;
//
// Check to see whether or not we even have a chance at getting the space in the first place
//
if (dwCacheUsedKilobytes > dwCacheSizeKilobytes)
{
//
// How many kilobytes do we need to free up on the device
//
dwNeededKilobytes = dwCacheUsedKilobytes - dwCacheSizeKilobytes;
//
// By default, we set the hResult value prior to calling GetOldest...
//
hResult = APPMAN_E_CACHEOVERRUN;
//
// We start off with the oldest application in the system
//
if (S_OK == GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData))
{
do
{
//
// Downsize sApplicationRecord
//
if (0 < sApplicationData.sBaseInfo.dwRemovableKilobytes)
{
if (S_FALSE == IsApplicationLocked(&sApplicationData))
{
DownsizeApplication(dwNeededKilobytes, &sApplicationData);
}
}
//
// Recomputer the amount of Kilobytes needed
//
hResult = GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
if (FAILED(hResult))
{
THROW(hResult);
}
//
// Now that we have downsized a title, how many used kilobytes are there in
// the cache
//
dwCacheUsedKilobytes = sDeviceSpaceInfo.dwCacheUsedKilobytes + dwExtraKilobytes;
//
// Should we keep going
//
if (dwCacheUsedKilobytes <= dwCacheSizeKilobytes)
{
hResult = S_OK;
}
else
{
hResult = APPMAN_E_CACHEOVERRUN;
}
}
while ((FAILED(hResult))&&(S_OK == GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)));
}
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns the number of elapsed minutes since October 25th 1968 (my birthday)
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CInformationManager::GetAgingCount(LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::GetAgingCount ()");
APPLICATION_DATA sChildData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
DWORD dwElapsedSeconds, dwChildElapsedSeconds;
dwElapsedSeconds = GetAgingCountInSeconds(&lpApplicationData->sAgingInfo);
dwChildElapsedSeconds = 0;
dwIndex = 0;
while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp(&(lpApplicationData->sBaseInfo.sApplicationGuid), &(sAssociationInfo.sParentGuid), sizeof(GUID)))
{
ZeroMemory(&sChildData, sizeof(sChildData));
memcpy(&(sChildData.sBaseInfo.sApplicationGuid), &(sAssociationInfo.sChildGuid), sizeof(GUID));
ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sChildData);
if (FAILED(GetApplicationData(&sChildData)))
{
THROW(E_UNEXPECTED);
}
dwChildElapsedSeconds = GetAgingCount(&sChildData);
if (dwChildElapsedSeconds >= dwElapsedSeconds)
{
dwElapsedSeconds = dwChildElapsedSeconds + 1;
}
}
dwIndex++;
}
OutputDebugString(MakeString("App %s %s is %d seconds old", lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], dwElapsedSeconds));
return dwElapsedSeconds;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetOldestApplicationDataByDeviceWithIndex(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::GetOldestApplicationDataByDeviceWithIndex ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
APPLICATION_DATA sApplicationData;
DWORD dwIndex;
HRESULT hResult = E_FAIL;
sLock.Lock();
//
// Get the device information
//
if (FAILED(GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord)))
{
THROW(APPMAN_E_INVALIDINDEX);
}
//
// By default, lpApplicationRecord will represent the first viable application
//
dwIndex = 0;
do
{
hResult = GetApplicationDataWithIndex(dwIndex, lpApplicationData);
dwIndex++;
if (SUCCEEDED(hResult))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID)))
{
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
{
break;
}
}
}
}
while (SUCCEEDED(hResult));
//
// If we have a viable initial application record, we move on to try and find the oldest one
//
if (SUCCEEDED(hResult))
{
//
// Now we enumerate the remaining application and figure out which one is the oldest
//
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
{
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
{
if (GetAgingCount(&sApplicationData) < GetAgingCount(lpApplicationData))
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
else
{
if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
{
//
// Both applications have the same aging count. We use the application guid as a bias to decide
// which of the two apps is actually older
//
if (0 < memcmp(&(lpApplicationData->sBaseInfo.sApplicationGuid), &(sApplicationData.sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
}
}
}
}
dwIndex++;
}
}
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::GetNextOldestApplicationDataByDeviceWithIndex(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
{
FUNCTION("CInfoMgr::GetNextOldestApplicationDataByDeviceWithIndex ()");
CLock sLock(&m_CriticalSection);
DEVICE_RECORD sDeviceRecord;
APPLICATION_DATA sApplicationData;
DWORD dwOriginalAgeInSeconds;
GUID sOriginalApplicationGuid;
DWORD dwIndex;
HRESULT hResult = E_FAIL;
sLock.Lock();
//
// Save the original information
//
dwOriginalAgeInSeconds = GetAgingCount(lpApplicationData);
memcpy(&sOriginalApplicationGuid, &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
//
// Get the device information
//
if (FAILED(GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord)))
{
THROW(APPMAN_E_INVALIDINDEX);
}
//
// By default, lpApplicationRecord will represent the first viable application
//
dwIndex = 0;
do
{
hResult = GetApplicationDataWithIndex(dwIndex, lpApplicationData);
dwIndex++;
if (SUCCEEDED(hResult))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID)))
{
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
{
break;
}
}
}
}
while (SUCCEEDED(hResult));
//
// First we need to find the newest application
//
if (SUCCEEDED(hResult))
{
//
// Now we enumerate the remaining application and figure out which one is the newest
//
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
{
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
{
if (GetAgingCount(&sApplicationData) > GetAgingCount(lpApplicationData))
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
else
{
if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
{
//
// Both applications have the same aging count. We use the application guid as a bias to decide
// which of the two apps is actually older
//
if (0 < memcmp(&(sApplicationData.sBaseInfo.sApplicationGuid), &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
}
}
}
}
dwIndex++;
}
//
// Ok we have the newest application represented by lpApplicationRecor. Now we go looking
// for the Oldest app that is newer that dwOriginalAgeInSeconds
//
dwIndex = 0;
while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
{
if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
{
if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
{
//
// Is sApplicationRecord older than lpApplicationRecord
//
if (GetAgingCount(&sApplicationData) < GetAgingCount(lpApplicationData))
{
//
// Is sApplicationRecord newer than sAgingInfo
//
if (GetAgingCount(&sApplicationData) > dwOriginalAgeInSeconds)
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
else
{
if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
{
//
// Both applications have the same aging count. We use the application guid as a bias to decide
// which of the two apps is actually older
//
if (0 < memcmp(&(sApplicationData.sBaseInfo.sApplicationGuid), &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
}
}
}
}
}
}
dwIndex++;
}
}
//
// Check to make sure that lpApplicationRecord represents a valid application record
//
if (SUCCEEDED(hResult))
{
//
// Ok now we need to check and make sure that the outgoing lpApplicationRecord is not identical
// to the incoming one (i.e. in the case where we only have a single app in system, this will
// occur
//
if (!memcmp(&sOriginalApplicationGuid, &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
ZeroMemory(lpApplicationData, sizeof(APPLICATION_DATA));
hResult = E_FAIL;
}
else
{
hResult = S_OK;
}
}
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::AddTempSpace(LPTEMP_SPACE_RECORD lpTempSpaceRecord)
{
FUNCTION("CInfoMgr::AddTempSpace ()");
CLock sLock(&m_CriticalSection);
DWORD dwDeviceIndex;
HRESULT hResult;
CWin32API Win32API;
DEVICE_RECORD sDeviceRecord;
CRegistryKey sRegistryKey;
CHAR szString[MAX_PATH_CHARCOUNT];
hResult = GetSpace(0, lpTempSpaceRecord->dwKilobytes, &dwDeviceIndex);
if (SUCCEEDED(hResult))
{
sLock.Lock();
//
// update and retrieve the device information
//
UpdateDeviceInfoWithIndex(dwDeviceIndex);
GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
//
// Fill in the TEMP_SPACE_RECORD var
//
if (FAILED(CoCreateGuid(&lpTempSpaceRecord->sGuid)))
{
THROW(E_UNEXPECTED);
}
memcpy((LPVOID) &lpTempSpaceRecord->sDeviceGuid, (LPVOID) &sDeviceRecord.sDeviceGuid, sizeof(GUID));
swprintf(lpTempSpaceRecord->wszDirectory, L"%c:\\Temp\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", dwDeviceIndex + 65, lpTempSpaceRecord->sGuid.Data1, lpTempSpaceRecord->sGuid.Data2, lpTempSpaceRecord->sGuid.Data3, lpTempSpaceRecord->sGuid.Data4[0], lpTempSpaceRecord->sGuid.Data4[1], lpTempSpaceRecord->sGuid.Data4[2], lpTempSpaceRecord->sGuid.Data4[3], lpTempSpaceRecord->sGuid.Data4[4], lpTempSpaceRecord->sGuid.Data4[5], lpTempSpaceRecord->sGuid.Data4[6], lpTempSpaceRecord->sGuid.Data4[7]);
//
// Add the entry to the registry
//
sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, NULL);
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", lpTempSpaceRecord->sGuid.Data1, lpTempSpaceRecord->sGuid.Data2, lpTempSpaceRecord->sGuid.Data3, lpTempSpaceRecord->sGuid.Data4[0], lpTempSpaceRecord->sGuid.Data4[1], lpTempSpaceRecord->sGuid.Data4[2], lpTempSpaceRecord->sGuid.Data4[3], lpTempSpaceRecord->sGuid.Data4[4], lpTempSpaceRecord->sGuid.Data4[5], lpTempSpaceRecord->sGuid.Data4[6], lpTempSpaceRecord->sGuid.Data4[7]);
sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpTempSpaceRecord, sizeof(TEMP_SPACE_RECORD));
//
// Create the directory
//
Win32API.CreateDirectory(lpTempSpaceRecord->wszDirectory, FALSE);
sLock.UnLock();
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RemoveTempSpace(LPTEMP_SPACE_RECORD lpTempSpaceRecord)
{
FUNCTION("CInfoMgr::RemoveTempSpace ()");
CLock sLock(&m_CriticalSection);
TEMP_SPACE_RECORD sTempSpaceRecord;
DWORD dwIndex;
HRESULT hResult = E_FAIL;
CWin32API Win32API;
CRegistryKey sRegistryKey;
CHAR szString[MAX_PATH_CHARCOUNT];
BOOL fRemoved;
sLock.Lock();
//
// First we need to find the matching entry (based on path and sApplicationGuid)
//
fRemoved = FALSE;
dwIndex = 0;
while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
{
//
// Does the enumerated temp space belong to the current application
//
if (0 == memcmp((LPVOID) &sTempSpaceRecord.sApplicationGuid, (LPVOID) &lpTempSpaceRecord->sApplicationGuid, sizeof(GUID)))
{
//
// Does the enumerated temp space have the same directory
//
if (0 == _wcsnicmp(sTempSpaceRecord.wszDirectory, lpTempSpaceRecord->wszDirectory, MAX_PATH_CHARCOUNT))
{
//
// This is the winner. Let's wack it
//
//
// Delete the directory
//
if (FAILED(DeleteDirectoryTree(sTempSpaceRecord.wszDirectory)))
{
RegFutureDirectoryCleanup(sTempSpaceRecord.wszDirectory);
}
//
// Remove the entry from the registry
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", KEY_ALL_ACCESS);
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sTempSpaceRecord.sGuid.Data1, sTempSpaceRecord.sGuid.Data2, sTempSpaceRecord.sGuid.Data3, sTempSpaceRecord.sGuid.Data4[0], sTempSpaceRecord.sGuid.Data4[1], sTempSpaceRecord.sGuid.Data4[2], sTempSpaceRecord.sGuid.Data4[3], sTempSpaceRecord.sGuid.Data4[4], sTempSpaceRecord.sGuid.Data4[5], sTempSpaceRecord.sGuid.Data4[6], sTempSpaceRecord.sGuid.Data4[7]);
hResult = sRegistryKey.DeleteValue(szString);
fRemoved = TRUE;
}
}
dwIndex++;
}
sLock.UnLock();
//
// Did we actually find the matching temp space entry and remove it ?
//
if (FALSE == fRemoved)
{
hResult = APPMAN_E_INVALIDDATA;
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::EnumTempSpace(const DWORD dwIndex, LPTEMP_SPACE_RECORD lpTempSpaceRecord)
{
FUNCTION("CInfoMgr::EnumTempSpace ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
TEMP_SPACE_RECORD sTempSpaceRecord;
HRESULT hResult = S_OK;
DWORD dwLoopIndex, dwTargetIndex, dwStringLen, dwSize, dwType;
CHAR szString[MAX_PATH_CHARCOUNT];
sLock.Lock();
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", KEY_READ);
//
// Because of the way the registry works, we have to start enumerating keys with
// a starting index of 0 and increment constantly until we get to the desired index
//
dwTargetIndex = dwIndex;
dwLoopIndex = 0;
while ((dwLoopIndex <= dwTargetIndex)&&(S_OK == hResult))
{
dwStringLen = MAX_PATH_CHARCOUNT;
dwSize = sizeof(sTempSpaceRecord);
hResult = sRegistryKey.EnumValues(dwLoopIndex, szString, &dwStringLen, &dwType, (LPBYTE) &sTempSpaceRecord, &dwSize);
if (S_OK == hResult)
{
if (dwSize != sizeof(sTempSpaceRecord))
{
dwTargetIndex++;
}
}
dwLoopIndex++;
}
if (S_OK == hResult)
{
memcpy((LPVOID) lpTempSpaceRecord, (LPVOID) &sTempSpaceRecord, sizeof(TEMP_SPACE_RECORD));
}
else
{
hResult = APPMAN_E_INVALIDINDEX;
}
sRegistryKey.CloseKey();
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::AddAssociation(LPASSOCIATION_INFO lpAssociationInfo)
{
FUNCTION("CInfoMgr::AddAssociation ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
CHAR szString[MAX_PATH_CHARCOUNT];
GUID sAssociationGuid;
sLock.Lock();
//
// Open the root registry key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
//
// Assign a GUID to the association
//
if (FAILED(CoCreateGuid(&sAssociationGuid)))
{
THROW(E_UNEXPECTED);
}
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", sAssociationGuid.Data1, sAssociationGuid.Data2, sAssociationGuid.Data3, sAssociationGuid.Data4[0], sAssociationGuid.Data4[1], sAssociationGuid.Data4[2], sAssociationGuid.Data4[3], sAssociationGuid.Data4[4], sAssociationGuid.Data4[5], sAssociationGuid.Data4[6], sAssociationGuid.Data4[7]);
sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpAssociationInfo, sizeof(ASSOCIATION_INFO));
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::RemoveAssociation(LPASSOCIATION_INFO lpAssociationInfo)
{
FUNCTION("CInfoMgr::RemoveAssociation ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
ASSOCIATION_INFO sAssociationInfo;
CHAR szString[MAX_PATH_CHARCOUNT];
DWORD dwIndex, dwValueNameLen, dwDataType, dwDataLen;
sLock.Lock();
//
// Open the root registry key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
//
// Enumerate all of the associations and find the matching one
//
dwIndex = 0;
dwDataLen = sizeof(ASSOCIATION_INFO);
dwValueNameLen = MAX_PATH_CHARCOUNT;
while (S_OK == sRegistryKey.EnumValues(dwIndex, szString, &dwValueNameLen, &dwDataType, (LPBYTE) &sAssociationInfo, &dwDataLen))
{
//
// Did we find the match
//
if (!memcmp(&sAssociationInfo, lpAssociationInfo, sizeof(ASSOCIATION_INFO)))
{
sRegistryKey.DeleteValue(szString);
break;
}
dwIndex++;
dwDataLen = sizeof(ASSOCIATION_INFO);
dwValueNameLen = MAX_PATH_CHARCOUNT;
}
sRegistryKey.CloseKey();
sLock.UnLock();
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CInformationManager::EnumAssociations(const DWORD dwTargetIndex, LPASSOCIATION_INFO lpAssociationInfo)
{
FUNCTION("CInfoMgr::EnumAssociations ()");
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
ASSOCIATION_INFO sAssociationInfo;
CHAR szString[MAX_PATH_CHARCOUNT];
HRESULT hResult;
DWORD dwIndex, dwValueNameLen, dwDataType, dwDataLen;
sLock.Lock();
//
// Open the root registry key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
//
// Enumerate all of the associations and find the matching one
//
dwIndex = 0;
do
{
dwDataLen = sizeof(ASSOCIATION_INFO);
dwValueNameLen = MAX_PATH_CHARCOUNT;
hResult = sRegistryKey.EnumValues(dwIndex, szString, &dwValueNameLen, &dwDataType, (LPBYTE) &sAssociationInfo, &dwDataLen);
dwIndex++;
}
while ((dwIndex <= dwTargetIndex)&&(S_OK == hResult));
//
// Did the while loop terminate because we read in our target entry ?
//
if (S_OK == hResult)
{
memcpy((LPVOID) lpAssociationInfo, (LPVOID) &sAssociationInfo, sizeof(ASSOCIATION_INFO));
}
else
{
hResult = APPMAN_E_INVALIDINDEX;
}
sRegistryKey.CloseKey();
sLock.UnLock();
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns the number of extra milliseconds that AppMan should wait for an Entry event
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CInformationManager::GetExtraWaitEventEntryTime(void)
{
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
DWORD dwType, dwSize;
DWORD dwWaitTime = 0;
sLock.Lock();
//
// Open the root AppMan key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
dwSize = sizeof(dwWaitTime);
sRegistryKey.GetValue("WaitEntryEventExtraTime", &dwType, (BYTE *) &dwWaitTime, &dwSize);
sRegistryKey.CloseKey();
sLock.UnLock();
return dwWaitTime;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns the number of extra milliseconds that AppMan should wait for a Leave event
//
//////////////////////////////////////////////////////////////////////////////////////////////
DWORD CInformationManager::GetExtraWaitEventExitTime(void)
{
CLock sLock(&m_CriticalSection);
CRegistryKey sRegistryKey;
DWORD dwType, dwSize;
DWORD dwWaitTime = 0;
sLock.Lock();
//
// Open the root AppMan key
//
sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
dwSize = sizeof(dwWaitTime);
sRegistryKey.GetValue("WaitLeaveEventExtraTime", &dwType, (BYTE *) &dwWaitTime, &dwSize);
sRegistryKey.CloseKey();
sLock.UnLock();
return dwWaitTime;
}