|
|
//////////////////////////////////////////////////////////////////////////////////////////////
//
// 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; }
|