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