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