Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5805 lines
170 KiB

  1. //////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // InformationManager.cpp
  4. //
  5. // Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
  6. //
  7. // Abstract :
  8. //
  9. // This is the implementation of CInformationManager
  10. //
  11. // History :
  12. //
  13. // 05/06/1999 luish Created
  14. //
  15. //////////////////////////////////////////////////////////////////////////////////////////////
  16. #include <windows.h>
  17. #include <string.h>
  18. #include <ntverp.h>
  19. #include "Resource.h"
  20. #include "ApplicationManager.h"
  21. #include "AppPropertyRules.h"
  22. #include "ExceptionHandler.h"
  23. #include "Win32API.h"
  24. #include "RegistryKey.h"
  25. #include "Lock.h"
  26. #include "AppManDebug.h"
  27. #include "Global.h"
  28. #include "StructIdentifiers.h"
  29. #ifdef DBG_MODULE
  30. #undef DBG_MODULE
  31. #endif
  32. #define DBG_MODULE DBG_INFOMAN
  33. //////////////////////////////////////////////////////////////////////////////////////////////
  34. //
  35. // Returns the number of elapsed minutes since October 25th 1968 (my birthday)
  36. //
  37. //////////////////////////////////////////////////////////////////////////////////////////////
  38. DWORD GetAgingCountInSeconds(LPAGING_INFO lpAgingInfo)
  39. {
  40. FUNCTION(" ::GetAgingCountInSeconds (LPSYSTEMTIME lpSystemTime)");
  41. DWORD dwElapsedDays = 0;
  42. DWORD dwElapsedMinutes;
  43. DWORD dwElapsedSeconds;
  44. dwElapsedDays += (lpAgingInfo->stLastUsedDate.wYear - 1980) * 366;
  45. dwElapsedDays += lpAgingInfo->stLastUsedDate.wMonth * 31;
  46. dwElapsedDays += lpAgingInfo->stLastUsedDate.wDay;
  47. dwElapsedMinutes = (dwElapsedDays * 1440) + (lpAgingInfo->stLastUsedDate.wHour * 60) + lpAgingInfo->stLastUsedDate.wMinute;
  48. dwElapsedSeconds = (dwElapsedMinutes * 60) + (lpAgingInfo->stLastUsedDate.wSecond);
  49. return dwElapsedSeconds;
  50. }
  51. //////////////////////////////////////////////////////////////////////////////////////////////
  52. //
  53. //////////////////////////////////////////////////////////////////////////////////////////////
  54. CInformationManager::CInformationManager(void)
  55. {
  56. FUNCTION("CInformationManager::CInformationManager (void)");
  57. m_lInitializationIndex = 0;
  58. }
  59. //////////////////////////////////////////////////////////////////////////////////////////////
  60. //
  61. //////////////////////////////////////////////////////////////////////////////////////////////
  62. CInformationManager::~CInformationManager(void)
  63. {
  64. FUNCTION("CInformationManager::~CInformationManager (void)");
  65. Shutdown();
  66. }
  67. //////////////////////////////////////////////////////////////////////////////////////////////
  68. //
  69. //////////////////////////////////////////////////////////////////////////////////////////////
  70. STDMETHODIMP CInformationManager::Initialize(void)
  71. {
  72. FUNCTION("CInfoMgr::Initialize ()");
  73. HRESULT hResult = S_OK;
  74. CLock sLock(&m_CriticalSection);
  75. //
  76. // Initialize the information manager if it is not already initialized
  77. //
  78. if (0 == InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
  79. {
  80. //
  81. // Before we proceed any further we need to initialize a system wide 'critical section'
  82. // and lock it. This ensures that any further processing past the function call is
  83. // exclusive to this process
  84. //
  85. m_CriticalSection.Initialize(TRUE, "W7407540-46a4-11d2-8d53-00c04f8f8b94");
  86. //
  87. // Did we create the critical section. If we did, we have to initialize the data in the
  88. // registry.
  89. //
  90. if (S_OK == m_CriticalSection.IsCreator())
  91. {
  92. //
  93. // Well if we are the creator we should initialize the registry and be the first to
  94. // AddRef()
  95. //
  96. RegInitialize();
  97. }
  98. //
  99. // Everything is ready
  100. //
  101. InterlockedIncrement(&m_lInitializationIndex);
  102. AddRef();
  103. m_CriticalSection.Leave();
  104. }
  105. return hResult;
  106. }
  107. //////////////////////////////////////////////////////////////////////////////////////////////
  108. //
  109. //////////////////////////////////////////////////////////////////////////////////////////////
  110. STDMETHODIMP CInformationManager::Shutdown(void)
  111. {
  112. FUNCTION("CInfoMgr::Shutdown ()");
  113. m_CriticalSection.Shutdown();
  114. InterlockedDecrement(&m_lInitializationIndex);
  115. return S_OK;
  116. }
  117. //////////////////////////////////////////////////////////////////////////////////////////////
  118. //
  119. //////////////////////////////////////////////////////////////////////////////////////////////
  120. STDMETHODIMP_(ULONG) CInformationManager::AddRef(void)
  121. {
  122. FUNCTION("CInfoMgr::AddRef ()");
  123. CLock sLock(&m_CriticalSection);
  124. CRegistryKey sRegistryKey;
  125. TCHAR szString[MAX_PATH_CHARCOUNT];
  126. DWORD dwReferenceCount, dwBufferSize, dwValueType;
  127. sLock.Lock();
  128. //
  129. // By default the dwReturnCount = BAD_REFERENCE_COUNT
  130. //
  131. dwReferenceCount = BAD_REFERENCE_COUNT;
  132. if (0 < InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
  133. {
  134. //
  135. // Open the AppMan registry key
  136. //
  137. sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan");
  138. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_ALL_ACCESS);
  139. //
  140. // Get the current value of ReferenceCount. Make sure it is a DWORD
  141. //
  142. dwBufferSize = sizeof(dwReferenceCount);
  143. sRegistryKey.GetValue(TEXT("ReferenceCount"), &dwValueType, (LPBYTE) &dwReferenceCount, &dwBufferSize);
  144. if (REG_DWORD != dwValueType)
  145. {
  146. THROW(E_UNEXPECTED);
  147. }
  148. //
  149. // Increment the ReferenceCount and write it to the Registry
  150. //
  151. dwReferenceCount++;
  152. sRegistryKey.SetValue(TEXT("ReferenceCount"), REG_DWORD, (LPBYTE) &dwReferenceCount, dwBufferSize);
  153. //
  154. // Close sRegistryKey
  155. //
  156. sRegistryKey.CloseKey();
  157. }
  158. sLock.UnLock();
  159. return (ULONG) dwReferenceCount;
  160. }
  161. //////////////////////////////////////////////////////////////////////////////////////////////
  162. //
  163. //////////////////////////////////////////////////////////////////////////////////////////////
  164. STDMETHODIMP_(ULONG) CInformationManager::Release(void)
  165. {
  166. FUNCTION("CInfoMgr::Release ()");
  167. CLock sLock(&m_CriticalSection);
  168. CRegistryKey sRegistryKey;
  169. TCHAR szString[MAX_PATH_CHARCOUNT];
  170. DWORD dwReferenceCount = 0, dwBufferSize, dwValueType;
  171. HRESULT hResult = S_OK;
  172. sLock.Lock();
  173. //
  174. // By default the dwReturnCount = BAD_REFERENCE_COUNT
  175. //
  176. dwReferenceCount = BAD_REFERENCE_COUNT;
  177. if (0 < InterlockedExchange(&m_lInitializationIndex, m_lInitializationIndex))
  178. {
  179. //
  180. // Open the AppMan registry key
  181. //
  182. sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan");
  183. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_ALL_ACCESS);
  184. //
  185. // Get the current value of ReferenceCount. Make sure it is a DWORD
  186. //
  187. dwBufferSize = sizeof(dwReferenceCount);
  188. sRegistryKey.GetValue(TEXT("ReferenceCount"), &dwValueType, (LPBYTE) &dwReferenceCount, &dwBufferSize);
  189. if (REG_DWORD != dwValueType)
  190. {
  191. THROW(E_UNEXPECTED);
  192. }
  193. //
  194. // Decrement the ReferenceCount and write it to the Registry
  195. //
  196. if (0 < dwReferenceCount)
  197. {
  198. dwReferenceCount--;
  199. sRegistryKey.SetValue(TEXT("ReferenceCount"), REG_DWORD, (LPBYTE) &dwReferenceCount, dwBufferSize);
  200. }
  201. //
  202. // Close sRegistryKey
  203. //
  204. sRegistryKey.CloseKey();
  205. }
  206. sLock.UnLock();
  207. return (ULONG) dwReferenceCount;
  208. }
  209. //////////////////////////////////////////////////////////////////////////////////////////////
  210. //
  211. //////////////////////////////////////////////////////////////////////////////////////////////
  212. STDMETHODIMP CInformationManager::GetAdvancedMode(LPDWORD lpdwAdvancedMode)
  213. {
  214. FUNCTION("CInfoMgr::GetAdvancedMode ()");
  215. CLock sLock(&m_CriticalSection);
  216. CRegistryKey sRegistryKey;
  217. APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
  218. DWORD dwType, dwSize;
  219. HRESULT hResult = S_OK;
  220. sLock.Lock();
  221. //
  222. // If we cannot create/open the root AppMan key then this is a catastrophic failure
  223. //
  224. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
  225. //
  226. // Get the APPLICATION_MANAGER_RECORD
  227. //
  228. dwSize = sizeof(APPLICATION_MANAGER_RECORD);
  229. sRegistryKey.GetValue("Vector000", &dwType, (LPBYTE) &sApplicationManagerRecord, &dwSize);
  230. if ((REG_BINARY != dwType)||(sizeof(APPLICATION_MANAGER_RECORD) != dwSize))
  231. {
  232. THROW(APPMAN_E_REGISTRYCORRUPT);
  233. }
  234. *lpdwAdvancedMode = sApplicationManagerRecord.dwAdvancedMode;
  235. sRegistryKey.CloseKey();
  236. sLock.UnLock();
  237. return hResult;
  238. }
  239. //////////////////////////////////////////////////////////////////////////////////////////////
  240. //
  241. //////////////////////////////////////////////////////////////////////////////////////////////
  242. STDMETHODIMP CInformationManager::SetAdvancedMode(DWORD dwAdvancedMode)
  243. {
  244. FUNCTION("CInfoMgr::SetAdvancedMode ()");
  245. CLock sLock(&m_CriticalSection);
  246. CRegistryKey sRegistryKey;
  247. APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
  248. DWORD dwType, dwSize;
  249. sLock.Lock();
  250. //
  251. // If we cannot create/open the root AppMan key then this is a catastrophic failure
  252. //
  253. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_ALL_ACCESS);
  254. //
  255. // Get the APPLICATION_MANAGER_RECORD
  256. //
  257. dwSize = sizeof(APPLICATION_MANAGER_RECORD);
  258. sRegistryKey.GetValue("Vector000", &dwType, (LPBYTE) &sApplicationManagerRecord, &dwSize);
  259. if ((REG_BINARY != dwType)||(sizeof(APPLICATION_MANAGER_RECORD) != dwSize))
  260. {
  261. THROW(APPMAN_E_REGISTRYCORRUPT);
  262. }
  263. sApplicationManagerRecord.dwAdvancedMode = dwAdvancedMode;
  264. sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &sApplicationManagerRecord, sizeof(APPLICATION_MANAGER_RECORD));
  265. sRegistryKey.CloseKey();
  266. sLock.UnLock();
  267. return S_OK;
  268. }
  269. //////////////////////////////////////////////////////////////////////////////////////////////
  270. //
  271. //////////////////////////////////////////////////////////////////////////////////////////////
  272. STDMETHODIMP CInformationManager::GetOptimalAvailableSpace(const DWORD dwApplicationCategory, LPDWORD lpdwOptimalKilobytes)
  273. {
  274. FUNCTION("CInfoMgr::GetOptimalAvailableSpace ()");
  275. CLock sLock(&m_CriticalSection);
  276. DEVICE_RECORD sDeviceRecord;
  277. DWORD dwDeviceIndex;
  278. DWORD dwOptimalKilobytes;
  279. HRESULT hResult = S_OK;
  280. sLock.Lock();
  281. //
  282. // Initialize the parameter to it's default value
  283. //
  284. *(lpdwOptimalKilobytes) = 0;
  285. //
  286. // Traverse all the local drives
  287. //
  288. for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
  289. {
  290. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  291. {
  292. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  293. GetDeviceOptimalSpaceWithIndex(dwDeviceIndex, &dwOptimalKilobytes);
  294. //
  295. // Consider the device space info if it does not exclude dwApplicationCategory
  296. //
  297. if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
  298. {
  299. if ((*(lpdwOptimalKilobytes)) < dwOptimalKilobytes)
  300. {
  301. *(lpdwOptimalKilobytes) = dwOptimalKilobytes;
  302. }
  303. }
  304. }
  305. }
  306. sLock.UnLock();
  307. return S_OK;
  308. }
  309. //////////////////////////////////////////////////////////////////////////////////////////////
  310. //
  311. //////////////////////////////////////////////////////////////////////////////////////////////
  312. STDMETHODIMP CInformationManager::GetMaximumAvailableSpace(const DWORD dwApplicationCategory, LPDWORD lpdwMaximumKilobytes)
  313. {
  314. FUNCTION("CInfoMgr::GetMaximumAvailableSpace ()");
  315. CLock sLock(&m_CriticalSection);
  316. DEVICE_RECORD sDeviceRecord;
  317. DWORD dwDeviceIndex;
  318. DWORD dwMaximumKilobytes;
  319. sLock.Lock();
  320. //
  321. // Initialize the parameter to it's default value
  322. //
  323. *(lpdwMaximumKilobytes) = 0;
  324. //
  325. // Traverse all the local drives
  326. //
  327. for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
  328. {
  329. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  330. {
  331. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  332. GetDeviceMaximumSpaceWithIndex(dwDeviceIndex, &dwMaximumKilobytes);
  333. //
  334. // Consider the device space info if it does not exclude dwApplicationCategory
  335. //
  336. if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
  337. {
  338. if ((*(lpdwMaximumKilobytes)) < dwMaximumKilobytes)
  339. {
  340. *(lpdwMaximumKilobytes) = dwMaximumKilobytes;
  341. }
  342. }
  343. }
  344. }
  345. sLock.UnLock();
  346. return S_OK;
  347. }
  348. //////////////////////////////////////////////////////////////////////////////////////////////
  349. //
  350. //////////////////////////////////////////////////////////////////////////////////////////////
  351. STDMETHODIMP CInformationManager::GetSpace(const DWORD dwApplicationCategory, const DWORD dwRequiredKilobytes, LPDWORD lpdwDeviceIndex)
  352. {
  353. FUNCTION("CInfoMgr::GetSpace ()");
  354. CLock sLock(&m_CriticalSection);
  355. DEVICE_RECORD sDeviceRecord;
  356. DWORD dwDeviceIndex, dwTargetDeviceIndex;
  357. DWORD dwKilobytes, dwTargetKilobytes;
  358. HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
  359. sLock.Lock();
  360. //
  361. // Initialize the startup parameters
  362. //
  363. *(lpdwDeviceIndex) = dwTargetDeviceIndex = 0xffffffff;
  364. dwTargetKilobytes = 0;
  365. //
  366. // Get the device with the most available Kilobytes. We attempt to do this for an optimal target
  367. //
  368. for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
  369. {
  370. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  371. {
  372. //
  373. // Get the device information
  374. //
  375. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  376. //
  377. // Process devices that are not excluded
  378. //
  379. if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
  380. {
  381. GetDeviceOptimalSpaceWithIndex(dwDeviceIndex, &dwKilobytes);
  382. if ((dwRequiredKilobytes <= dwKilobytes)&&(dwTargetKilobytes < dwKilobytes))
  383. {
  384. dwTargetDeviceIndex = dwDeviceIndex;
  385. dwTargetKilobytes = dwKilobytes;
  386. }
  387. }
  388. }
  389. }
  390. //
  391. // If we failed to find an optimal fit, then we will go for a maximal fit
  392. //
  393. if (0xffffffff == dwTargetDeviceIndex)
  394. {
  395. for (dwDeviceIndex = 0; dwDeviceIndex < MAX_DEVICES; dwDeviceIndex++)
  396. {
  397. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  398. {
  399. //
  400. // Get the device information
  401. //
  402. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  403. //
  404. // Process devices that are not excluded
  405. //
  406. if (!(dwApplicationCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
  407. {
  408. GetDeviceMaximumSpaceWithIndex(dwDeviceIndex, &dwKilobytes);
  409. if ((dwRequiredKilobytes <= dwKilobytes)&&(dwTargetKilobytes < dwKilobytes))
  410. {
  411. dwTargetDeviceIndex = dwDeviceIndex;
  412. dwTargetKilobytes = dwKilobytes;
  413. }
  414. }
  415. }
  416. }
  417. }
  418. //
  419. // Did we find a target drive ?
  420. //
  421. if (0xffffffff == dwTargetDeviceIndex)
  422. {
  423. THROW(APPMAN_E_NODISKSPACEAVAILABLE);
  424. }
  425. //
  426. // Make sure to unlock before we try and free up the space
  427. //
  428. sLock.UnLock();
  429. //
  430. // Free up the space on the target device. Make sure that FreeSpaceOnDeviceWithIndex()
  431. // is called outside of a locking region
  432. //
  433. hResult = FreeSpaceOnDeviceWithIndex(dwTargetDeviceIndex, dwRequiredKilobytes);
  434. if (SUCCEEDED(hResult))
  435. {
  436. //
  437. // Record the target device to lpdwDeviceIndex
  438. //
  439. *(lpdwDeviceIndex) = dwTargetDeviceIndex;
  440. }
  441. return hResult;
  442. }
  443. //////////////////////////////////////////////////////////////////////////////////////////////
  444. //
  445. //////////////////////////////////////////////////////////////////////////////////////////////
  446. STDMETHODIMP CInformationManager::FreeSpaceOnDevice(const GUID * lpDeviceGuid, const DWORD dwRequiredKilobytes)
  447. {
  448. FUNCTION("CInfoMgr::FreeSpaceOnDevice ()");
  449. DEVICE_RECORD sDeviceRecord;
  450. HRESULT hResult;
  451. //
  452. // Translate the device guid into a device index
  453. //
  454. ZeroMemory(&sDeviceRecord, sizeof(DEVICE_RECORD));
  455. memcpy(&(sDeviceRecord.sDeviceGuid), lpDeviceGuid, sizeof(GUID));
  456. hResult = GetDeviceInfo(&sDeviceRecord);
  457. if (SUCCEEDED(hResult))
  458. {
  459. hResult = FreeSpaceOnDeviceWithIndex(GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial), dwRequiredKilobytes);
  460. }
  461. return hResult;
  462. }
  463. //////////////////////////////////////////////////////////////////////////////////////////////
  464. //
  465. // Returns the number of elapsed minutes since October 25th 1968 (my birthday)
  466. //
  467. //////////////////////////////////////////////////////////////////////////////////////////////
  468. //STDMETHODIMP_(DWORD) CInformationManager::GetApplicationAge(LPAPPLICATION_DATA lpApplicationData)
  469. //{
  470. // FUNCTION("CInfoMgr::GetApplicationAge ()");
  471. //
  472. // return GetAgingCount(lpApplicationData);
  473. //}
  474. //////////////////////////////////////////////////////////////////////////////////////////////
  475. //
  476. //////////////////////////////////////////////////////////////////////////////////////////////
  477. STDMETHODIMP CInformationManager::CheckApplicationExistance(const LPAPPLICATION_DATA lpApplicationData)
  478. {
  479. FUNCTION("CInfoMgr::CheckApplicationExistance ()");
  480. CLock sLock(&m_CriticalSection);
  481. HRESULT hResult = S_FALSE;
  482. DWORD dwApplicationIndex;
  483. APPLICATION_DATA sApplicationData;
  484. sLock.Lock();
  485. dwApplicationIndex = 0;
  486. while ((S_FALSE == hResult)&&(SUCCEEDED(GetApplicationDataWithIndex(dwApplicationIndex, &sApplicationData))))
  487. {
  488. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  489. {
  490. if (0 == memcmp((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID)))
  491. {
  492. hResult = S_OK;
  493. }
  494. }
  495. else
  496. {
  497. if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
  498. {
  499. if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], MAX_PATH_CHARCOUNT+1))
  500. {
  501. if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], sApplicationData.wszStringProperty[APP_STRING_SIGNATURE], MAX_PATH_CHARCOUNT+1))
  502. {
  503. hResult = S_OK;
  504. }
  505. }
  506. }
  507. else
  508. {
  509. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  510. }
  511. }
  512. dwApplicationIndex++;
  513. }
  514. sLock.UnLock();
  515. return hResult;
  516. }
  517. //////////////////////////////////////////////////////////////////////////////////////////////
  518. //
  519. //////////////////////////////////////////////////////////////////////////////////////////////
  520. BOOL CInformationManager::IsApplicationPinned(const LPAPPLICATION_DATA lpApplicationData)
  521. {
  522. FUNCTION("CInfoMgr::IsApplicationPinned ()");
  523. CLock sLock(&m_CriticalSection);
  524. APPLICATION_DATA sApplicationData;
  525. ASSOCIATION_INFO sAssociationData;
  526. DWORD dwIndex;
  527. BOOL fResult = FALSE;
  528. //
  529. // Lock the information manager to prevent other processes from using it
  530. //
  531. sLock.Lock();
  532. //
  533. // First we make sure the root path is not pinned itself
  534. //
  535. fResult = lpApplicationData->sBaseInfo.dwPinState;
  536. //
  537. // Lock this application and all of it's parents
  538. //
  539. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  540. dwIndex = 0;
  541. while ((FALSE == fResult)&&(S_OK == EnumAssociations(dwIndex, &sAssociationData)))
  542. {
  543. if (0 == memcmp((LPVOID) &(sAssociationData.sParentGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  544. {
  545. //
  546. // We have found an association parented by lpApplicationData
  547. //
  548. ZeroMemory(&sApplicationData, sizeof(sApplicationData));
  549. memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sChildGuid), sizeof(GUID));
  550. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
  551. if (SUCCEEDED(GetApplicationData(&sApplicationData)))
  552. {
  553. fResult = IsApplicationPinned(&sApplicationData);
  554. }
  555. }
  556. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  557. dwIndex++;
  558. }
  559. //
  560. // Now that we are done, unlock the Information Manager
  561. //
  562. sLock.UnLock();
  563. return fResult;
  564. }
  565. //////////////////////////////////////////////////////////////////////////////////////////////
  566. //
  567. //////////////////////////////////////////////////////////////////////////////////////////////
  568. STDMETHODIMP CInformationManager::IsInstanceGuidStillAlive(const GUID * lpGuid)
  569. {
  570. FUNCTION("CInfoMgr::IsInstanceGuidStillAlive ()");
  571. CLock sLock(&m_CriticalSection);
  572. HANDLE hMutex;
  573. CHAR szString[MAX_PATH];
  574. HRESULT hResult = S_OK;
  575. sLock.Lock();
  576. //
  577. // Create a named mutex
  578. //
  579. 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]);
  580. hMutex = CreateMutex(NULL, FALSE, szString);
  581. if (NULL == hMutex)
  582. {
  583. THROW(E_UNEXPECTED);
  584. }
  585. //
  586. // Did we create the mutex
  587. //
  588. if (ERROR_ALREADY_EXISTS == GetLastError())
  589. {
  590. //
  591. // If we get WAIT_TIMEOUT then the thread is still alive
  592. // If we get WAIT_OBJECT_0 then the thread is the current one using this function
  593. // If we get WAIT_ABANDONNED then the thread died
  594. //
  595. switch (WaitForSingleObject(hMutex, 0))
  596. {
  597. case WAIT_TIMEOUT
  598. : hResult = S_OK;
  599. break;
  600. case WAIT_OBJECT_0
  601. : hResult = S_OK;
  602. break;
  603. case WAIT_ABANDONED
  604. : hResult = S_FALSE;
  605. break;
  606. }
  607. }
  608. else
  609. {
  610. //
  611. // We created the mutex. This means that instance is no longer alive
  612. //
  613. hResult = S_FALSE;
  614. }
  615. //
  616. // Close the mutex handle
  617. //
  618. CloseHandle(hMutex);
  619. //
  620. // Now that we are done, unlock the Information Manager
  621. //
  622. sLock.UnLock();
  623. return hResult;
  624. }
  625. //////////////////////////////////////////////////////////////////////////////////////////////
  626. //
  627. //////////////////////////////////////////////////////////////////////////////////////////////
  628. STDMETHODIMP CInformationManager::IsApplicationLocked(LPAPPLICATION_DATA lpApplicationData)
  629. {
  630. FUNCTION("CInfoMgr::IsApplicationLocked ()");
  631. CLock sLock(&m_CriticalSection);
  632. CRegistryKey sRegistryKey;
  633. GUID sEncryptedGuid;
  634. CHAR szString[40];
  635. HRESULT hResult;
  636. assert(NULL != lpApplicationData);
  637. sLock.Lock();
  638. //
  639. // Open the AppMan\\Lock registry entry
  640. //
  641. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
  642. //
  643. // What would be the encrypted guid for this application. This value will be used as the
  644. // Value Name of the registry entry
  645. //
  646. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  647. EncryptGuid(&sEncryptedGuid);
  648. 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]);
  649. //
  650. // Is the application already locked
  651. //
  652. hResult = sRegistryKey.CheckForExistingValue(szString);
  653. if (S_OK == hResult)
  654. {
  655. LOCK_INFO sLockInfo;
  656. DWORD dwDataType, dwDataLen;
  657. //
  658. // Well the application is locked, but is the lock still valid, let's check
  659. //
  660. dwDataLen = sizeof(sLockInfo);
  661. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  662. sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
  663. if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo))||(S_FALSE == IsInstanceGuidStillAlive(&sLockInfo.guidInstanceGuid)))
  664. {
  665. //
  666. // The lock is invalid
  667. //
  668. if (S_OK == sRegistryKey.CheckForExistingValue(szString))
  669. {
  670. sRegistryKey.DeleteValue(szString);
  671. }
  672. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  673. hResult = S_FALSE;
  674. }
  675. }
  676. //
  677. // Close the registry
  678. //
  679. sRegistryKey.CloseKey();
  680. //
  681. // Unlock the information manager
  682. //
  683. sLock.UnLock();
  684. return hResult;
  685. }
  686. //////////////////////////////////////////////////////////////////////////////////////////////
  687. //
  688. //////////////////////////////////////////////////////////////////////////////////////////////
  689. STDMETHODIMP CInformationManager::LockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
  690. {
  691. FUNCTION("CInfoMgr::LockApplicationData ()");
  692. CLock sLock(&m_CriticalSection);
  693. CRegistryKey sRegistryKey;
  694. LOCK_INFO sLockInfo;
  695. GUID sEncryptedGuid;
  696. DWORD dwIndex, dwDataType, dwDataLen;
  697. CHAR szGuid[40];
  698. HRESULT hResult = S_OK;
  699. assert(NULL != lpApplicationData);
  700. sLock.Lock();
  701. //
  702. // Open the AppMan\\Lock registry entry
  703. //
  704. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
  705. //
  706. // What would be the encrypted guid for this application. This value will be used as the
  707. // Value Name of the registry entry
  708. //
  709. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  710. EncryptGuid(&sEncryptedGuid);
  711. 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]);
  712. //
  713. // Is the application already locked
  714. //
  715. if (S_OK == IsApplicationLocked(lpApplicationData))
  716. {
  717. //
  718. // Get the lock info for this application
  719. //
  720. dwDataLen = sizeof(sLockInfo);
  721. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  722. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
  723. //
  724. // Make sure the data that we have retrieved makes sense
  725. //
  726. if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo)))
  727. {
  728. //
  729. // The registry entry isnt very good.
  730. //
  731. sRegistryKey.DeleteValue(szGuid);
  732. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  733. }
  734. //
  735. // Handle depending on reentry case or wait state
  736. //
  737. if (0 == memcmp((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID)))
  738. {
  739. //
  740. // Reentry case
  741. //
  742. sLockInfo.dwLockCount++;
  743. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
  744. }
  745. else
  746. {
  747. DWORD dwStartTime;
  748. //
  749. // Other instance has the object locked. We have to wait for lock to go away
  750. //
  751. dwStartTime = GetTickCount();
  752. sLock.UnLock();
  753. hResult = APPMAN_E_OBJECTLOCKED;
  754. dwIndex = 0;
  755. do
  756. {
  757. //
  758. // Give the lock owner thread a chance to relinquish the lock
  759. //
  760. Sleep(100);
  761. if (S_FALSE == IsApplicationLocked(lpApplicationData))
  762. {
  763. hResult = S_OK;
  764. }
  765. //
  766. // Each time we increment dwIndex, 1/10 of a second went by.
  767. //
  768. dwIndex++;
  769. //
  770. // Did we run out of time
  771. //
  772. if (10000 > (GetTickCount() - dwStartTime))
  773. {
  774. THROW(APPMAN_E_APPLICATIONALREADYLOCKED);
  775. }
  776. }
  777. while (FAILED(hResult));
  778. }
  779. }
  780. else
  781. {
  782. //
  783. // There is no lock on this object
  784. //
  785. sLockInfo.dwSize = sizeof(sLockInfo);
  786. sLockInfo.dwStructId = LOCK_STRUCT;
  787. sLockInfo.dwLockCount = 1;
  788. memcpy((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID));
  789. //
  790. // Write out the new lock info to the registry
  791. //
  792. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
  793. }
  794. //
  795. // Close the registry key
  796. //
  797. sRegistryKey.CloseKey();
  798. //
  799. // Make sure the information manager unlocked
  800. //
  801. sLock.UnLock();
  802. return hResult;
  803. }
  804. //////////////////////////////////////////////////////////////////////////////////////////////
  805. //
  806. //////////////////////////////////////////////////////////////////////////////////////////////
  807. STDMETHODIMP CInformationManager::UnlockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
  808. {
  809. FUNCTION("CInfoMgr::UnlockApplicationData ()");
  810. CLock sLock(&m_CriticalSection);
  811. CRegistryKey sRegistryKey;
  812. LOCK_INFO sLockInfo;
  813. DWORD dwDataType, dwDataLen;
  814. GUID sEncryptedGuid;
  815. CHAR szGuid[40];
  816. HRESULT hResult = S_OK;
  817. assert(NULL != lpApplicationData);
  818. sLock.Lock();
  819. //
  820. // Open the AppMan\\Lock registry entry
  821. //
  822. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
  823. //
  824. // What would be the encrypted guid for this application. This value will be used as the
  825. // Value Name of the registry entry
  826. //
  827. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  828. EncryptGuid(&sEncryptedGuid);
  829. 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]);
  830. //
  831. // Is the application already locked
  832. //
  833. if (S_OK == IsApplicationLocked(lpApplicationData))
  834. {
  835. //
  836. // Get the lock info for this application
  837. //
  838. dwDataLen = sizeof(sLockInfo);
  839. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  840. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
  841. //
  842. // Make sure the data that we have retrieved makes sense
  843. //
  844. if ((REG_BINARY != dwDataType)||(dwDataLen != sizeof(sLockInfo)))
  845. {
  846. //
  847. // The registry entry isnt very good.
  848. //
  849. sRegistryKey.DeleteValue(szGuid);
  850. }
  851. else
  852. {
  853. //
  854. // Make sure that we do own this lock
  855. //
  856. if (0 == memcmp((LPVOID) &(sLockInfo.guidInstanceGuid), (LPVOID) lpInstanceGuid, sizeof(GUID)))
  857. {
  858. sLockInfo.dwLockCount--;
  859. if (0 == sLockInfo.dwLockCount)
  860. {
  861. //
  862. // The lock is over. Delete the registry entry
  863. //
  864. sRegistryKey.DeleteValue(szGuid);
  865. }
  866. else
  867. {
  868. //
  869. // We still own the lock. Write out the new registry information with the updated
  870. // lock count
  871. //
  872. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sLockInfo, sizeof(sLockInfo));
  873. }
  874. }
  875. }
  876. }
  877. //
  878. // Close the registry key
  879. //
  880. sRegistryKey.CloseKey();
  881. //
  882. // Make sure the information manager unlocked
  883. //
  884. sLock.UnLock();
  885. return hResult;
  886. }
  887. //////////////////////////////////////////////////////////////////////////////////////////////
  888. //
  889. //////////////////////////////////////////////////////////////////////////////////////////////
  890. STDMETHODIMP CInformationManager::ForceUnlockApplicationData(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
  891. {
  892. FUNCTION("CInfoMgr::UnlockApplicationData ()");
  893. CLock sLock(&m_CriticalSection);
  894. HRESULT hResult = S_OK;
  895. assert(NULL != lpApplicationData);
  896. sLock.Lock();
  897. //
  898. // Is the application already locked
  899. //
  900. if (S_OK == IsApplicationLocked(lpApplicationData))
  901. {
  902. CRegistryKey sRegistryKey;
  903. GUID sEncryptedGuid;
  904. CHAR szString[MAX_PATH];
  905. LOCK_INFO sLockInfo;
  906. DWORD dwDataType, dwDataLen;
  907. //
  908. // Open the AppMan\\Lock registry entry
  909. //
  910. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", KEY_ALL_ACCESS);
  911. //
  912. // What would be the encrypted guid for this application. This value will be used as the
  913. // Value Name of the registry entry
  914. //
  915. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  916. EncryptGuid(&sEncryptedGuid);
  917. 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]);
  918. //
  919. // Well the application is locked, but do we own the lock ?
  920. //
  921. dwDataLen = sizeof(sLockInfo);
  922. ZeroMemory(&sLockInfo, sizeof(sLockInfo));
  923. sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) &sLockInfo, &dwDataLen);
  924. if (0 == memcmp(&sLockInfo.guidInstanceGuid, lpInstanceGuid, sizeof(GUID)))
  925. {
  926. //
  927. // We own the lock so let's kill it
  928. //
  929. sRegistryKey.DeleteValue(szString);
  930. }
  931. //
  932. // Close the registry key
  933. //
  934. sRegistryKey.CloseKey();
  935. }
  936. //
  937. // Make sure the information manager unlocked
  938. //
  939. sLock.UnLock();
  940. return hResult;
  941. }
  942. //////////////////////////////////////////////////////////////////////////////////////////////
  943. //
  944. //////////////////////////////////////////////////////////////////////////////////////////////
  945. STDMETHODIMP CInformationManager::LockApplicationData(LPAPPLICATION_DATA lpApplicationData)
  946. {
  947. FUNCTION("CInfoMgr::LockApplicationData ()");
  948. GUID sZeroGuid;
  949. ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
  950. return LockApplicationData(lpApplicationData, &sZeroGuid);
  951. }
  952. //////////////////////////////////////////////////////////////////////////////////////////////
  953. //
  954. //////////////////////////////////////////////////////////////////////////////////////////////
  955. STDMETHODIMP CInformationManager::UnlockApplicationData(LPAPPLICATION_DATA lpApplicationData)
  956. {
  957. FUNCTION("CInfoMgr::UnlockApplicationData ()");
  958. GUID sZeroGuid;
  959. ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
  960. return UnlockApplicationData(lpApplicationData, &sZeroGuid);
  961. }
  962. //////////////////////////////////////////////////////////////////////////////////////////////
  963. //
  964. //////////////////////////////////////////////////////////////////////////////////////////////
  965. STDMETHODIMP CInformationManager::LockParentApplications(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
  966. {
  967. FUNCTION("CInfoMgr::LockParentApplications ()");
  968. CLock sLock(&m_CriticalSection);
  969. APPLICATION_DATA sApplicationData;
  970. ASSOCIATION_INFO sAssociationData;
  971. DWORD dwIndex;
  972. HRESULT hResult = S_OK;
  973. //
  974. // Lock the information manager to prevent other processes from using it
  975. //
  976. sLock.Lock();
  977. //
  978. // Lock this application and all of it's parents
  979. //
  980. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  981. dwIndex = 0;
  982. while (S_OK == EnumAssociations(dwIndex, &sAssociationData))
  983. {
  984. if (0 == memcmp((LPVOID) &(sAssociationData.sChildGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  985. {
  986. //
  987. // We have found a parent application. There can only be one parent per application
  988. //
  989. ZeroMemory(&sApplicationData, sizeof(sApplicationData));
  990. memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sParentGuid), sizeof(GUID));
  991. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
  992. if (SUCCEEDED(GetApplicationData(&sApplicationData)))
  993. {
  994. hResult = LockParentApplications(&sApplicationData, lpInstanceGuid);
  995. }
  996. }
  997. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  998. dwIndex++;
  999. }
  1000. //
  1001. // If everything is going ok, lock this applications
  1002. //
  1003. if (SUCCEEDED(hResult))
  1004. {
  1005. hResult = LockApplicationData(lpApplicationData, lpInstanceGuid);
  1006. }
  1007. //
  1008. // Now that we are done, unlock the Information Manager
  1009. //
  1010. sLock.UnLock();
  1011. return hResult;
  1012. }
  1013. //////////////////////////////////////////////////////////////////////////////////////////////
  1014. //
  1015. //////////////////////////////////////////////////////////////////////////////////////////////
  1016. STDMETHODIMP CInformationManager::UnlockParentApplications(LPAPPLICATION_DATA lpApplicationData, GUID * lpInstanceGuid)
  1017. {
  1018. FUNCTION("CInfoMgr::UnlockParentApplications ()");
  1019. CLock sLock(&m_CriticalSection);
  1020. APPLICATION_DATA sApplicationData;
  1021. ASSOCIATION_INFO sAssociationData;
  1022. DWORD dwIndex;
  1023. HRESULT hResult = S_OK;
  1024. //
  1025. // Lock the information manager to prevent other processes from using it
  1026. //
  1027. sLock.Lock();
  1028. //
  1029. // Unlock this application and all of it's parents
  1030. //
  1031. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  1032. dwIndex = 0;
  1033. while (S_OK == EnumAssociations(dwIndex, &sAssociationData))
  1034. {
  1035. if (0 == memcmp((LPVOID) &(sAssociationData.sChildGuid), (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  1036. {
  1037. //
  1038. // We have found a parent application. There can only be one parent per application
  1039. //
  1040. ZeroMemory(&sApplicationData, sizeof(sApplicationData));
  1041. memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationData.sParentGuid), sizeof(GUID));
  1042. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
  1043. if (SUCCEEDED(GetApplicationData(&sApplicationData)))
  1044. {
  1045. hResult = UnlockParentApplications(&sApplicationData, lpInstanceGuid);
  1046. }
  1047. }
  1048. ZeroMemory(&sAssociationData, sizeof(sAssociationData));
  1049. dwIndex++;
  1050. }
  1051. //
  1052. // If everything is going ok, lock this applications
  1053. //
  1054. if (SUCCEEDED(hResult))
  1055. {
  1056. hResult = UnlockApplicationData(lpApplicationData, lpInstanceGuid);
  1057. }
  1058. //
  1059. // Now that we are done, unlock the Information Manager
  1060. //
  1061. sLock.Lock();
  1062. return hResult;
  1063. }
  1064. //////////////////////////////////////////////////////////////////////////////////////////////
  1065. //
  1066. //////////////////////////////////////////////////////////////////////////////////////////////
  1067. STDMETHODIMP CInformationManager::LockParentApplications(LPAPPLICATION_DATA lpApplicationData)
  1068. {
  1069. FUNCTION("CInfoMgr::LockParentApplications ()");
  1070. GUID sZeroGuid;
  1071. ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
  1072. return LockParentApplications(lpApplicationData, &sZeroGuid);
  1073. }
  1074. //////////////////////////////////////////////////////////////////////////////////////////////
  1075. //
  1076. //////////////////////////////////////////////////////////////////////////////////////////////
  1077. STDMETHODIMP CInformationManager::UnlockParentApplications(LPAPPLICATION_DATA lpApplicationData)
  1078. {
  1079. FUNCTION("CInfoMgr::UnlockParentApplications ()");
  1080. GUID sZeroGuid;
  1081. ZeroMemory(&sZeroGuid, sizeof(sZeroGuid));
  1082. return UnlockParentApplications(lpApplicationData, &sZeroGuid);
  1083. }
  1084. //////////////////////////////////////////////////////////////////////////////////////////////
  1085. //
  1086. //////////////////////////////////////////////////////////////////////////////////////////////
  1087. STDMETHODIMP CInformationManager::AddApplicationData(LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
  1088. {
  1089. FUNCTION("CInfoMgr::AddApplicationData ()");
  1090. CLock sLock(&m_CriticalSection);
  1091. assert(NULL != lpApplicationData);
  1092. sLock.Lock();
  1093. //
  1094. // Make sure the SIGNATURE and COMPANYNAME properties are set
  1095. //
  1096. if ((S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))||(S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
  1097. {
  1098. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  1099. }
  1100. //
  1101. // Does the application already exist
  1102. //
  1103. if (S_OK == CheckApplicationExistance(lpApplicationData))
  1104. {
  1105. THROW(APPMAN_E_APPLICATIONALREADYEXISTS);
  1106. }
  1107. //
  1108. // Assign a new GUID to the application record
  1109. //
  1110. if (FAILED(CoCreateGuid(&(lpApplicationData->sBaseInfo.sApplicationGuid))))
  1111. {
  1112. THROW(E_UNEXPECTED);
  1113. }
  1114. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, lpApplicationData);
  1115. //
  1116. // Set the application record
  1117. //
  1118. SetApplicationData(lpApplicationData, lpInstanceGuid);
  1119. sLock.UnLock();
  1120. return S_OK;
  1121. }
  1122. //////////////////////////////////////////////////////////////////////////////////////////////
  1123. //
  1124. //////////////////////////////////////////////////////////////////////////////////////////////
  1125. STDMETHODIMP CInformationManager::RemoveApplicationData(LPAPPLICATION_DATA lpApplicationData)
  1126. {
  1127. FUNCTION("CInfoMgr::RemoveApplicationData ()");
  1128. CLock sLock(&m_CriticalSection);
  1129. CRegistryKey sRegistryKey;
  1130. APPLICATION_DATA sApplicationData;
  1131. CHAR szString[MAX_PATH_CHARCOUNT];
  1132. GUID sEncryptedGuid;
  1133. BOOL fEraseSetupRoot = TRUE;
  1134. DWORD dwIndex;
  1135. assert(NULL != lpApplicationData);
  1136. sLock.Lock();
  1137. //
  1138. // In order to remove an application, we must have DATA_FIELD_GUID validated
  1139. //
  1140. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  1141. {
  1142. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  1143. }
  1144. //
  1145. // Does the application already exist
  1146. //
  1147. if (S_OK == CheckApplicationExistance(lpApplicationData))
  1148. {
  1149. //
  1150. // Make sure we have a fully populated application object
  1151. //
  1152. if (SUCCEEDED(GetApplicationData(lpApplicationData)))
  1153. {
  1154. ASSOCIATION_INFO sAssociationInfo;
  1155. //
  1156. // Remove related associations from system
  1157. //
  1158. dwIndex = 0;
  1159. while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
  1160. {
  1161. if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
  1162. {
  1163. RemoveAssociation(&sAssociationInfo);
  1164. }
  1165. else if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
  1166. {
  1167. RemoveAssociation(&sAssociationInfo);
  1168. }
  1169. dwIndex++;
  1170. }
  1171. //
  1172. // Delete the application record
  1173. //
  1174. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID));
  1175. EncryptGuid(&sEncryptedGuid);
  1176. 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]);
  1177. if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
  1178. {
  1179. sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
  1180. }
  1181. //
  1182. // Find out if any other applications are using this directory
  1183. //
  1184. dwIndex = 0;
  1185. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  1186. {
  1187. if (0 == wcscmp(sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1188. {
  1189. fEraseSetupRoot = FALSE;
  1190. }
  1191. dwIndex++;
  1192. }
  1193. //
  1194. // Delete the setup root directory.
  1195. //
  1196. if (fEraseSetupRoot)
  1197. {
  1198. if (FAILED(DeleteDirectoryTree(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH])))
  1199. {
  1200. RegFutureDirectoryCleanup(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]);
  1201. }
  1202. }
  1203. //
  1204. // Close sRegistryKey
  1205. //
  1206. sRegistryKey.CloseKey();
  1207. }
  1208. }
  1209. sLock.UnLock();
  1210. return S_OK;
  1211. }
  1212. //////////////////////////////////////////////////////////////////////////////////////////////
  1213. //
  1214. //////////////////////////////////////////////////////////////////////////////////////////////
  1215. STDMETHODIMP CInformationManager::GetApplicationDataWithIndex(const DWORD dwApplicationIndex, LPAPPLICATION_DATA lpApplicationData)
  1216. {
  1217. FUNCTION("CInfoMgr::GetApplicationDataWithIndex ()");
  1218. CLock sLock(&m_CriticalSection);
  1219. DEVICE_RECORD sDeviceRecord;
  1220. CWin32API sWin32API;
  1221. CRegistryKey sRegistryKey;
  1222. CHAR szString[MAX_PATH_CHARCOUNT+1];
  1223. DWORD dwIndex, dwTargetIndex;
  1224. DWORD dwValueType, dwValueLen;
  1225. DWORD dwStringLen, dwStringIndex;
  1226. HRESULT hResult = S_OK;
  1227. BOOL fRemoveApp = FALSE;
  1228. assert(NULL != lpApplicationData);
  1229. sLock.Lock();
  1230. //
  1231. // First we need to open the application root key
  1232. //
  1233. sprintf(szString, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications");
  1234. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_READ);
  1235. //
  1236. // Because of the way the registry works, we have to start enumerating keys with
  1237. // a starting index of 0 and increment constantly until we get to the desired index
  1238. //
  1239. dwTargetIndex = dwApplicationIndex;
  1240. dwIndex = 0;
  1241. while ((dwIndex <= dwTargetIndex)&&(SUCCEEDED(hResult)))
  1242. {
  1243. dwStringLen = sizeof(szString);
  1244. if (S_OK == sRegistryKey.EnumKeys(dwIndex, szString, &dwStringLen))
  1245. {
  1246. ZeroMemory(lpApplicationData, sizeof(APPLICATION_DATA));
  1247. if (!StringToGuidA(szString, &lpApplicationData->sBaseInfo.sApplicationGuid))
  1248. {
  1249. dwTargetIndex++;
  1250. }
  1251. }
  1252. else
  1253. {
  1254. hResult = APPMAN_E_INVALIDINDEX;
  1255. }
  1256. dwIndex++;
  1257. }
  1258. //
  1259. // Close sRegistryKey
  1260. //
  1261. sRegistryKey.CloseKey();
  1262. //
  1263. // Did we find a candidate application
  1264. //
  1265. if (SUCCEEDED(hResult))
  1266. {
  1267. 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]);
  1268. if (S_FALSE == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
  1269. {
  1270. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1271. }
  1272. //
  1273. // Open the application registry key
  1274. //
  1275. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, szString, KEY_READ);
  1276. //
  1277. // Read in the binary data
  1278. //
  1279. dwValueLen = sizeof(lpApplicationData->sBaseInfo);
  1280. sRegistryKey.GetValue("Vector000", &dwValueType, (LPBYTE) &lpApplicationData->sBaseInfo, &dwValueLen);
  1281. if (sizeof(lpApplicationData->sBaseInfo) != dwValueLen)
  1282. {
  1283. THROW(E_UNEXPECTED);
  1284. }
  1285. dwValueLen = sizeof(lpApplicationData->sAgingInfo);
  1286. sRegistryKey.GetValue("Vector001", &dwValueType, (LPBYTE) &lpApplicationData->sAgingInfo, &dwValueLen);
  1287. if (sizeof(lpApplicationData->sAgingInfo) != dwValueLen)
  1288. {
  1289. THROW(E_UNEXPECTED);
  1290. }
  1291. dwValueLen = sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]);
  1292. sRegistryKey.GetValue("Vector002", &dwValueType, (LPBYTE) lpApplicationData->wszStringProperty[APP_STRING_CRYPTO], &dwValueLen);
  1293. if (sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]) != dwValueLen)
  1294. {
  1295. THROW(E_UNEXPECTED);
  1296. }
  1297. //
  1298. // Read in the string data
  1299. //
  1300. for (dwIndex = 0; dwIndex < PROPERTY_COUNT; dwIndex++)
  1301. {
  1302. //
  1303. // If the property is set, is it a string ?
  1304. //
  1305. if ((S_OK == IsApplicationPropertyInitializedWithIndex(dwIndex, lpApplicationData))&&(APP_STRING_NONE != gPropertyInfo[dwIndex].dwStringId))
  1306. {
  1307. //
  1308. // Get the encrypted string from the registry
  1309. //
  1310. sprintf(szString, "Vector%03x", gPropertyInfo[dwIndex].dwStringId + 2);
  1311. dwValueLen = (MAX_PATH_CHARCOUNT+1)*2;
  1312. sRegistryKey.GetValue(szString, &dwValueType, (LPBYTE) lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId], &dwValueLen);
  1313. //
  1314. // Decrypt the string
  1315. //
  1316. for (dwStringIndex = 0; dwStringIndex < MAX_PATH_CHARCOUNT+1; dwStringIndex++)
  1317. {
  1318. lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringIndex] ^= lpApplicationData->wszStringProperty[APP_STRING_CRYPTO][dwStringIndex];
  1319. }
  1320. }
  1321. }
  1322. //
  1323. // Close sRegistryKey
  1324. //
  1325. sRegistryKey.CloseKey();
  1326. //
  1327. // Compensate for a changing device index (i.e. problem with SCSI pluggins)
  1328. //
  1329. ZeroMemory(&sDeviceRecord, sizeof(sDeviceRecord));
  1330. memcpy(&sDeviceRecord.sDeviceGuid, &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID));
  1331. GetDeviceInfo(&sDeviceRecord);
  1332. //
  1333. // Get the device index of the device using the volume serial passed in
  1334. //
  1335. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
  1336. {
  1337. lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1338. }
  1339. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
  1340. {
  1341. lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1342. }
  1343. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_EXECUTECMDLINE, lpApplicationData))
  1344. {
  1345. lpApplicationData->wszStringProperty[APP_STRING_EXECUTECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1346. }
  1347. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, lpApplicationData))
  1348. {
  1349. lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1350. }
  1351. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, lpApplicationData))
  1352. {
  1353. lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1354. }
  1355. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
  1356. {
  1357. lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1358. }
  1359. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, lpApplicationData))
  1360. {
  1361. lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1362. }
  1363. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1364. {
  1365. lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE][0] = (WORD) (65 + GetDeviceIndex(sDeviceRecord.sDeviceInfo.dwVolumeSerial));
  1366. }
  1367. //
  1368. // If the application is in a ready state and the setup root path is gone, this is not so bad
  1369. //
  1370. if (APP_STATE_READY == lpApplicationData->sBaseInfo.dwState)
  1371. {
  1372. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1373. {
  1374. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
  1375. {
  1376. fRemoveApp = TRUE;
  1377. }
  1378. }
  1379. }
  1380. else
  1381. {
  1382. if ((APP_STATE_DOWNSIZING | APP_STATE_DOWNSIZED | APP_STATE_REINSTALLING | APP_STATE_UNINSTALLING | APP_STATE_SELFTESTING) && lpApplicationData->sBaseInfo.dwState)
  1383. {
  1384. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1385. {
  1386. fRemoveApp = TRUE;
  1387. }
  1388. }
  1389. }
  1390. //
  1391. // Should we remove the application
  1392. //
  1393. if (fRemoveApp)
  1394. {
  1395. ASSOCIATION_INFO sAssociationInfo;
  1396. //
  1397. // Well there's no sense in keeping the application lying around since both of it's root paths
  1398. // are gone. Let's delete the record
  1399. //
  1400. EncryptGuid(&lpApplicationData->sBaseInfo.sApplicationGuid);
  1401. 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]);
  1402. if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
  1403. {
  1404. sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
  1405. }
  1406. //
  1407. // Remove related associations from system
  1408. //
  1409. DecryptGuid(&lpApplicationData->sBaseInfo.sApplicationGuid);
  1410. dwIndex = 0;
  1411. while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
  1412. {
  1413. if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
  1414. {
  1415. RemoveAssociation(&sAssociationInfo);
  1416. }
  1417. else if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
  1418. {
  1419. RemoveAssociation(&sAssociationInfo);
  1420. }
  1421. dwIndex++;
  1422. }
  1423. //
  1424. // Recursively call
  1425. //
  1426. hResult = GetApplicationDataWithIndex(dwApplicationIndex, lpApplicationData);
  1427. }
  1428. }
  1429. sLock.UnLock();
  1430. return hResult;
  1431. }
  1432. //////////////////////////////////////////////////////////////////////////////////////////////
  1433. //
  1434. //////////////////////////////////////////////////////////////////////////////////////////////
  1435. STDMETHODIMP CInformationManager::GetApplicationData(LPAPPLICATION_DATA lpApplicationData)
  1436. {
  1437. FUNCTION("CInfoMgr::GetApplicationData ()");
  1438. CLock sLock(&m_CriticalSection);
  1439. HRESULT hResult = S_FALSE;
  1440. DWORD dwApplicationIndex;
  1441. APPLICATION_DATA sApplicationData;
  1442. assert(NULL != lpApplicationData);
  1443. sLock.Lock();
  1444. dwApplicationIndex = 0;
  1445. while ((S_FALSE == hResult)&&(SUCCEEDED(GetApplicationDataWithIndex(dwApplicationIndex, &sApplicationData))))
  1446. {
  1447. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  1448. {
  1449. if (0 == memcmp((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID)))
  1450. {
  1451. memcpy((LPVOID) lpApplicationData, (LPVOID) &sApplicationData, sizeof(APPLICATION_DATA));
  1452. hResult = S_OK;
  1453. }
  1454. }
  1455. else
  1456. {
  1457. if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, lpApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, lpApplicationData)))
  1458. {
  1459. if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], MAX_PATH_CHARCOUNT+1))
  1460. {
  1461. if (0 == _wcsnicmp(lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], sApplicationData.wszStringProperty[APP_STRING_SIGNATURE], MAX_PATH_CHARCOUNT+1))
  1462. {
  1463. memcpy((LPVOID) lpApplicationData, (LPVOID) &sApplicationData, sizeof(APPLICATION_DATA));
  1464. hResult = S_OK;
  1465. }
  1466. }
  1467. }
  1468. else
  1469. {
  1470. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  1471. }
  1472. }
  1473. dwApplicationIndex++;
  1474. }
  1475. sLock.UnLock();
  1476. //
  1477. // Did we find the application we were looking for ?
  1478. //
  1479. if (S_FALSE == hResult)
  1480. {
  1481. hResult = APPMAN_E_UNKNOWNAPPLICATION;
  1482. }
  1483. return hResult;
  1484. }
  1485. //////////////////////////////////////////////////////////////////////////////////////////////
  1486. //
  1487. //////////////////////////////////////////////////////////////////////////////////////////////
  1488. STDMETHODIMP CInformationManager::SetApplicationData(LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
  1489. {
  1490. FUNCTION("CInfoMgr::SetApplicationData ()");
  1491. CLock sLock(&m_CriticalSection);
  1492. CRegistryKey sRegistryKey;
  1493. GUID sApplicationGuid;
  1494. CHAR szString[MAX_PATH_CHARCOUNT+1];
  1495. DWORD dwStringLen, dwIndex;
  1496. WCHAR wszEncryptedString[MAX_PATH_CHARCOUNT+1];
  1497. assert(NULL != lpApplicationData);
  1498. sLock.Lock();
  1499. //
  1500. // Record the instance guid
  1501. //
  1502. if (NULL != lpInstanceGuid)
  1503. {
  1504. memcpy(&lpApplicationData->sBaseInfo.sInstanceGuid, lpInstanceGuid, sizeof(GUID));
  1505. }
  1506. else
  1507. {
  1508. ZeroMemory(&lpApplicationData->sBaseInfo.sInstanceGuid, sizeof(GUID));
  1509. }
  1510. //
  1511. // First we need to determine how the encrypted GUID is going to look like
  1512. //
  1513. memcpy(&sApplicationGuid, &lpApplicationData->sBaseInfo.sApplicationGuid, sizeof(GUID));
  1514. EncryptGuid(&sApplicationGuid);
  1515. //
  1516. // Now that we have the encrypted GUID, we need to build the root registry entry for this
  1517. // application.
  1518. //
  1519. 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]);
  1520. if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, szString))
  1521. {
  1522. sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, szString);
  1523. }
  1524. //
  1525. // Open the application registry key
  1526. //
  1527. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, szString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, NULL);
  1528. //
  1529. // Write out the binary data
  1530. //
  1531. sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &lpApplicationData->sBaseInfo, sizeof(lpApplicationData->sBaseInfo));
  1532. sRegistryKey.SetValue("Vector001", REG_BINARY, (LPBYTE) &lpApplicationData->sAgingInfo, sizeof(lpApplicationData->sAgingInfo));
  1533. sRegistryKey.SetValue("Vector002", REG_BINARY, (LPBYTE) lpApplicationData->wszStringProperty[APP_STRING_CRYPTO], sizeof(lpApplicationData->wszStringProperty[APP_STRING_CRYPTO]));
  1534. //
  1535. // Write out the string data
  1536. //
  1537. for (dwIndex = 0; dwIndex < PROPERTY_COUNT; dwIndex++)
  1538. {
  1539. //
  1540. // If the property is set, is it a string ?
  1541. //
  1542. if ((S_OK == IsApplicationPropertyInitializedWithIndex(dwIndex, lpApplicationData))&&(APP_STRING_NONE != gPropertyInfo[dwIndex].dwStringId))
  1543. {
  1544. //
  1545. // First determine how many bytes we want to write out to the registry
  1546. //
  1547. ZeroMemory(wszEncryptedString, sizeof(wszEncryptedString));
  1548. dwStringLen = 0;
  1549. do
  1550. {
  1551. wszEncryptedString[dwStringLen] = lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringLen];
  1552. wszEncryptedString[dwStringLen] ^= lpApplicationData->wszStringProperty[APP_STRING_CRYPTO][dwStringLen];
  1553. dwStringLen++;
  1554. }
  1555. while (0 != lpApplicationData->wszStringProperty[gPropertyInfo[dwIndex].dwStringId][dwStringLen-1]);
  1556. //
  1557. // Write out the encrypted string into a binary buffer into the registry
  1558. //
  1559. sprintf(szString, "Vector%03x", gPropertyInfo[dwIndex].dwStringId + 2);
  1560. sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) wszEncryptedString, dwStringLen*2);
  1561. }
  1562. }
  1563. //
  1564. // Close sRegistryKey
  1565. //
  1566. sRegistryKey.CloseKey();
  1567. sLock.UnLock();
  1568. return S_OK;
  1569. }
  1570. //////////////////////////////////////////////////////////////////////////////////////////////
  1571. //
  1572. //////////////////////////////////////////////////////////////////////////////////////////////
  1573. STDMETHODIMP CInformationManager::SetApplicationState(const LPAPPLICATION_DATA lpApplicationData, const GUID * lpInstanceGuid)
  1574. {
  1575. FUNCTION("CInfoMgr::SetApplicationState ()");
  1576. CLock sLock(&m_CriticalSection);
  1577. APPLICATION_DATA sApplicationData;
  1578. assert(NULL != lpApplicationData);
  1579. sLock.Lock();
  1580. memcpy(&sApplicationData, lpApplicationData, sizeof(APPLICATION_DATA));
  1581. if (SUCCEEDED(GetApplicationData(&sApplicationData)))
  1582. {
  1583. sApplicationData.sBaseInfo.dwState = lpApplicationData->sBaseInfo.dwState;
  1584. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_STATE, &sApplicationData);
  1585. SetApplicationData(&sApplicationData, lpInstanceGuid);
  1586. }
  1587. else
  1588. {
  1589. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1590. }
  1591. sLock.UnLock();
  1592. return S_OK;
  1593. }
  1594. //////////////////////////////////////////////////////////////////////////////////////////////
  1595. //
  1596. //////////////////////////////////////////////////////////////////////////////////////////////
  1597. STDMETHODIMP CInformationManager::AssignDeviceToApplication(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
  1598. {
  1599. FUNCTION("CInfoMgr::AssignDeviceToApplication ()");
  1600. CLock sLock(&m_CriticalSection);
  1601. DEVICE_RECORD sDeviceRecord;
  1602. assert(NULL != lpApplicationData);
  1603. sLock.Lock();
  1604. //
  1605. // Make sure that dwDeviceIndex points to a valid device
  1606. //
  1607. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  1608. {
  1609. THROW(E_UNEXPECTED);
  1610. }
  1611. //
  1612. // Get the device record
  1613. //
  1614. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  1615. //
  1616. // Update the lpApplicationData
  1617. //
  1618. memcpy(&(lpApplicationData->sBaseInfo.sDeviceGuid), &(sDeviceRecord.sDeviceGuid), sizeof(GUID));
  1619. //
  1620. // Validate the field
  1621. //
  1622. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_DEVICEGUID, lpApplicationData);
  1623. sLock.UnLock();
  1624. return S_OK;
  1625. }
  1626. //////////////////////////////////////////////////////////////////////////////////////////////
  1627. //
  1628. //////////////////////////////////////////////////////////////////////////////////////////////
  1629. STDMETHODIMP CInformationManager::DownsizeApplication(const DWORD dwRequiredKilobytes, const LPAPPLICATION_DATA lpApplicationData)
  1630. {
  1631. FUNCTION("CInfoMgr::DownsizeApplication ()");
  1632. HRESULT hResult = E_FAIL;
  1633. CHAR szExeLine[MAX_PATH_CHARCOUNT];
  1634. CHAR szCmdLine[MAX_PATH_CHARCOUNT];
  1635. PROCESS_INFORMATION sProcessInformation;
  1636. assert(NULL != lpApplicationData);
  1637. //
  1638. // Make sure the application is not locked
  1639. //
  1640. if (S_FALSE == IsApplicationLocked(lpApplicationData))
  1641. {
  1642. //
  1643. // Make sure the setup root path exists
  1644. //
  1645. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
  1646. {
  1647. THROW(E_UNEXPECTED);
  1648. }
  1649. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1650. {
  1651. DisableApplication(lpApplicationData);
  1652. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1653. }
  1654. //
  1655. // Make sure the application is in a proper state
  1656. //
  1657. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
  1658. {
  1659. //
  1660. // Make sure the application is not pinned
  1661. //
  1662. if (FALSE == IsApplicationPinned(lpApplicationData))
  1663. {
  1664. //
  1665. // Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
  1666. //
  1667. ZeroMemory(szExeLine, sizeof(szExeLine));
  1668. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, lpApplicationData))
  1669. {
  1670. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DOWNSIZECMDLINE]), szExeLine, sizeof(szExeLine));
  1671. }
  1672. else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1673. {
  1674. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
  1675. }
  1676. if (1 < StrLenA(szExeLine))
  1677. {
  1678. //
  1679. // Trigger the wait event
  1680. //
  1681. if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_DOWNSIZE)))
  1682. {
  1683. //
  1684. // Construct the downsize command line
  1685. //
  1686. 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]);
  1687. if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
  1688. {
  1689. CloseHandle(sProcessInformation.hThread);
  1690. CloseHandle(sProcessInformation.hProcess);
  1691. hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_DOWNSIZE, 150000, 150000);
  1692. }
  1693. else
  1694. {
  1695. KillWaitEvent(lpApplicationData, WAIT_FINALIZE_DOWNSIZE);
  1696. }
  1697. }
  1698. }
  1699. }
  1700. else
  1701. {
  1702. hResult = S_OK;
  1703. }
  1704. }
  1705. }
  1706. else
  1707. {
  1708. hResult = APPMAN_E_OBJECTLOCKED;
  1709. }
  1710. return hResult;
  1711. }
  1712. //////////////////////////////////////////////////////////////////////////////////////////////
  1713. //
  1714. //////////////////////////////////////////////////////////////////////////////////////////////
  1715. STDMETHODIMP CInformationManager::ReInstallApplication(const LPAPPLICATION_DATA lpApplicationData)
  1716. {
  1717. FUNCTION("CInfoMgr::ReInstallApplication ()");
  1718. HRESULT hResult = E_FAIL;
  1719. CHAR szExeLine[MAX_PATH_CHARCOUNT];
  1720. CHAR szCmdLine[MAX_PATH_CHARCOUNT];
  1721. PROCESS_INFORMATION sProcessInformation;
  1722. assert(NULL != lpApplicationData);
  1723. //
  1724. // Make sure the application is in a proper state
  1725. //
  1726. if ((APP_STATE_READY | APP_STATE_DOWNSIZED | APP_STATE_DOWNSIZING) & lpApplicationData->sBaseInfo.dwState)
  1727. {
  1728. //
  1729. // Make sure the application root path exists
  1730. //
  1731. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
  1732. {
  1733. THROW(E_UNEXPECTED);
  1734. }
  1735. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
  1736. {
  1737. m_Win32API.CreateDirectory(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH], TRUE);
  1738. }
  1739. //
  1740. // Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
  1741. //
  1742. ZeroMemory(szExeLine, sizeof(szExeLine));
  1743. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, lpApplicationData))
  1744. {
  1745. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_REINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
  1746. }
  1747. else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1748. {
  1749. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
  1750. }
  1751. if (1 < StrLenA(szExeLine))
  1752. {
  1753. //
  1754. // Trigger the wait event
  1755. //
  1756. if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_REINSTALL)))
  1757. {
  1758. //
  1759. // Construct the downsize command line
  1760. //
  1761. 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]);
  1762. if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
  1763. {
  1764. CloseHandle(sProcessInformation.hThread);
  1765. CloseHandle(sProcessInformation.hProcess);
  1766. hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_REINSTALL, 40000, 0xffffffff);
  1767. }
  1768. else
  1769. {
  1770. KillWaitEvent(lpApplicationData, WAIT_FINALIZE_REINSTALL);
  1771. }
  1772. }
  1773. }
  1774. }
  1775. return hResult;
  1776. }
  1777. //////////////////////////////////////////////////////////////////////////////////////////////
  1778. //
  1779. //////////////////////////////////////////////////////////////////////////////////////////////
  1780. STDMETHODIMP CInformationManager::UnInstallApplication(const LPAPPLICATION_DATA lpApplicationData)
  1781. {
  1782. FUNCTION("CInfoMgr::UnInstallApplication ()");
  1783. HRESULT hResult = E_FAIL;
  1784. CHAR szExeLine[MAX_PATH_CHARCOUNT];
  1785. CHAR szCmdLine[MAX_PATH_CHARCOUNT];
  1786. PROCESS_INFORMATION sProcessInformation;
  1787. assert(NULL != lpApplicationData);
  1788. //
  1789. // Make sure the setup root path exists
  1790. //
  1791. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
  1792. {
  1793. THROW(E_UNEXPECTED);
  1794. }
  1795. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1796. {
  1797. DisableApplication(lpApplicationData);
  1798. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1799. }
  1800. //
  1801. // Are we using the APP_STRING_UNINSTALLCMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
  1802. //
  1803. ZeroMemory(szExeLine, sizeof(szExeLine));
  1804. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
  1805. {
  1806. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
  1807. }
  1808. else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1809. {
  1810. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
  1811. }
  1812. if (1 < StrLenA(szExeLine))
  1813. {
  1814. //
  1815. // Trigger the wait event
  1816. //
  1817. 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]);
  1818. if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
  1819. {
  1820. CloseHandle(sProcessInformation.hThread);
  1821. CloseHandle(sProcessInformation.hProcess);
  1822. }
  1823. }
  1824. return hResult;
  1825. }
  1826. //////////////////////////////////////////////////////////////////////////////////////////////
  1827. //
  1828. //////////////////////////////////////////////////////////////////////////////////////////////
  1829. STDMETHODIMP CInformationManager::UnInstallApplicationWait(const LPAPPLICATION_DATA lpApplicationData)
  1830. {
  1831. FUNCTION("CInformationManager::UnInstallApplicationWait (const LPAPPLICATION_DATA lpApplicationData)");
  1832. HRESULT hResult = E_FAIL;
  1833. CHAR szExeLine[MAX_PATH_CHARCOUNT];
  1834. CHAR szCmdLine[MAX_PATH_CHARCOUNT];
  1835. PROCESS_INFORMATION sProcessInformation;
  1836. assert(NULL != lpApplicationData);
  1837. //
  1838. // Make sure the setup root path exists
  1839. //
  1840. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
  1841. {
  1842. THROW(E_UNEXPECTED);
  1843. }
  1844. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1845. {
  1846. DisableApplication(lpApplicationData);
  1847. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1848. }
  1849. //
  1850. // Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
  1851. //
  1852. ZeroMemory(szExeLine, sizeof(szExeLine));
  1853. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, lpApplicationData))
  1854. {
  1855. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_UNINSTALLCMDLINE]), szExeLine, sizeof(szExeLine));
  1856. }
  1857. else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1858. {
  1859. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
  1860. }
  1861. if (1 < StrLenA(szExeLine))
  1862. {
  1863. //
  1864. // Trigger the wait event
  1865. //
  1866. if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_UNINSTALL)))
  1867. {
  1868. //
  1869. // Construct the downsize command line
  1870. //
  1871. 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]);
  1872. if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
  1873. {
  1874. CloseHandle(sProcessInformation.hThread);
  1875. CloseHandle(sProcessInformation.hProcess);
  1876. hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_UNINSTALL, 40000, 0xffffffff);
  1877. }
  1878. else
  1879. {
  1880. KillWaitEvent(lpApplicationData, WAIT_FINALIZE_UNINSTALL);
  1881. }
  1882. }
  1883. }
  1884. return hResult;
  1885. }
  1886. //////////////////////////////////////////////////////////////////////////////////////////////
  1887. //
  1888. //////////////////////////////////////////////////////////////////////////////////////////////
  1889. STDMETHODIMP CInformationManager::SelfTestApplication(const LPAPPLICATION_DATA lpApplicationData)
  1890. {
  1891. FUNCTION("CInfoMgr::SelfTestApplication ()");
  1892. HRESULT hResult = E_FAIL;
  1893. CHAR szExeLine[MAX_PATH_CHARCOUNT];
  1894. CHAR szCmdLine[MAX_PATH_CHARCOUNT];
  1895. PROCESS_INFORMATION sProcessInformation;
  1896. assert(NULL != lpApplicationData);
  1897. //
  1898. // Make sure the setup root path exists
  1899. //
  1900. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, lpApplicationData))
  1901. {
  1902. THROW(E_UNEXPECTED);
  1903. }
  1904. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  1905. {
  1906. DisableApplication(lpApplicationData);
  1907. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  1908. }
  1909. //
  1910. // Make sure the application root path exists
  1911. //
  1912. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, lpApplicationData))
  1913. {
  1914. THROW(E_UNEXPECTED);
  1915. }
  1916. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
  1917. {
  1918. m_Win32API.CreateDirectory(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH], TRUE);
  1919. }
  1920. //
  1921. // Are we using the IDX_PROPERTY_DOWNSIZECMDLINE or IDX_PROPERTY_DEFAULTSETUPEXECMDLINE
  1922. //
  1923. ZeroMemory(szExeLine, sizeof(szExeLine));
  1924. if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, lpApplicationData))
  1925. {
  1926. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_SELFTESTCMDLINE]), szExeLine, sizeof(szExeLine));
  1927. }
  1928. else if (S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, lpApplicationData))
  1929. {
  1930. m_Win32API.WideCharToMultiByte(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE], sizeof(lpApplicationData->wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]), szExeLine, sizeof(szExeLine));
  1931. }
  1932. if (1 < StrLenA(szExeLine))
  1933. {
  1934. //
  1935. // Trigger the wait event
  1936. //
  1937. if (SUCCEEDED(InitializeWaitEvent(lpApplicationData, WAIT_FINALIZE_SELFTEST)))
  1938. {
  1939. //
  1940. // Construct the downsize command line
  1941. //
  1942. 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]);
  1943. if (m_Win32API.CreateProcess(szCmdLine, &sProcessInformation))
  1944. {
  1945. CloseHandle(sProcessInformation.hThread);
  1946. CloseHandle(sProcessInformation.hProcess);
  1947. hResult = WaitForEventCompletion(lpApplicationData, WAIT_FINALIZE_SELFTEST, 40000, 0xffffffff);
  1948. }
  1949. else
  1950. {
  1951. KillWaitEvent(lpApplicationData, WAIT_FINALIZE_SELFTEST);
  1952. }
  1953. }
  1954. }
  1955. return hResult;
  1956. }
  1957. //////////////////////////////////////////////////////////////////////////////////////////////
  1958. //
  1959. //////////////////////////////////////////////////////////////////////////////////////////////
  1960. STDMETHODIMP CInformationManager::RunApplication(const LPAPPLICATION_DATA lpApplicationData, const DWORD dwRunFlags, const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
  1961. {
  1962. FUNCTION("CInfoMgr::RunApplication ()");
  1963. HRESULT hResult = S_OK;
  1964. APPLICATION_DATA sApplicationData;
  1965. WCHAR wszParameters[MAX_PATH_CHARCOUNT];
  1966. WCHAR wszCommandLine[MAX_PATH_CHARCOUNT];
  1967. CWin32API sWin32API;
  1968. BOOL fRunning = FALSE;
  1969. PROCESS_INFORMATION sProcessInformation;
  1970. //
  1971. // Make a local copy of the application object
  1972. //
  1973. memcpy((LPVOID) &sApplicationData, (LPVOID) lpApplicationData, sizeof(sApplicationData));
  1974. hResult = GetApplicationData(&sApplicationData);
  1975. if (FAILED(hResult))
  1976. {
  1977. THROW(hResult);
  1978. }
  1979. //
  1980. // Ready the application
  1981. //
  1982. ReadyApplication(&sApplicationData);
  1983. //
  1984. // Build the command line parameters
  1985. //
  1986. ZeroMemory(wszParameters, sizeof(wszParameters));
  1987. if ((APP_PROPERTY_STR_ANSI == dwStringMask)||(APP_PROPERTY_STR_UNICODE == dwStringMask))
  1988. {
  1989. //
  1990. // Check to make sure the parameters are valid
  1991. //
  1992. if (NULL != lpData)
  1993. {
  1994. if (IsBadReadPtr(lpData, dwDataLen))
  1995. {
  1996. THROW(APPMAN_E_INVALIDPARAMETERS);
  1997. }
  1998. if (0 < dwDataLen)
  1999. {
  2000. //
  2001. // Make sure the command line parameters are converted to unicode
  2002. //
  2003. if (APP_PROPERTY_STR_ANSI == dwStringMask)
  2004. {
  2005. if (MAX_PATH_CHARCOUNT < StrLenA((LPCSTR) lpData))
  2006. {
  2007. THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
  2008. }
  2009. else
  2010. {
  2011. sWin32API.MultiByteToWideChar((LPCSTR) lpData, dwDataLen, wszParameters, MAX_PATH_CHARCOUNT);
  2012. }
  2013. }
  2014. else
  2015. {
  2016. if (MAX_PATH_CHARCOUNT < StrLenW((LPCWSTR) lpData))
  2017. {
  2018. THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
  2019. }
  2020. else
  2021. {
  2022. memcpy(wszParameters, lpData, StrLenW((LPCWSTR) lpData) * 2);
  2023. }
  2024. }
  2025. }
  2026. }
  2027. }
  2028. else
  2029. {
  2030. if (0 != dwStringMask)
  2031. {
  2032. THROW(APPMAN_E_INVALIDPARAMETERS);
  2033. }
  2034. }
  2035. //
  2036. // Construct the command line
  2037. //
  2038. if (1 < StrLenW(wszParameters))
  2039. {
  2040. //
  2041. // Make sure the total lenght does not exceed MAX_PATH_CHARCOUNT
  2042. //
  2043. if (MAX_PATH_CHARCOUNT < (StrLenW(sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE])+StrLenW(wszParameters)))
  2044. {
  2045. THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
  2046. }
  2047. wcscpy(wszCommandLine, sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
  2048. wcscat(wszCommandLine, L" /AppManStarted ");
  2049. wcscat(wszCommandLine, wszParameters);
  2050. }
  2051. else
  2052. {
  2053. wcscpy(wszCommandLine, sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
  2054. wcscat(wszCommandLine, L" /AppManStarted");
  2055. }
  2056. //
  2057. // Run it
  2058. //
  2059. if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
  2060. {
  2061. fRunning = TRUE;
  2062. }
  2063. else
  2064. {
  2065. if (SUCCEEDED(SelfTestApplication(&sApplicationData)))
  2066. {
  2067. if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
  2068. {
  2069. fRunning = TRUE;
  2070. }
  2071. else
  2072. {
  2073. THROW(E_FAIL);
  2074. }
  2075. }
  2076. else
  2077. {
  2078. THROW(E_FAIL);
  2079. }
  2080. }
  2081. if (fRunning)
  2082. {
  2083. sApplicationData.sAgingInfo.dwUsageCount++;
  2084. GetLocalTime(&(sApplicationData.sAgingInfo.stLastUsedDate));
  2085. SetApplicationData(&sApplicationData, NULL);
  2086. if (APP_RUN_BLOCK & dwRunFlags)
  2087. {
  2088. do
  2089. {
  2090. //
  2091. // Make sure to prevent message pump starvation
  2092. //
  2093. MSG Message;
  2094. while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
  2095. {
  2096. TranslateMessage(&Message);
  2097. DispatchMessage(&Message);
  2098. }
  2099. //
  2100. // Give other threads/processes the time to do stuff
  2101. //
  2102. Sleep(100);
  2103. }
  2104. while (WAIT_TIMEOUT == WaitForSingleObject(sProcessInformation.hProcess, 0));
  2105. }
  2106. CloseHandle(sProcessInformation.hThread);
  2107. CloseHandle(sProcessInformation.hProcess);
  2108. hResult = S_OK;
  2109. }
  2110. return hResult;
  2111. }
  2112. //////////////////////////////////////////////////////////////////////////////////////////////
  2113. //
  2114. //////////////////////////////////////////////////////////////////////////////////////////////
  2115. STDMETHODIMP CInformationManager::PinApplication(const LPAPPLICATION_DATA lpApplicationData, BOOL * lpfPinState)
  2116. {
  2117. FUNCTION("CInfoMgr::PinApplication ()");
  2118. CLock sLock(&m_CriticalSection);
  2119. HRESULT hResult = E_FAIL;
  2120. APPLICATION_DATA sApplicationData;
  2121. BOOL fPinState;
  2122. //
  2123. // Lock the application manager
  2124. //
  2125. sLock.Lock();
  2126. //
  2127. // Define the target pin state
  2128. //
  2129. if (NULL == lpfPinState)
  2130. {
  2131. fPinState = FALSE;
  2132. }
  2133. else
  2134. {
  2135. if (FALSE == *lpfPinState)
  2136. {
  2137. fPinState = FALSE;
  2138. }
  2139. else
  2140. {
  2141. fPinState = TRUE;
  2142. }
  2143. }
  2144. //
  2145. // Make a local copy of the application data in order to get the latest information
  2146. //
  2147. memcpy(&sApplicationData, lpApplicationData, sizeof(APPLICATION_DATA));
  2148. if (FAILED(GetApplicationData(&sApplicationData)))
  2149. {
  2150. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  2151. }
  2152. if ((APP_STATE_READY == sApplicationData.sBaseInfo.dwState)||(APP_STATE_DOWNSIZED == sApplicationData.sBaseInfo.dwState))
  2153. {
  2154. //
  2155. // Update the application data with the new pin state
  2156. //
  2157. sApplicationData.sBaseInfo.dwPinState = fPinState;
  2158. hResult = SetApplicationData(&sApplicationData, NULL);
  2159. }
  2160. else
  2161. {
  2162. hResult = APPMAN_E_INVALIDSTATE;
  2163. }
  2164. //
  2165. // Unlock the application manager
  2166. //
  2167. sLock.UnLock();
  2168. return hResult;
  2169. }
  2170. //////////////////////////////////////////////////////////////////////////////////////////////
  2171. //
  2172. //////////////////////////////////////////////////////////////////////////////////////////////
  2173. STDMETHODIMP CInformationManager::ReadyApplication(const LPAPPLICATION_DATA lpApplicationData)
  2174. {
  2175. FUNCTION("CInfoMgr::ReadyApplication ()");
  2176. ASSOCIATION_INFO sAssociationInfo;
  2177. HRESULT hResult = E_FAIL;
  2178. DWORD dwIndex;
  2179. assert(NULL != lpApplicationData);
  2180. //
  2181. // Find out if any other applications are using this directory
  2182. //
  2183. dwIndex = 0;
  2184. while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
  2185. {
  2186. if (0 == memcmp((LPVOID) &lpApplicationData->sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
  2187. {
  2188. APPLICATION_DATA sApplicationData;
  2189. //
  2190. // Check to make sure the parent is in a ready state
  2191. //
  2192. ZeroMemory(&sApplicationData, sizeof(sApplicationData));
  2193. memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
  2194. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
  2195. if (FAILED(GetApplicationData(&sApplicationData)))
  2196. {
  2197. THROW(E_UNEXPECTED);
  2198. }
  2199. hResult = ReadyApplication(&sApplicationData);
  2200. if (FAILED(hResult))
  2201. {
  2202. THROW(hResult);
  2203. }
  2204. else
  2205. {
  2206. if (FAILED(GetApplicationData(&sApplicationData)))
  2207. {
  2208. THROW(E_UNEXPECTED);
  2209. }
  2210. else
  2211. {
  2212. if (sApplicationData.sBaseInfo.dwState != APP_STATE_READY)
  2213. {
  2214. THROW(APPMAN_E_PARENTAPPNOTREADY);
  2215. }
  2216. }
  2217. }
  2218. }
  2219. dwIndex++;
  2220. }
  2221. //
  2222. // Make sure the application is in a proper state
  2223. //
  2224. if (APP_STATE_READY != lpApplicationData->sBaseInfo.dwState)
  2225. {
  2226. if (SUCCEEDED(ReInstallApplication(lpApplicationData)))
  2227. {
  2228. if (FAILED(GetApplicationData(lpApplicationData)))
  2229. {
  2230. THROW(E_UNEXPECTED);
  2231. }
  2232. else
  2233. {
  2234. if (APP_STATE_READY != lpApplicationData->sBaseInfo.dwState)
  2235. {
  2236. THROW(APPMAN_E_PARENTAPPNOTREADY);
  2237. }
  2238. }
  2239. }
  2240. else
  2241. {
  2242. THROW(APPMAN_E_PARENTAPPNOTREADY);
  2243. }
  2244. }
  2245. else
  2246. {
  2247. //
  2248. // Well the application reports that it is in a ready state but is it ? Check to make sure
  2249. // the root paths exist. If both are gone, remove the application from the registry
  2250. // and throw APPMAN_E_UNKNOWNAPPLICATION. If the root path is missing, call selftest on
  2251. // the application and ready it.
  2252. //
  2253. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_APPROOTPATH]))
  2254. {
  2255. if (FALSE == m_Win32API.FileExists(lpApplicationData->wszStringProperty[APP_STRING_SETUPROOTPATH]))
  2256. {
  2257. RemoveApplicationData(lpApplicationData);
  2258. THROW(APPMAN_E_UNKNOWNAPPLICATION);
  2259. }
  2260. else
  2261. {
  2262. if (FAILED(SelfTestApplication(lpApplicationData)))
  2263. {
  2264. THROW(APPMAN_E_PARENTAPPNOTREADY);
  2265. }
  2266. ReadyApplication(lpApplicationData);
  2267. }
  2268. }
  2269. }
  2270. return S_OK;
  2271. }
  2272. //////////////////////////////////////////////////////////////////////////////////////////////
  2273. //
  2274. //////////////////////////////////////////////////////////////////////////////////////////////
  2275. STDMETHODIMP CInformationManager::DisableApplication(const LPAPPLICATION_DATA lpApplicationData)
  2276. {
  2277. APPLICATION_DATA sApplicationData;
  2278. ASSOCIATION_INFO sAssociationInfo;
  2279. DWORD dwIndex;
  2280. HRESULT hResult;
  2281. //
  2282. // Disable this application
  2283. //
  2284. lpApplicationData->sBaseInfo.dwReservedKilobytes = 0;
  2285. lpApplicationData->sBaseInfo.dwRemovableKilobytes = 0;
  2286. lpApplicationData->sBaseInfo.dwNonRemovableKilobytes = 0;
  2287. lpApplicationData->sBaseInfo.dwState |= APP_STATE_UNSTABLE;
  2288. hResult = SetApplicationData(lpApplicationData, NULL);
  2289. //
  2290. // Disable all of the children of this application
  2291. //
  2292. dwIndex = 0;
  2293. while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
  2294. {
  2295. if (0 == memcmp((LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sParentGuid), sizeof(GUID)))
  2296. {
  2297. ZeroMemory(&sApplicationData, sizeof(sApplicationData));
  2298. memcpy((LPVOID) &(sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID));
  2299. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
  2300. if (SUCCEEDED(GetApplicationData(&sApplicationData)))
  2301. {
  2302. hResult = DisableApplication(&sApplicationData);
  2303. }
  2304. }
  2305. dwIndex++;
  2306. }
  2307. return hResult;
  2308. }
  2309. //////////////////////////////////////////////////////////////////////////////////////////////
  2310. //
  2311. //////////////////////////////////////////////////////////////////////////////////////////////
  2312. STDMETHODIMP_(DWORD) CInformationManager::GetPropertyIndex(const DWORD dwProperty)
  2313. {
  2314. FUNCTION("CInfoMgr::GetPropertyIndex ()");
  2315. DWORD dwIndex;
  2316. DWORD dwPropertyIndex;
  2317. dwIndex = 0;
  2318. dwPropertyIndex = INVALID_PROPERTY_INDEX;
  2319. while ((PROPERTY_COUNT > dwIndex)&&(INVALID_PROPERTY_INDEX == dwPropertyIndex))
  2320. {
  2321. if (gPropertyInfo[dwIndex].dwProperty == dwProperty)
  2322. {
  2323. dwPropertyIndex = dwIndex;
  2324. }
  2325. dwIndex++;
  2326. }
  2327. return dwPropertyIndex;
  2328. }
  2329. //////////////////////////////////////////////////////////////////////////////////////////////
  2330. //
  2331. //////////////////////////////////////////////////////////////////////////////////////////////
  2332. STDMETHODIMP CInformationManager::IsValidApplicationProperty(const DWORD dwProperty)
  2333. {
  2334. FUNCTION("CInfoMgr::IsValidApplicationProperty ()");
  2335. HRESULT hResult = S_FALSE;
  2336. DWORD dwFilteredProperty, dwPropertyModifiers;
  2337. DWORD dwPropertyIndex;
  2338. //
  2339. // What is the base property
  2340. //
  2341. dwFilteredProperty = dwProperty & 0x0000ffff;
  2342. dwPropertyModifiers = dwProperty & 0xffff0000;
  2343. dwPropertyIndex = GetPropertyIndex(dwFilteredProperty);
  2344. if (INVALID_PROPERTY_INDEX != dwPropertyIndex)
  2345. {
  2346. if ((APP_PROPERTY_STR_ANSI == dwPropertyModifiers)||(APP_PROPERTY_STR_UNICODE == dwPropertyModifiers)||(0 == dwPropertyModifiers))
  2347. {
  2348. hResult = S_OK;
  2349. }
  2350. }
  2351. return hResult;
  2352. }
  2353. //////////////////////////////////////////////////////////////////////////////////////////////
  2354. //
  2355. //////////////////////////////////////////////////////////////////////////////////////////////
  2356. STDMETHODIMP CInformationManager::ValidateApplicationPropertyWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
  2357. {
  2358. FUNCTION("CInfoMgr::ValidateApplicationPropertyWithIndex ()");
  2359. lpApplicationData->sBaseInfo.dwLowPropertyMask |= gPropertyInfo[dwPropertyIndex].dwLowPropertyMask;
  2360. lpApplicationData->sBaseInfo.dwHighPropertyMask |= gPropertyInfo[dwPropertyIndex].dwHighPropertyMask;
  2361. return S_OK;
  2362. }
  2363. //////////////////////////////////////////////////////////////////////////////////////////////
  2364. //
  2365. //////////////////////////////////////////////////////////////////////////////////////////////
  2366. STDMETHODIMP CInformationManager::InvalidateApplicationPropertyWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
  2367. {
  2368. FUNCTION("CInfoMgr::InvalidateApplicationPropertyWithIndex ()");
  2369. lpApplicationData->sBaseInfo.dwLowPropertyMask &= ~(gPropertyInfo[dwPropertyIndex].dwLowPropertyMask);
  2370. lpApplicationData->sBaseInfo.dwHighPropertyMask &= ~(gPropertyInfo[dwPropertyIndex].dwHighPropertyMask);
  2371. return S_OK;
  2372. }
  2373. //////////////////////////////////////////////////////////////////////////////////////////////
  2374. //
  2375. //////////////////////////////////////////////////////////////////////////////////////////////
  2376. STDMETHODIMP CInformationManager::IsApplicationPropertyInitializedWithIndex(const DWORD dwPropertyIndex, LPAPPLICATION_DATA lpApplicationData)
  2377. {
  2378. FUNCTION("CInfoMgr::IsApplicationPropertyInitializedWithIndex ()");
  2379. HRESULT hResult = S_FALSE;
  2380. if ((lpApplicationData->sBaseInfo.dwLowPropertyMask & gPropertyInfo[dwPropertyIndex].dwLowPropertyMask)||(lpApplicationData->sBaseInfo.dwHighPropertyMask & gPropertyInfo[dwPropertyIndex].dwHighPropertyMask))
  2381. {
  2382. hResult = S_OK;
  2383. }
  2384. return hResult;
  2385. }
  2386. //////////////////////////////////////////////////////////////////////////////////////////////
  2387. //
  2388. //////////////////////////////////////////////////////////////////////////////////////////////
  2389. STDMETHODIMP CInformationManager::DeleteDirectoryTree(LPCSTR lpszDirectory)
  2390. {
  2391. FUNCTION("CInfoMgr::DeleteDirectoryTree ()");
  2392. HRESULT hResult = E_FAIL;
  2393. if (m_Win32API.RemoveDirectory(lpszDirectory))
  2394. {
  2395. hResult = S_OK;
  2396. }
  2397. return hResult;
  2398. }
  2399. //////////////////////////////////////////////////////////////////////////////////////////////
  2400. //
  2401. //////////////////////////////////////////////////////////////////////////////////////////////
  2402. STDMETHODIMP CInformationManager::DeleteDirectoryTree(LPCWSTR lpwszDirectory)
  2403. {
  2404. FUNCTION("CInfoMgr::DeleteDirectoryTree ()");
  2405. HRESULT hResult = E_FAIL;
  2406. CHAR szString[MAX_PATH_CHARCOUNT];
  2407. if (m_Win32API.WideCharToMultiByte(lpwszDirectory, MAX_PATH_CHARCOUNT, szString, MAX_PATH_CHARCOUNT))
  2408. {
  2409. hResult = DeleteDirectoryTree(szString);
  2410. }
  2411. return hResult;
  2412. }
  2413. //////////////////////////////////////////////////////////////////////////////////////////////
  2414. //
  2415. // The InitializeRegistry() method ensures the following things :
  2416. //
  2417. // (1) That all the required registry entries are initialized properly
  2418. // (2) That the registry entries are in synch with the backup file (if applicable)
  2419. //
  2420. //////////////////////////////////////////////////////////////////////////////////////////////
  2421. STDMETHODIMP CInformationManager::RegInitialize(void)
  2422. {
  2423. FUNCTION("CInfoMgr::RegInitialize ()");
  2424. CLock sLock(&m_CriticalSection);
  2425. CRegistryKey sRegistryKey;
  2426. APPLICATION_DATA sApplicationData;
  2427. DWORD dwKeyDisposition, dwDWORD;
  2428. TEMP_SPACE_RECORD sTempSpaceRecord;
  2429. CHAR szValueName[MAX_PATH_CHARCOUNT];
  2430. WCHAR wszDirectory[MAX_PATH_CHARCOUNT];
  2431. DWORD dwIndex, dwCounter;
  2432. DWORD dwDataType, dwDataLen, dwDataValue, dwValueLen;
  2433. sLock.Lock();
  2434. //
  2435. // Open the root key
  2436. //
  2437. if (S_FALSE == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan"))
  2438. {
  2439. //
  2440. // Hum the root key doesn't exist, let's see if we can create it. Otherwise return APPMAN_E_REINSTALLDX
  2441. //
  2442. THROW(APPMAN_E_REINSTALLDX);
  2443. }
  2444. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_ALL_ACCESS);
  2445. //
  2446. // Make sure the AppMan version is the right version
  2447. //
  2448. if (S_OK == sRegistryKey.CheckForExistingValue("AppManVersion"))
  2449. {
  2450. dwDataLen = sizeof(dwDataValue);
  2451. sRegistryKey.GetValue("AppManVersion", &dwDataType, (BYTE *) &dwDataValue, &dwDataLen);
  2452. if (REG_VERSION > dwDataValue)
  2453. {
  2454. THROW(APPMAN_E_REINSTALLDX);
  2455. }
  2456. }
  2457. //
  2458. // Initialize the AppMan\ReferenceCounter value
  2459. //
  2460. dwDWORD = 0;
  2461. sRegistryKey.SetValue("ReferenceCount", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
  2462. //
  2463. // Initialize the AppMan\Version value
  2464. //
  2465. if (S_FALSE == sRegistryKey.CheckForExistingValue("AppManVersion"))
  2466. {
  2467. dwDWORD = REG_VERSION;
  2468. sRegistryKey.SetValue("AppManVersion", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
  2469. }
  2470. //
  2471. // Initialize wait event extra wait vars
  2472. //
  2473. if (S_FALSE == sRegistryKey.CheckForExistingValue("WaitEntryEventExtraTime"))
  2474. {
  2475. dwDWORD = 0;
  2476. sRegistryKey.SetValue("WaitEntryEventExtraTime", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
  2477. }
  2478. if (S_FALSE == sRegistryKey.CheckForExistingValue("WaitLeaveEventExtraTime"))
  2479. {
  2480. dwDWORD = 0;
  2481. sRegistryKey.SetValue("WaitLeaveEventExtraTime", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
  2482. }
  2483. //
  2484. // Initialize the AppMan\DefaultCacheSize
  2485. //
  2486. if (S_FALSE == sRegistryKey.CheckForExistingValue("DefaultPercentCacheSize"))
  2487. {
  2488. dwDWORD = DEFAULT_PERCENT_CACHE_SIZE;
  2489. sRegistryKey.SetValue("DefaultPercentCacheSize", REG_DWORD, (const BYTE *) &dwDWORD, sizeof(dwDWORD));
  2490. }
  2491. //
  2492. // Insert the original APPLICATION_MANAGER_RECORD
  2493. //
  2494. if (S_FALSE == sRegistryKey.CheckForExistingValue("Vector000"))
  2495. {
  2496. APPLICATION_MANAGER_RECORD sApplicationManagerRecord;
  2497. sApplicationManagerRecord.dwSize = sizeof(APPLICATION_MANAGER_RECORD);
  2498. sApplicationManagerRecord.dwStructId = APPLICATION_MANAGER_STRUCT;
  2499. if (FAILED(CoCreateGuid(&sApplicationManagerRecord.sSystemGuid)))
  2500. {
  2501. THROW(E_UNEXPECTED);
  2502. }
  2503. sApplicationManagerRecord.dwAdvancedMode = FALSE;
  2504. sRegistryKey.SetValue("Vector000", REG_BINARY, (LPBYTE) &sApplicationManagerRecord, sizeof(APPLICATION_MANAGER_RECORD));
  2505. }
  2506. //
  2507. // Create the AppMan\Devices key.
  2508. //
  2509. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2510. //
  2511. // Create the AppMan\Applications key
  2512. //
  2513. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Applications", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2514. //
  2515. // Create the AppMan\Associations key
  2516. //
  2517. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2518. //
  2519. // Create the AppMan\TempAllocation key
  2520. //
  2521. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2522. //
  2523. // Create the AppMan\Cleanup key
  2524. //
  2525. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2526. //
  2527. // Get rid of any leftover locks
  2528. //
  2529. if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock"))
  2530. {
  2531. sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock");
  2532. }
  2533. //
  2534. // Create the AppMan\Lock key
  2535. //
  2536. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Lock", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2537. //
  2538. // Make sure that any leftover wait events are deleted
  2539. //
  2540. if (S_OK == sRegistryKey.CheckForExistingKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent"))
  2541. {
  2542. sRegistryKey.DeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent");
  2543. }
  2544. //
  2545. // Create the AppMan\Lock key
  2546. //
  2547. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, &dwKeyDisposition);
  2548. //
  2549. // Clean up the directories if required
  2550. //
  2551. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", KEY_ALL_ACCESS);
  2552. dwIndex = 0;
  2553. ZeroMemory(szValueName, sizeof(szValueName));
  2554. ZeroMemory(wszDirectory, sizeof(wszDirectory));
  2555. dwValueLen = sizeof(szValueName);
  2556. dwDataLen = sizeof(wszDirectory);
  2557. while (S_OK == sRegistryKey.EnumValues(dwIndex, szValueName, &dwValueLen, &dwDataType, (LPBYTE) wszDirectory, &dwDataLen))
  2558. {
  2559. //
  2560. // Decrypt the cleanup directory
  2561. //
  2562. for (dwCounter = 0; dwCounter < (dwDataLen/2)-1; dwCounter++)
  2563. {
  2564. wszDirectory[dwCounter] ^= 0xffffffff;
  2565. }
  2566. //
  2567. // Attempt to delete the directory to be cleaned up
  2568. //
  2569. if (1 < StrLenW(wszDirectory))
  2570. {
  2571. m_Win32API.RemoveDirectory(wszDirectory);
  2572. if (!m_Win32API.FileExists(wszDirectory))
  2573. {
  2574. sRegistryKey.DeleteValue(szValueName);
  2575. }
  2576. else
  2577. {
  2578. dwIndex++;
  2579. }
  2580. }
  2581. //
  2582. // Get ready for the next loop
  2583. //
  2584. ZeroMemory(szValueName, sizeof(szValueName));
  2585. ZeroMemory(wszDirectory, sizeof(wszDirectory));
  2586. dwValueLen = sizeof(szValueName);
  2587. dwDataLen = sizeof(wszDirectory);
  2588. }
  2589. //
  2590. // Scan through each application record and make sure that none of them have
  2591. // any reserved space assigned to them
  2592. //
  2593. dwIndex = 0;
  2594. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  2595. {
  2596. if (0 < sApplicationData.sBaseInfo.dwReservedKilobytes)
  2597. {
  2598. sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
  2599. InvalidateApplicationPropertyWithIndex(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES, &sApplicationData);
  2600. SetApplicationData(&sApplicationData, NULL);
  2601. }
  2602. dwIndex++;
  2603. }
  2604. //
  2605. // Scan through the temporary directories and delete them
  2606. //
  2607. dwIndex = 0;
  2608. while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
  2609. {
  2610. if (FAILED(RemoveTempSpace(&sTempSpaceRecord)))
  2611. {
  2612. dwIndex++;
  2613. }
  2614. }
  2615. //
  2616. // Close sRegistryKey
  2617. //
  2618. sRegistryKey.CloseKey();
  2619. //
  2620. // Scan through the devices and update their information
  2621. //
  2622. ScanDevices();
  2623. sLock.UnLock();
  2624. return S_OK;
  2625. }
  2626. //////////////////////////////////////////////////////////////////////////////////////////////
  2627. //
  2628. //////////////////////////////////////////////////////////////////////////////////////////////
  2629. STDMETHODIMP CInformationManager::RegFutureDirectoryCleanup(LPCWSTR lpwszDirectory)
  2630. {
  2631. FUNCTION("CInfoMgr::RegFutureDirectoryCleanup ()");
  2632. CLock sLock(&m_CriticalSection);
  2633. CRegistryKey sRegistryKey;
  2634. DWORD dwDefaultValue, dwIndex;
  2635. GUID sGuid;
  2636. HRESULT hResult = E_FAIL;
  2637. CHAR szValueName[64];
  2638. WCHAR wszDirectory[MAX_PATH_CHARCOUNT+1];
  2639. sLock.Lock();
  2640. //
  2641. // Encrypt the key.
  2642. //
  2643. dwIndex = 0;
  2644. while (0 != lpwszDirectory[dwIndex])
  2645. {
  2646. wszDirectory[dwIndex] = (WCHAR)(lpwszDirectory[dwIndex] ^ 0xffffffff);
  2647. dwIndex++;
  2648. }
  2649. wszDirectory[dwIndex] = 0;
  2650. //
  2651. // Generate a unique value name for the key
  2652. //
  2653. if (FAILED(CoCreateGuid(&sGuid)))
  2654. {
  2655. THROW(E_UNEXPECTED);
  2656. }
  2657. 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]);
  2658. //
  2659. // Add the directory name to the AppMan\Cleanup registry key
  2660. //
  2661. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Cleanup", KEY_ALL_ACCESS);
  2662. dwDefaultValue = 1;
  2663. sRegistryKey.SetValue(szValueName, REG_BINARY, (LPBYTE) wszDirectory, (dwIndex+1)*2);
  2664. //
  2665. // Close sRegistryKey
  2666. //
  2667. sRegistryKey.CloseKey();
  2668. sLock.UnLock();
  2669. return hResult;
  2670. }
  2671. //////////////////////////////////////////////////////////////////////////////////////////////
  2672. //
  2673. //////////////////////////////////////////////////////////////////////////////////////////////
  2674. STDMETHODIMP CInformationManager::InitializeWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
  2675. {
  2676. FUNCTION("CInfoMgr::InitializeWaitEvent()");
  2677. CLock sLock(&m_CriticalSection);
  2678. CRegistryKey sRegistryKey;
  2679. WAIT_INFO sWaitInfo;
  2680. GUID sEncryptedGuid;
  2681. CHAR szGuid[40];
  2682. DWORD dwDataType, dwDataSize;
  2683. HRESULT hResult = E_FAIL;
  2684. //
  2685. // Make sure that lpApplicationData and dwWaitEvent are valid
  2686. //
  2687. if ((NULL == lpApplicationData)||(IsBadReadPtr(lpApplicationData, sizeof(APPLICATION_DATA)))||(WAIT_EVENT_COUNT <= dwWaitEvent))
  2688. {
  2689. THROW(E_UNEXPECTED);
  2690. }
  2691. //
  2692. // Lock the information manager
  2693. //
  2694. sLock.Lock();
  2695. //
  2696. // Open the root registry key for the wait events
  2697. //
  2698. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
  2699. //
  2700. // Make sure we have a valid application guid within lpApplicationData
  2701. //
  2702. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  2703. {
  2704. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  2705. }
  2706. //
  2707. // Computer the encrypted guid for lpApplicationData
  2708. //
  2709. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  2710. EncryptGuid(&sEncryptedGuid);
  2711. 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]);
  2712. //
  2713. // Initialize the local sWaitEvent to Zero
  2714. //
  2715. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  2716. //
  2717. // Is there an existing event initialized for lpApplicationGuid
  2718. //
  2719. if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
  2720. {
  2721. //
  2722. // There is already a wait event in the system. Let's check to see if the wait event
  2723. // conflicts with this one or whether or not we can just add to it.
  2724. //
  2725. dwDataSize = sizeof(sWaitInfo);
  2726. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  2727. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  2728. {
  2729. //
  2730. // The registry entry is bogus, delete it
  2731. //
  2732. sRegistryKey.DeleteValue(szGuid);
  2733. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  2734. }
  2735. }
  2736. //
  2737. // Initialize the wait event if possible
  2738. //
  2739. if (0 != sWaitInfo.dwEventCount[dwWaitEvent])
  2740. {
  2741. THROW(E_UNEXPECTED);
  2742. }
  2743. else
  2744. {
  2745. sWaitInfo.dwEventCount[dwWaitEvent] = 0xffffffff;
  2746. }
  2747. //
  2748. // Write out the event
  2749. //
  2750. sWaitInfo.dwSize = sizeof(sWaitInfo);
  2751. sWaitInfo.dwStructId = WAIT_STRUCT;
  2752. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
  2753. //
  2754. // Close the registry
  2755. //
  2756. sRegistryKey.CloseKey();
  2757. //
  2758. // unlock the information manager
  2759. //
  2760. sLock.UnLock();
  2761. return hResult;
  2762. }
  2763. //////////////////////////////////////////////////////////////////////////////////////////////
  2764. //
  2765. //////////////////////////////////////////////////////////////////////////////////////////////
  2766. STDMETHODIMP CInformationManager::EnterWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent, const GUID * lpInstanceGuid)
  2767. {
  2768. FUNCTION("CInfoMgr::EnterWaitEvent()");
  2769. CLock sLock(&m_CriticalSection);
  2770. CRegistryKey sRegistryKey;
  2771. WAIT_INFO sWaitInfo;
  2772. GUID sEncryptedGuid;
  2773. CHAR szGuid[40];
  2774. DWORD dwDataType, dwDataSize;
  2775. HRESULT hResult = E_FAIL;
  2776. //
  2777. // Lock the information manager
  2778. //
  2779. sLock.Lock();
  2780. //
  2781. // Open the root registry key for the wait events
  2782. //
  2783. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
  2784. //
  2785. // Make sure we have a valid application guid within lpApplicationData
  2786. //
  2787. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  2788. {
  2789. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  2790. }
  2791. //
  2792. // Computer the encrypted guid for lpApplicationData
  2793. //
  2794. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  2795. EncryptGuid(&sEncryptedGuid);
  2796. 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]);
  2797. //
  2798. // Initialize the local sWaitEvent to Zero
  2799. //
  2800. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  2801. //
  2802. // Is there an existing event initialized for lpApplicationGuid
  2803. //
  2804. if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
  2805. {
  2806. //
  2807. // There is already a wait event in the system. Let's check to see if the wait event
  2808. // conflicts with this one or whether or not we can just add to it.
  2809. //
  2810. dwDataSize = sizeof(sWaitInfo);
  2811. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  2812. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  2813. {
  2814. THROW(E_UNEXPECTED);
  2815. }
  2816. //
  2817. // Initialize the wait event if possible
  2818. //
  2819. if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
  2820. {
  2821. sWaitInfo.dwEventCount[dwWaitEvent] = 1;
  2822. }
  2823. else if (0 < sWaitInfo.dwEventCount[dwWaitEvent])
  2824. {
  2825. (sWaitInfo.dwEventCount[dwWaitEvent])++;
  2826. }
  2827. //
  2828. // Save the instance guid
  2829. //
  2830. if (NULL != lpInstanceGuid)
  2831. {
  2832. memcpy(&sWaitInfo.guidInstanceGuid, lpInstanceGuid, sizeof(GUID));
  2833. }
  2834. //
  2835. // Write out the event
  2836. //
  2837. sWaitInfo.dwSize = sizeof(sWaitInfo);
  2838. sWaitInfo.dwStructId = WAIT_STRUCT;
  2839. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
  2840. }
  2841. //
  2842. // Close the registry
  2843. //
  2844. sRegistryKey.CloseKey();
  2845. //
  2846. // unlock the information manager
  2847. //
  2848. sLock.UnLock();
  2849. return hResult;
  2850. }
  2851. //////////////////////////////////////////////////////////////////////////////////////////////
  2852. //
  2853. //////////////////////////////////////////////////////////////////////////////////////////////
  2854. STDMETHODIMP CInformationManager::LeaveWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
  2855. {
  2856. FUNCTION("CInfoMgr::LeaveWaitEvent()");
  2857. CLock sLock(&m_CriticalSection);
  2858. CRegistryKey sRegistryKey;
  2859. WAIT_INFO sWaitInfo;
  2860. GUID sEncryptedGuid;
  2861. CHAR szGuid[40];
  2862. DWORD dwDataType, dwDataSize;
  2863. HRESULT hResult = E_FAIL;
  2864. //
  2865. // Lock the information manager
  2866. //
  2867. sLock.Lock();
  2868. //
  2869. // Open the root registry key for the wait events
  2870. //
  2871. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
  2872. //
  2873. // Make sure we have a valid application guid within lpApplicationData
  2874. //
  2875. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  2876. {
  2877. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  2878. }
  2879. //
  2880. // Computer the encrypted guid for lpApplicationData
  2881. //
  2882. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  2883. EncryptGuid(&sEncryptedGuid);
  2884. 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]);
  2885. //
  2886. // Initialize the local sWaitEvent to Zero
  2887. //
  2888. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  2889. //
  2890. // Is there an existing event initialized for lpApplicationGuid
  2891. //
  2892. if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
  2893. {
  2894. //
  2895. // There is already a wait event in the system. Let's check to see if the wait event
  2896. // conflicts with this one or whether or not we can just add to it.
  2897. //
  2898. dwDataSize = sizeof(sWaitInfo);
  2899. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  2900. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  2901. {
  2902. THROW(E_UNEXPECTED);
  2903. }
  2904. //
  2905. // Initialize the wait event if possible
  2906. //
  2907. if ((0 < sWaitInfo.dwEventCount[dwWaitEvent])&&(0xffffffff != sWaitInfo.dwEventCount[dwWaitEvent]))
  2908. {
  2909. sWaitInfo.dwEventCount[dwWaitEvent]--;
  2910. }
  2911. //
  2912. // Write out the event
  2913. //
  2914. sWaitInfo.dwSize = sizeof(sWaitInfo);
  2915. sWaitInfo.dwStructId = WAIT_STRUCT;
  2916. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
  2917. }
  2918. //
  2919. // Close the registry
  2920. //
  2921. sRegistryKey.CloseKey();
  2922. //
  2923. // unlock the information manager
  2924. //
  2925. sLock.UnLock();
  2926. return hResult;
  2927. }
  2928. //////////////////////////////////////////////////////////////////////////////////////////////
  2929. //
  2930. //////////////////////////////////////////////////////////////////////////////////////////////
  2931. STDMETHODIMP CInformationManager::WaitForEventCompletion(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent, const DWORD dwEntryMilliseconds, const DWORD dwExitMilliseconds)
  2932. {
  2933. FUNCTION("CInfoMgr::WaitForEventCompletion()");
  2934. CLock sLock(&m_CriticalSection);
  2935. CRegistryKey sRegistryKey;
  2936. WAIT_INFO sWaitInfo;
  2937. GUID sEncryptedGuid;
  2938. CHAR szGuid[40];
  2939. DWORD dwStartTime;
  2940. DWORD dwDataType, dwDataSize;
  2941. DWORD dwEntryTime, dwExitTime;
  2942. BOOL fDone;
  2943. HRESULT hResult = E_FAIL;
  2944. //
  2945. // Open the root registry key for the wait events
  2946. //
  2947. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
  2948. //
  2949. // Make sure we have a valid application guid within lpApplicationData
  2950. //
  2951. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  2952. {
  2953. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  2954. }
  2955. //
  2956. // Computer the encrypted guid for lpApplicationData
  2957. //
  2958. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  2959. EncryptGuid(&sEncryptedGuid);
  2960. 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]);
  2961. //
  2962. // Initialize the local sWaitEvent to Zero
  2963. //
  2964. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  2965. //
  2966. // Add bias to wait times
  2967. //
  2968. dwEntryTime = dwEntryMilliseconds + GetExtraWaitEventEntryTime();
  2969. dwExitTime = dwExitMilliseconds + GetExtraWaitEventExitTime();
  2970. //
  2971. // Wait for the event to start
  2972. //
  2973. dwStartTime = GetTickCount();
  2974. fDone = FALSE;
  2975. do
  2976. {
  2977. //
  2978. // Lock the information manager
  2979. //
  2980. sLock.Lock();
  2981. //
  2982. // Read in the event record
  2983. //
  2984. dwDataSize = sizeof(sWaitInfo);
  2985. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  2986. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  2987. {
  2988. THROW(E_UNEXPECTED);
  2989. }
  2990. //
  2991. // unlock the information manager
  2992. //
  2993. sLock.UnLock();
  2994. //
  2995. // Is the event started
  2996. //
  2997. if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
  2998. {
  2999. //
  3000. // Make sure to prevent message pump starvation
  3001. //
  3002. MSG Message;
  3003. while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
  3004. {
  3005. TranslateMessage(&Message);
  3006. DispatchMessage(&Message);
  3007. }
  3008. //
  3009. // Give other threads/processes the time to do stuff
  3010. //
  3011. Sleep(100);
  3012. }
  3013. else if (0 <= sWaitInfo.dwEventCount[dwWaitEvent])
  3014. {
  3015. fDone = TRUE;
  3016. }
  3017. }
  3018. while ((FALSE == fDone)&&(dwEntryTime > (GetTickCount() - dwStartTime)));
  3019. if (TRUE == fDone)
  3020. {
  3021. //
  3022. // Wait for the event to end
  3023. //
  3024. dwStartTime = GetTickCount();
  3025. fDone = FALSE;
  3026. do
  3027. {
  3028. //
  3029. // Lock the information manager
  3030. //
  3031. sLock.Lock();
  3032. //
  3033. // Read in the event record
  3034. //
  3035. dwDataSize = sizeof(sWaitInfo);
  3036. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  3037. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  3038. {
  3039. THROW(E_UNEXPECTED);
  3040. }
  3041. //
  3042. // Is the event over
  3043. //
  3044. if (0xffffffff == sWaitInfo.dwEventCount[dwWaitEvent])
  3045. {
  3046. THROW(E_UNEXPECTED);
  3047. }
  3048. else if (0 == sWaitInfo.dwEventCount[dwWaitEvent])
  3049. {
  3050. fDone = TRUE;
  3051. //
  3052. // Should we delete the wait event from the registry
  3053. //
  3054. if (0 == (sWaitInfo.dwEventCount[WAIT_FINALIZE_DOWNSIZE] + sWaitInfo.dwEventCount[WAIT_FINALIZE_REINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_UNINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_SELFTEST]))
  3055. {
  3056. sRegistryKey.DeleteValue(szGuid);
  3057. }
  3058. //
  3059. // Did the owner thread die on us
  3060. //
  3061. if (S_FALSE == IsInstanceGuidStillAlive(&sWaitInfo.guidInstanceGuid))
  3062. {
  3063. if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
  3064. {
  3065. sRegistryKey.DeleteValue(szGuid);
  3066. }
  3067. }
  3068. }
  3069. //
  3070. // unlock the information manager
  3071. //
  3072. sLock.UnLock();
  3073. //
  3074. // Should we sleep ?
  3075. //
  3076. if (FALSE == fDone)
  3077. {
  3078. //
  3079. // Make sure to prevent message pump starvation
  3080. //
  3081. MSG Message;
  3082. while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
  3083. {
  3084. TranslateMessage(&Message);
  3085. DispatchMessage(&Message);
  3086. }
  3087. //
  3088. // Give other threads/processes the time to do stuff
  3089. //
  3090. Sleep(100);
  3091. }
  3092. }
  3093. while ((FALSE == fDone)&&(dwExitTime > (GetTickCount() - dwStartTime)));
  3094. //
  3095. // Did the event finish
  3096. //
  3097. if (TRUE == fDone)
  3098. {
  3099. hResult = S_OK;
  3100. }
  3101. }
  3102. else
  3103. {
  3104. //
  3105. // The wait event has expired unsuccessfully. We will now delete the wait event since it
  3106. // will no longer be used
  3107. //
  3108. sRegistryKey.DeleteValue(szGuid);
  3109. }
  3110. //
  3111. // Close the registry
  3112. //
  3113. sRegistryKey.CloseKey();
  3114. return hResult;
  3115. }
  3116. //////////////////////////////////////////////////////////////////////////////////////////////
  3117. //
  3118. //////////////////////////////////////////////////////////////////////////////////////////////
  3119. STDMETHODIMP CInformationManager::KillWaitEvent(LPAPPLICATION_DATA lpApplicationData, const DWORD dwWaitEvent)
  3120. {
  3121. FUNCTION("CInfoMgr::KillWaitEvent()");
  3122. CLock sLock(&m_CriticalSection);
  3123. CRegistryKey sRegistryKey;
  3124. WAIT_INFO sWaitInfo;
  3125. GUID sEncryptedGuid;
  3126. CHAR szGuid[40];
  3127. DWORD dwDataType, dwDataSize;
  3128. HRESULT hResult = E_FAIL;
  3129. //
  3130. // Lock the information manager
  3131. //
  3132. sLock.Lock();
  3133. //
  3134. // Open the root registry key for the wait events
  3135. //
  3136. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\WaitEvent", KEY_ALL_ACCESS);
  3137. //
  3138. // Make sure we have a valid application guid within lpApplicationData
  3139. //
  3140. if (S_OK != IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, lpApplicationData))
  3141. {
  3142. THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
  3143. }
  3144. //
  3145. // Computer the encrypted guid for lpApplicationData
  3146. //
  3147. memcpy((LPVOID) &sEncryptedGuid, (LPVOID) &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  3148. EncryptGuid(&sEncryptedGuid);
  3149. 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]);
  3150. //
  3151. // Initialize the local sWaitEvent to Zero
  3152. //
  3153. ZeroMemory(&sWaitInfo, sizeof(sWaitInfo));
  3154. //
  3155. // Is there an existing event initialized for lpApplicationGuid
  3156. //
  3157. if (S_OK == sRegistryKey.CheckForExistingValue(szGuid))
  3158. {
  3159. //
  3160. // There is already a wait event in the system. Let's check to see if the wait event
  3161. // conflicts with this one or whether or not we can just add to it.
  3162. //
  3163. dwDataSize = sizeof(sWaitInfo);
  3164. sRegistryKey.GetValue(szGuid, &dwDataType, (LPBYTE) &sWaitInfo, &dwDataSize);
  3165. if ((REG_BINARY != dwDataType)||(sizeof(sWaitInfo) != dwDataSize))
  3166. {
  3167. THROW(E_UNEXPECTED);
  3168. }
  3169. //
  3170. // Initialize the wait event if possible
  3171. //
  3172. if (0xffffffff != sWaitInfo.dwEventCount[dwWaitEvent])
  3173. {
  3174. THROW(E_UNEXPECTED);
  3175. }
  3176. else
  3177. {
  3178. sWaitInfo.dwEventCount[dwWaitEvent] = 0;
  3179. }
  3180. }
  3181. //
  3182. // Should we delete the event or write the update record to the registry
  3183. //
  3184. if (0 == (sWaitInfo.dwEventCount[WAIT_FINALIZE_DOWNSIZE] + sWaitInfo.dwEventCount[WAIT_FINALIZE_REINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_UNINSTALL] + sWaitInfo.dwEventCount[WAIT_FINALIZE_SELFTEST]))
  3185. {
  3186. sRegistryKey.DeleteValue(szGuid);
  3187. }
  3188. else
  3189. {
  3190. //
  3191. // Write out the event
  3192. //
  3193. sWaitInfo.dwSize = sizeof(sWaitInfo);
  3194. sWaitInfo.dwStructId = WAIT_STRUCT;
  3195. hResult = sRegistryKey.SetValue(szGuid, REG_BINARY, (LPBYTE) &sWaitInfo, sizeof(sWaitInfo));
  3196. }
  3197. //
  3198. // Close the registry
  3199. //
  3200. sRegistryKey.CloseKey();
  3201. //
  3202. // unlock the information manager
  3203. //
  3204. sLock.UnLock();
  3205. return hResult;
  3206. }
  3207. //////////////////////////////////////////////////////////////////////////////////////////////
  3208. //
  3209. //////////////////////////////////////////////////////////////////////////////////////////////
  3210. STDMETHODIMP CInformationManager::CheckDeviceExistance(const DWORD dwDeviceIndex)
  3211. {
  3212. FUNCTION("CInfoMgr::CheckDeviceExistance ()");
  3213. CLock sLock(&m_CriticalSection);
  3214. CRegistryKey sRegistryKey;
  3215. TCHAR szString[MAX_PATH_CHARCOUNT];
  3216. HRESULT hResult = S_FALSE;
  3217. sLock.Lock();
  3218. //
  3219. // Open the AppMan\Devices key
  3220. //
  3221. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
  3222. //
  3223. // Add the device record to the registry
  3224. //
  3225. sprintf(szString, "[0x%08x]", dwDeviceIndex);
  3226. hResult = sRegistryKey.CheckForExistingValue(szString);
  3227. //
  3228. // Close sRegistryKey
  3229. //
  3230. sRegistryKey.CloseKey();
  3231. sLock.UnLock();
  3232. return hResult;
  3233. }
  3234. //////////////////////////////////////////////////////////////////////////////////////////////
  3235. //
  3236. //////////////////////////////////////////////////////////////////////////////////////////////
  3237. DWORD CInformationManager::GetDeviceIndex(const DWORD dwVolumeSerial)
  3238. {
  3239. CHAR szString[MAX_PATH_CHARCOUNT];
  3240. DWORD dwDeviceIndex, dwReturnValue, dwTempVolumeSerial;
  3241. dwDeviceIndex = 0;
  3242. dwReturnValue = 0xffffffff;
  3243. while ((0xffffffff == dwReturnValue)&&(MAX_DEVICES > dwDeviceIndex))
  3244. {
  3245. sprintf(szString, "%c:\\", dwDeviceIndex + 65);
  3246. if (DRIVE_FIXED == m_Win32API.GetDriveType(szString))
  3247. {
  3248. if (m_Win32API.IsDriveFormatted(szString))
  3249. {
  3250. if ((m_Win32API.GetVolumeInformation(szString, NULL, 0, &dwTempVolumeSerial))&&(dwVolumeSerial == dwTempVolumeSerial))
  3251. {
  3252. dwReturnValue = dwDeviceIndex;
  3253. }
  3254. }
  3255. }
  3256. dwDeviceIndex++;
  3257. }
  3258. return dwReturnValue;
  3259. }
  3260. //////////////////////////////////////////////////////////////////////////////////////////////
  3261. //
  3262. //////////////////////////////////////////////////////////////////////////////////////////////
  3263. STDMETHODIMP CInformationManager::AddDeviceWithIndex(const DWORD dwDeviceIndex)
  3264. {
  3265. FUNCTION("CInfoMgr::AddDeviceIndex ()");
  3266. CLock sLock(&m_CriticalSection);
  3267. TCHAR szString[10];
  3268. DEVICE_RECORD sDeviceRecord;
  3269. sLock.Lock();
  3270. //
  3271. // Initialize the device info
  3272. //
  3273. sprintf(szString, "%c:\\", dwDeviceIndex + 65);
  3274. if (!m_Win32API.GetVolumeInformation(szString, NULL, 0, &(sDeviceRecord.sDeviceInfo.dwVolumeSerial)))
  3275. {
  3276. THROW(E_UNEXPECTED);
  3277. }
  3278. //
  3279. // create the device record
  3280. //
  3281. if (FAILED(CoCreateGuid(&(sDeviceRecord.sDeviceGuid))))
  3282. {
  3283. THROW(E_UNEXPECTED);
  3284. }
  3285. sDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
  3286. sDeviceRecord.sDeviceInfo.dwDeviceFlags = DRIVE_FIXED;
  3287. sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask = 0;
  3288. sDeviceRecord.sDeviceInfo.dwPercentCacheSize = DEFAULT_PERCENT_CACHE_SIZE;
  3289. sDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize = 100;
  3290. sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
  3291. sDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
  3292. sDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
  3293. sDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
  3294. //
  3295. // Set the device info
  3296. //
  3297. SetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3298. sLock.UnLock();
  3299. return S_OK;
  3300. }
  3301. //////////////////////////////////////////////////////////////////////////////////////////////
  3302. //
  3303. //////////////////////////////////////////////////////////////////////////////////////////////
  3304. STDMETHODIMP CInformationManager::RemoveDeviceWithIndex(const DWORD dwDeviceIndex)
  3305. {
  3306. FUNCTION("CInfoMgr::RemoveDeviceIndex ()");
  3307. CLock sLock(&m_CriticalSection);
  3308. CRegistryKey sRegistryKey;
  3309. TCHAR szString[MAX_PATH_CHARCOUNT];
  3310. sLock.Lock();
  3311. //
  3312. // Open the AppMan\Devices key
  3313. //
  3314. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
  3315. //
  3316. // Get the GUID of the device at dwDeviceIndex
  3317. //
  3318. sprintf(szString, "[0x%08x]", dwDeviceIndex);
  3319. if (S_OK == sRegistryKey.CheckForExistingValue(szString))
  3320. {
  3321. sRegistryKey.DeleteValue(szString);
  3322. }
  3323. //
  3324. // Close sRegistryKey
  3325. //
  3326. sRegistryKey.CloseKey();
  3327. sLock.UnLock();
  3328. return S_OK;
  3329. }
  3330. //////////////////////////////////////////////////////////////////////////////////////////////
  3331. //
  3332. //////////////////////////////////////////////////////////////////////////////////////////////
  3333. STDMETHODIMP CInformationManager::UpdateDeviceInfoWithIndex(const DWORD dwDeviceIndex)
  3334. {
  3335. FUNCTION("CInfoMgr::UpdateDeviceInfoWithIndex ()");
  3336. CLock sLock(&m_CriticalSection);
  3337. DEVICE_RECORD sDeviceRecord;
  3338. APPLICATION_DATA sApplicationData;
  3339. DWORD dwIndex;
  3340. WCHAR wszString[MAX_PATH_CHARCOUNT];
  3341. CWin32API sWin32API;
  3342. sLock.Lock();
  3343. //
  3344. // Make sure the device really exists
  3345. //
  3346. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  3347. {
  3348. THROW(E_UNEXPECTED);
  3349. }
  3350. swprintf(wszString, L"%c:\\", dwDeviceIndex + 65);
  3351. if (m_Win32API.IsDriveFormatted(wszString))
  3352. {
  3353. //
  3354. // Get the device record
  3355. //
  3356. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3357. //
  3358. // Initialize the sDeviceRecord
  3359. //
  3360. sDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
  3361. sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
  3362. sDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
  3363. sDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
  3364. //
  3365. // Enumerate all of the applications on the system and verify that they do really exist
  3366. // (i.e. both setup root path and application root path are there). If the setup root
  3367. // path is missin, remove the game from the cache
  3368. //
  3369. dwIndex = 0;
  3370. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  3371. {
  3372. if ((S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, &sApplicationData))&&(S_OK == IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &sApplicationData)))
  3373. {
  3374. if (FALSE == sWin32API.FileExists(sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH]))
  3375. {
  3376. DisableApplication(&sApplicationData);
  3377. }
  3378. }
  3379. dwIndex++;
  3380. }
  3381. //
  3382. // Enumerate all of the applications on the system and consider those that belong
  3383. // to this device
  3384. //
  3385. dwIndex = 0;
  3386. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  3387. {
  3388. //
  3389. // Is the application assigned to this device
  3390. //
  3391. if (!memcmp(&(sApplicationData.sBaseInfo.sDeviceGuid), &(sDeviceRecord.sDeviceGuid), sizeof(GUID)))
  3392. {
  3393. //
  3394. // Is the application in an installing state ?
  3395. //
  3396. if (APP_STATE_INSTALLING != sApplicationData.sBaseInfo.dwState)
  3397. {
  3398. //
  3399. // Update the device information
  3400. //
  3401. if (FALSE == sApplicationData.sBaseInfo.dwPinState)
  3402. {
  3403. sDeviceRecord.sDeviceInfo.dwRemovableKilobytes += sApplicationData.sBaseInfo.dwRemovableKilobytes;
  3404. sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes += sApplicationData.sBaseInfo.dwNonRemovableKilobytes;
  3405. }
  3406. else
  3407. {
  3408. sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes += sApplicationData.sBaseInfo.dwNonRemovableKilobytes + sApplicationData.sBaseInfo.dwRemovableKilobytes;
  3409. }
  3410. if ((0 < sApplicationData.sBaseInfo.dwReservedKilobytes)&&(S_FALSE == IsInstanceGuidStillAlive(&sApplicationData.sBaseInfo.sInstanceGuid)))
  3411. {
  3412. //
  3413. // The application has some reserved space assigned to it but it is no longer valid
  3414. //
  3415. sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
  3416. SetApplicationData(&sApplicationData, NULL);
  3417. }
  3418. sDeviceRecord.sDeviceInfo.dwReservedKilobytes += sApplicationData.sBaseInfo.dwReservedKilobytes;
  3419. }
  3420. else
  3421. {
  3422. if ((0 < sApplicationData.sBaseInfo.dwReservedKilobytes)&&(S_FALSE == IsInstanceGuidStillAlive(&sApplicationData.sBaseInfo.sInstanceGuid)))
  3423. {
  3424. //
  3425. // The application has some reserved space assigned to it but it is no longer valid
  3426. //
  3427. sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
  3428. SetApplicationData(&sApplicationData, NULL);
  3429. }
  3430. sDeviceRecord.sDeviceInfo.dwReservedKilobytes += sApplicationData.sBaseInfo.dwReservedKilobytes;
  3431. }
  3432. }
  3433. dwIndex++;
  3434. }
  3435. //
  3436. // Update the device record
  3437. //
  3438. SetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3439. }
  3440. sLock.UnLock();
  3441. return S_OK;
  3442. }
  3443. //////////////////////////////////////////////////////////////////////////////////////////////
  3444. //
  3445. //////////////////////////////////////////////////////////////////////////////////////////////
  3446. STDMETHODIMP CInformationManager::ScanDevices(void)
  3447. {
  3448. FUNCTION("CInfoMgr::ScanDevices ()");
  3449. CLock sLock(&m_CriticalSection);
  3450. HRESULT hResult;
  3451. sLock.Lock();
  3452. hResult = ScanDevices(0);
  3453. sLock.UnLock();
  3454. return hResult;
  3455. }
  3456. //////////////////////////////////////////////////////////////////////////////////////////////
  3457. //
  3458. //////////////////////////////////////////////////////////////////////////////////////////////
  3459. STDMETHODIMP CInformationManager::ScanDevices(const DWORD dwDeviceIndex)
  3460. {
  3461. FUNCTION("CInfoMgr::ScanDevices ()");
  3462. HRESULT hResult = S_OK;
  3463. if (MAX_DEVICES > dwDeviceIndex)
  3464. {
  3465. CHAR szString[MAX_PATH_CHARCOUNT];
  3466. DEVICE_RECORD sDeviceRecord;
  3467. DEVICE_RECORD sExistingDeviceRecord;
  3468. BOOL fGuidAlreadyAssigned = FALSE;
  3469. DWORD dwIndex;
  3470. ZeroMemory(&sExistingDeviceRecord, sizeof(sExistingDeviceRecord));
  3471. //
  3472. // What does the system say about the device at dwDeviceIndex
  3473. //
  3474. sprintf(szString, "%c:\\", dwDeviceIndex + 65);
  3475. if (DRIVE_FIXED == m_Win32API.GetDriveType(szString))
  3476. {
  3477. //
  3478. // Get the volume serial of the device if it is formatted
  3479. //
  3480. if (m_Win32API.IsDriveFormatted(szString))
  3481. {
  3482. //
  3483. // Initialize the existing device record
  3484. //
  3485. ZeroMemory(&(sExistingDeviceRecord.sDeviceGuid), sizeof(GUID));
  3486. sExistingDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
  3487. sExistingDeviceRecord.sDeviceInfo.dwDeviceFlags = DRIVE_FIXED;
  3488. sExistingDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask = 0;
  3489. sExistingDeviceRecord.sDeviceInfo.dwPercentCacheSize = DEFAULT_PERCENT_CACHE_SIZE;
  3490. sExistingDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize = 100;
  3491. sExistingDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes = 0;
  3492. sExistingDeviceRecord.sDeviceInfo.dwRemovableKilobytes = 0;
  3493. sExistingDeviceRecord.sDeviceInfo.dwReservedKilobytes = 0;
  3494. sExistingDeviceRecord.sDeviceInfo.dwLastUsedThreshold = 0;
  3495. //
  3496. // Get the volume serial information
  3497. //
  3498. m_Win32API.GetVolumeInformation(szString, NULL, 0, &sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial);
  3499. //
  3500. // Enumerate the devices recorded inside AppMan and figure out if one of them already
  3501. // has this volume serial. Record the Guid of the device for later use
  3502. //
  3503. for (dwIndex = 0; dwIndex < MAX_DEVICES; dwIndex++)
  3504. {
  3505. if (S_OK == CheckDeviceExistance(dwIndex))
  3506. {
  3507. //
  3508. // Get the existing record
  3509. //
  3510. hResult = GetDeviceInfoWithIndex(dwIndex, &sDeviceRecord);
  3511. if (FAILED(hResult))
  3512. {
  3513. THROW(E_UNEXPECTED);
  3514. }
  3515. //
  3516. // Is the currently enumerated device the target record we are looking for
  3517. //
  3518. if (sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial == sDeviceRecord.sDeviceInfo.dwVolumeSerial)
  3519. {
  3520. fGuidAlreadyAssigned = TRUE;
  3521. memcpy(&sExistingDeviceRecord, &sDeviceRecord, sizeof(sDeviceRecord));
  3522. sExistingDeviceRecord.sDeviceInfo.dwDeviceIndex = dwDeviceIndex;
  3523. }
  3524. }
  3525. }
  3526. }
  3527. }
  3528. //
  3529. // Recursively go to the next device
  3530. //
  3531. ScanDevices(dwDeviceIndex + 1);
  3532. RemoveDeviceWithIndex(dwDeviceIndex);
  3533. if (SUCCEEDED(hResult))
  3534. {
  3535. if (0 != sExistingDeviceRecord.sDeviceInfo.dwVolumeSerial)
  3536. {
  3537. if (TRUE == fGuidAlreadyAssigned)
  3538. {
  3539. SetDeviceInfoWithIndex(dwDeviceIndex, &sExistingDeviceRecord);
  3540. UpdateDeviceInfoWithIndex(dwDeviceIndex);
  3541. }
  3542. else
  3543. {
  3544. if (m_Win32API.IsDriveFormatted(szString))
  3545. {
  3546. AddDeviceWithIndex(dwDeviceIndex);
  3547. }
  3548. }
  3549. }
  3550. }
  3551. }
  3552. return hResult;
  3553. }
  3554. //////////////////////////////////////////////////////////////////////////////////////////////
  3555. //
  3556. //////////////////////////////////////////////////////////////////////////////////////////////
  3557. STDMETHODIMP CInformationManager::GetDeviceInfo(LPDEVICE_RECORD lpDeviceRecord)
  3558. {
  3559. FUNCTION("CInfoMgr::GetDeviceInfo ()");
  3560. DEVICE_RECORD sDeviceRecord;
  3561. DWORD dwDeviceIndex;
  3562. HRESULT hResult = E_FAIL;
  3563. assert(NULL != lpDeviceRecord);
  3564. //
  3565. // Enumerate all of the devices and find the one that matches
  3566. //
  3567. dwDeviceIndex = 0;
  3568. while ((FAILED(hResult))&&(MAX_DEVICES > dwDeviceIndex))
  3569. {
  3570. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  3571. {
  3572. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3573. if (!memcmp(&(sDeviceRecord.sDeviceGuid), &(lpDeviceRecord->sDeviceGuid), sizeof(GUID)))
  3574. {
  3575. memcpy(lpDeviceRecord, &sDeviceRecord, sizeof(DEVICE_RECORD));
  3576. hResult = S_OK;
  3577. }
  3578. }
  3579. dwDeviceIndex++;
  3580. }
  3581. return hResult;
  3582. }
  3583. //////////////////////////////////////////////////////////////////////////////////////////////
  3584. //
  3585. //////////////////////////////////////////////////////////////////////////////////////////////
  3586. STDMETHODIMP CInformationManager::GetDeviceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_RECORD lpDeviceRecord)
  3587. {
  3588. FUNCTION("CInfoMgr::GetDeviceInfoWithIndex ()");
  3589. CLock sLock(&m_CriticalSection);
  3590. CRegistryKey sRegistryKey;
  3591. TCHAR szString[MAX_PATH_CHARCOUNT];
  3592. DWORD dwDataType, dwDataLen;
  3593. assert(NULL != lpDeviceRecord);
  3594. //
  3595. // Does the device exist
  3596. //
  3597. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  3598. {
  3599. THROW(E_FAIL);
  3600. }
  3601. sLock.Lock();
  3602. //
  3603. // Open the AppMan\Devices key
  3604. //
  3605. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
  3606. //
  3607. // Get the GUID of the device at dwDeviceIndex
  3608. //
  3609. sprintf(szString, "[0x%08x]", dwDeviceIndex);
  3610. if (S_FALSE == sRegistryKey.CheckForExistingValue(szString))
  3611. {
  3612. THROW(E_UNEXPECTED);
  3613. }
  3614. //
  3615. // Get the device info from the registry and make sure it is valid
  3616. //
  3617. dwDataLen = sizeof(DEVICE_RECORD);
  3618. sRegistryKey.GetValue(szString, &dwDataType, (LPBYTE) lpDeviceRecord, &dwDataLen);
  3619. if ((REG_BINARY != dwDataType)||(sizeof(DEVICE_RECORD) != dwDataLen))
  3620. {
  3621. THROW(E_UNEXPECTED);
  3622. }
  3623. //
  3624. // Close sRegistryKey
  3625. //
  3626. sRegistryKey.CloseKey();
  3627. sLock.UnLock();
  3628. return S_OK;
  3629. }
  3630. //////////////////////////////////////////////////////////////////////////////////////////////
  3631. //
  3632. //////////////////////////////////////////////////////////////////////////////////////////////
  3633. STDMETHODIMP CInformationManager::SetDeviceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_RECORD lpDeviceRecord)
  3634. {
  3635. FUNCTION("CInfoMgr::SetDeviceInfoWithIndex ()");
  3636. CLock sLock(&m_CriticalSection);
  3637. CRegistryKey sRegistryKey;
  3638. TCHAR szString[MAX_PATH_CHARCOUNT];
  3639. assert(NULL != lpDeviceRecord);
  3640. sLock.Lock();
  3641. //
  3642. // Open the AppMan\Devices key
  3643. //
  3644. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Devices"), KEY_ALL_ACCESS);
  3645. //
  3646. // Get the GUID of the device at dwDeviceIndex
  3647. //
  3648. sprintf(szString, "[0x%08x]", dwDeviceIndex);
  3649. sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpDeviceRecord, sizeof(DEVICE_RECORD));
  3650. //
  3651. // Close sRegistryKey
  3652. //
  3653. sRegistryKey.CloseKey();
  3654. sLock.UnLock();
  3655. return S_OK;
  3656. }
  3657. //////////////////////////////////////////////////////////////////////////////////////////////
  3658. //
  3659. //////////////////////////////////////////////////////////////////////////////////////////////
  3660. STDMETHODIMP CInformationManager::GetDeviceSpaceInfoWithIndex(const DWORD dwDeviceIndex, LPDEVICE_SPACE_INFO lpDeviceSpaceInfo)
  3661. {
  3662. FUNCTION("CInfoMgr::GetDeviceSpaceInfoWithIndex ()");
  3663. CLock sLock(&m_CriticalSection);
  3664. DEVICE_RECORD sDeviceRecord;
  3665. TEMP_SPACE_RECORD sTempSpaceRecord;
  3666. TCHAR szString[MAX_PATH_CHARCOUNT];
  3667. DWORD dwTheoreticalMaximumAvailableKilobytes, dwIndex;
  3668. sLock.Lock();
  3669. //
  3670. // Make sure the device really exists
  3671. //
  3672. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  3673. {
  3674. THROW(E_UNEXPECTED);
  3675. }
  3676. //
  3677. // update and retrieve the device information
  3678. //
  3679. UpdateDeviceInfoWithIndex(dwDeviceIndex);
  3680. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3681. //
  3682. // How much temporary reserved space is there ?
  3683. //
  3684. lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes = 0;
  3685. lpDeviceSpaceInfo->dwTotalUsedTemporaryKilobytes = 0;
  3686. dwIndex = 0;
  3687. while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
  3688. {
  3689. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sTempSpaceRecord.sDeviceGuid, sizeof(GUID)))
  3690. {
  3691. lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes += sTempSpaceRecord.dwKilobytes;
  3692. lpDeviceSpaceInfo->dwTotalUsedTemporaryKilobytes += m_Win32API.GetDirectorySize(sTempSpaceRecord.wszDirectory);
  3693. }
  3694. dwIndex++;
  3695. }
  3696. //
  3697. // Get the basic numbers
  3698. //
  3699. sprintf(szString, "%c:\\", dwDeviceIndex + 65);
  3700. lpDeviceSpaceInfo->dwTotalKilobytes = m_Win32API.GetDriveSize(szString);
  3701. lpDeviceSpaceInfo->dwTotalFreeKilobytes = m_Win32API.GetDriveFreeSpace(szString);
  3702. lpDeviceSpaceInfo->dwCacheSizeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentCacheSize * (lpDeviceSpaceInfo->dwTotalKilobytes / 100);
  3703. lpDeviceSpaceInfo->dwMinimumFreeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentMinimumFreeSize * (lpDeviceSpaceInfo->dwTotalKilobytes / 100);
  3704. lpDeviceSpaceInfo->dwTotalRemovableKilobytes = sDeviceRecord.sDeviceInfo.dwRemovableKilobytes;
  3705. lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes = sDeviceRecord.sDeviceInfo.dwNonRemovableKilobytes + sDeviceRecord.sDeviceInfo.dwReservedKilobytes + lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes;
  3706. lpDeviceSpaceInfo->dwOptimalRemovableKilobytes = lpDeviceSpaceInfo->dwTotalRemovableKilobytes >> 1;
  3707. lpDeviceSpaceInfo->dwCacheUsedKilobytes = lpDeviceSpaceInfo->dwTotalRemovableKilobytes + lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes;
  3708. //
  3709. // How many free kilobytes do we have in the cache and if not how many kilobytes are spilling over
  3710. // in the slack space
  3711. //
  3712. if (lpDeviceSpaceInfo->dwCacheSizeKilobytes > lpDeviceSpaceInfo->dwCacheUsedKilobytes)
  3713. {
  3714. lpDeviceSpaceInfo->dwCacheFreeKilobytes = min(lpDeviceSpaceInfo->dwCacheSizeKilobytes - lpDeviceSpaceInfo->dwCacheUsedKilobytes, (lpDeviceSpaceInfo->dwTotalFreeKilobytes - (sDeviceRecord.sDeviceInfo.dwReservedKilobytes + lpDeviceSpaceInfo->dwTotalReservedTemporaryKilobytes)));
  3715. lpDeviceSpaceInfo->dwSlackUsedKilobytes = 0;
  3716. }
  3717. else
  3718. {
  3719. lpDeviceSpaceInfo->dwCacheFreeKilobytes = 0;
  3720. lpDeviceSpaceInfo->dwSlackUsedKilobytes = lpDeviceSpaceInfo->dwCacheUsedKilobytes - lpDeviceSpaceInfo->dwCacheSizeKilobytes;
  3721. }
  3722. //
  3723. // How big is the slack space
  3724. //
  3725. if (lpDeviceSpaceInfo->dwTotalFreeKilobytes > (lpDeviceSpaceInfo->dwMinimumFreeKilobytes + lpDeviceSpaceInfo->dwCacheFreeKilobytes))
  3726. {
  3727. lpDeviceSpaceInfo->dwSlackSizeKilobytes = lpDeviceSpaceInfo->dwSlackUsedKilobytes + lpDeviceSpaceInfo->dwTotalFreeKilobytes - (lpDeviceSpaceInfo->dwMinimumFreeKilobytes + lpDeviceSpaceInfo->dwCacheFreeKilobytes);
  3728. }
  3729. else
  3730. {
  3731. lpDeviceSpaceInfo->dwSlackSizeKilobytes = 0;
  3732. }
  3733. //
  3734. // How much free slack space do we have left over
  3735. //
  3736. if (lpDeviceSpaceInfo->dwSlackSizeKilobytes > lpDeviceSpaceInfo->dwSlackUsedKilobytes)
  3737. {
  3738. lpDeviceSpaceInfo->dwSlackFreeKilobytes = min(lpDeviceSpaceInfo->dwSlackSizeKilobytes - lpDeviceSpaceInfo->dwSlackUsedKilobytes, lpDeviceSpaceInfo->dwTotalFreeKilobytes);
  3739. }
  3740. else
  3741. {
  3742. lpDeviceSpaceInfo->dwSlackFreeKilobytes = 0;
  3743. }
  3744. //
  3745. // What is the theoretical maximum amount of kilobytes that could be made available
  3746. //
  3747. if ((lpDeviceSpaceInfo->dwCacheSizeKilobytes + lpDeviceSpaceInfo->dwSlackSizeKilobytes) < lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes )
  3748. {
  3749. dwTheoreticalMaximumAvailableKilobytes = 0;
  3750. }
  3751. else
  3752. {
  3753. dwTheoreticalMaximumAvailableKilobytes = lpDeviceSpaceInfo->dwCacheSizeKilobytes + lpDeviceSpaceInfo->dwSlackSizeKilobytes - lpDeviceSpaceInfo->dwTotalNonRemovableKilobytes;
  3754. }
  3755. //
  3756. // Compute the final values
  3757. //
  3758. lpDeviceSpaceInfo->dwTotalUsableFreeKilobytes = lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes;
  3759. lpDeviceSpaceInfo->dwMaximumUsableKilobytes = min((lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes + lpDeviceSpaceInfo->dwTotalRemovableKilobytes), dwTheoreticalMaximumAvailableKilobytes);
  3760. lpDeviceSpaceInfo->dwOptimalUsableKilobytes = min((lpDeviceSpaceInfo->dwCacheFreeKilobytes + lpDeviceSpaceInfo->dwSlackFreeKilobytes + lpDeviceSpaceInfo->dwOptimalRemovableKilobytes), dwTheoreticalMaximumAvailableKilobytes);
  3761. lpDeviceSpaceInfo->dwTotalReservedKilobytes = sDeviceRecord.sDeviceInfo.dwReservedKilobytes;
  3762. sLock.UnLock();
  3763. return S_OK;
  3764. }
  3765. //////////////////////////////////////////////////////////////////////////////////////////////
  3766. //
  3767. //////////////////////////////////////////////////////////////////////////////////////////////
  3768. STDMETHODIMP CInformationManager::GetDeviceOptimalSpaceWithIndex(const DWORD dwDeviceIndex, LPDWORD lpdwKilobytes)
  3769. {
  3770. FUNCTION("CInfoMgr::GetDeviceOptimalSpaceWithIndex ()");
  3771. DEVICE_SPACE_INFO sDeviceSpaceInfo;
  3772. //
  3773. // Make sure the device really exists
  3774. //
  3775. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  3776. {
  3777. THROW(E_UNEXPECTED);
  3778. }
  3779. //
  3780. // update and retrieve the device information
  3781. //
  3782. GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3783. //
  3784. // Calculate the optimal size available
  3785. //
  3786. *lpdwKilobytes = sDeviceSpaceInfo.dwOptimalUsableKilobytes;
  3787. return S_OK;
  3788. }
  3789. //////////////////////////////////////////////////////////////////////////////////////////////
  3790. //
  3791. //////////////////////////////////////////////////////////////////////////////////////////////
  3792. STDMETHODIMP CInformationManager::GetDeviceMaximumSpaceWithIndex(const DWORD dwDeviceIndex, LPDWORD lpdwKilobytes)
  3793. {
  3794. FUNCTION("CInfoMgr::GetDeviceMaximumSpaceWithIndex()");
  3795. DEVICE_SPACE_INFO sDeviceSpaceInfo;
  3796. //
  3797. // Make sure the device really exists
  3798. //
  3799. if (S_FALSE == CheckDeviceExistance(dwDeviceIndex))
  3800. {
  3801. THROW(E_UNEXPECTED);
  3802. }
  3803. //
  3804. // update and retrieve the device information
  3805. //
  3806. GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3807. //
  3808. // Calculate the maximum size available
  3809. //
  3810. *lpdwKilobytes = sDeviceSpaceInfo.dwMaximumUsableKilobytes;
  3811. return S_OK;
  3812. }
  3813. //////////////////////////////////////////////////////////////////////////////////////////////
  3814. //
  3815. //////////////////////////////////////////////////////////////////////////////////////////////
  3816. STDMETHODIMP CInformationManager::FreeSpaceOnDeviceWithIndex(const DWORD dwDeviceIndex, const DWORD dwRequiredKilobytes)
  3817. {
  3818. FUNCTION("CInfoMgr::FreeSpaceOnDeviceWithIndex ()");
  3819. APPLICATION_DATA sApplicationData;
  3820. DEVICE_SPACE_INFO sDeviceSpaceInfo;
  3821. DWORD dwNeededKilobytes = 0;
  3822. HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
  3823. //
  3824. // Get the device space information
  3825. //
  3826. GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3827. //
  3828. // Check to see whether or not we even have a chance at getting the space in the first place
  3829. //
  3830. if (dwRequiredKilobytes > sDeviceSpaceInfo.dwMaximumUsableKilobytes)
  3831. {
  3832. THROW(APPMAN_E_NODISKSPACEAVAILABLE);
  3833. }
  3834. //
  3835. // Compute the amount of Kilobytes that are needed
  3836. //
  3837. if (dwRequiredKilobytes > sDeviceSpaceInfo.dwTotalUsableFreeKilobytes)
  3838. {
  3839. dwNeededKilobytes = dwRequiredKilobytes - sDeviceSpaceInfo.dwTotalUsableFreeKilobytes;
  3840. //
  3841. // We start off with the oldest application in the system
  3842. //
  3843. if (S_OK == GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData))
  3844. {
  3845. do
  3846. {
  3847. //
  3848. // Downsize sApplicationRecord
  3849. //
  3850. if (0 < sApplicationData.sBaseInfo.dwRemovableKilobytes)
  3851. {
  3852. if (S_FALSE == IsApplicationLocked(&sApplicationData))
  3853. {
  3854. DownsizeApplication(dwNeededKilobytes, &sApplicationData);
  3855. }
  3856. }
  3857. //
  3858. // Recomputer the amount of Kilobytes needed
  3859. //
  3860. GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3861. if (dwRequiredKilobytes > sDeviceSpaceInfo.dwTotalUsableFreeKilobytes)
  3862. {
  3863. dwNeededKilobytes = dwRequiredKilobytes - sDeviceSpaceInfo.dwTotalUsableFreeKilobytes;
  3864. }
  3865. else
  3866. {
  3867. dwNeededKilobytes = 0;
  3868. }
  3869. }
  3870. while ((0 < dwNeededKilobytes)&&(S_OK == GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)));
  3871. }
  3872. }
  3873. //
  3874. // Did we succeed ?
  3875. //
  3876. if (0 == dwNeededKilobytes)
  3877. {
  3878. hResult = S_OK;
  3879. }
  3880. return hResult;
  3881. }
  3882. //////////////////////////////////////////////////////////////////////////////////////////////
  3883. //
  3884. //////////////////////////////////////////////////////////////////////////////////////////////
  3885. STDMETHODIMP CInformationManager::FixCacheOverrun(const GUID * lpDeviceGuid, const DWORD dwExtraKilobytes)
  3886. {
  3887. FUNCTION("CInfoMgr::FixCacheOverrun()");
  3888. APPLICATION_DATA sApplicationData = {0};
  3889. DEVICE_RECORD sDeviceRecord = {0};
  3890. DEVICE_SPACE_INFO sDeviceSpaceInfo = {0};
  3891. DWORD dwDeviceIndex;
  3892. DWORD dwNeededKilobytes, dwCacheUsedKilobytes, dwCacheSizeKilobytes;
  3893. HRESULT hResult = APPMAN_E_NODISKSPACEAVAILABLE;
  3894. //
  3895. // Enumerate all of the devices and find the one that matches
  3896. //
  3897. dwDeviceIndex = 0;
  3898. while ((FAILED(hResult))&&(MAX_DEVICES > dwDeviceIndex))
  3899. {
  3900. if (S_OK == CheckDeviceExistance(dwDeviceIndex))
  3901. {
  3902. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  3903. if (!memcmp(&(sDeviceRecord.sDeviceGuid), lpDeviceGuid, sizeof(GUID)))
  3904. {
  3905. hResult = S_OK;
  3906. break;
  3907. }
  3908. }
  3909. dwDeviceIndex++;
  3910. }
  3911. if (SUCCEEDED(hResult))
  3912. {
  3913. //
  3914. // Get the device space information
  3915. //
  3916. hResult = GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3917. if (SUCCEEDED(hResult))
  3918. {
  3919. //
  3920. // What is the maximum possible cache size ?
  3921. //
  3922. dwCacheSizeKilobytes = sDeviceRecord.sDeviceInfo.dwPercentCacheSize * (sDeviceSpaceInfo.dwTotalKilobytes / 100);
  3923. dwCacheUsedKilobytes = sDeviceSpaceInfo.dwCacheUsedKilobytes + dwExtraKilobytes;
  3924. //
  3925. // Check to see whether or not we even have a chance at getting the space in the first place
  3926. //
  3927. if (dwCacheUsedKilobytes > dwCacheSizeKilobytes)
  3928. {
  3929. //
  3930. // How many kilobytes do we need to free up on the device
  3931. //
  3932. dwNeededKilobytes = dwCacheUsedKilobytes - dwCacheSizeKilobytes;
  3933. //
  3934. // By default, we set the hResult value prior to calling GetOldest...
  3935. //
  3936. hResult = APPMAN_E_CACHEOVERRUN;
  3937. //
  3938. // We start off with the oldest application in the system
  3939. //
  3940. if (S_OK == GetOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData))
  3941. {
  3942. do
  3943. {
  3944. //
  3945. // Downsize sApplicationRecord
  3946. //
  3947. if (0 < sApplicationData.sBaseInfo.dwRemovableKilobytes)
  3948. {
  3949. if (S_FALSE == IsApplicationLocked(&sApplicationData))
  3950. {
  3951. DownsizeApplication(dwNeededKilobytes, &sApplicationData);
  3952. }
  3953. }
  3954. //
  3955. // Recomputer the amount of Kilobytes needed
  3956. //
  3957. hResult = GetDeviceSpaceInfoWithIndex(dwDeviceIndex, &sDeviceSpaceInfo);
  3958. if (FAILED(hResult))
  3959. {
  3960. THROW(hResult);
  3961. }
  3962. //
  3963. // Now that we have downsized a title, how many used kilobytes are there in
  3964. // the cache
  3965. //
  3966. dwCacheUsedKilobytes = sDeviceSpaceInfo.dwCacheUsedKilobytes + dwExtraKilobytes;
  3967. //
  3968. // Should we keep going
  3969. //
  3970. if (dwCacheUsedKilobytes <= dwCacheSizeKilobytes)
  3971. {
  3972. hResult = S_OK;
  3973. }
  3974. else
  3975. {
  3976. hResult = APPMAN_E_CACHEOVERRUN;
  3977. }
  3978. }
  3979. while ((FAILED(hResult))&&(S_OK == GetNextOldestApplicationDataByDeviceWithIndex(dwDeviceIndex, &sApplicationData)));
  3980. }
  3981. }
  3982. }
  3983. }
  3984. return hResult;
  3985. }
  3986. //////////////////////////////////////////////////////////////////////////////////////////////
  3987. //
  3988. // Returns the number of elapsed minutes since October 25th 1968 (my birthday)
  3989. //
  3990. //////////////////////////////////////////////////////////////////////////////////////////////
  3991. DWORD CInformationManager::GetAgingCount(LPAPPLICATION_DATA lpApplicationData)
  3992. {
  3993. FUNCTION("CInfoMgr::GetAgingCount ()");
  3994. APPLICATION_DATA sChildData;
  3995. ASSOCIATION_INFO sAssociationInfo;
  3996. DWORD dwIndex;
  3997. DWORD dwElapsedSeconds, dwChildElapsedSeconds;
  3998. dwElapsedSeconds = GetAgingCountInSeconds(&lpApplicationData->sAgingInfo);
  3999. dwChildElapsedSeconds = 0;
  4000. dwIndex = 0;
  4001. while (S_OK == EnumAssociations(dwIndex, &sAssociationInfo))
  4002. {
  4003. if (0 == memcmp(&(lpApplicationData->sBaseInfo.sApplicationGuid), &(sAssociationInfo.sParentGuid), sizeof(GUID)))
  4004. {
  4005. ZeroMemory(&sChildData, sizeof(sChildData));
  4006. memcpy(&(sChildData.sBaseInfo.sApplicationGuid), &(sAssociationInfo.sChildGuid), sizeof(GUID));
  4007. ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sChildData);
  4008. if (FAILED(GetApplicationData(&sChildData)))
  4009. {
  4010. THROW(E_UNEXPECTED);
  4011. }
  4012. dwChildElapsedSeconds = GetAgingCount(&sChildData);
  4013. if (dwChildElapsedSeconds >= dwElapsedSeconds)
  4014. {
  4015. dwElapsedSeconds = dwChildElapsedSeconds + 1;
  4016. }
  4017. }
  4018. dwIndex++;
  4019. }
  4020. OutputDebugString(MakeString("App %s %s is %d seconds old", lpApplicationData->wszStringProperty[APP_STRING_COMPANYNAME], lpApplicationData->wszStringProperty[APP_STRING_SIGNATURE], dwElapsedSeconds));
  4021. return dwElapsedSeconds;
  4022. }
  4023. //////////////////////////////////////////////////////////////////////////////////////////////
  4024. //
  4025. //////////////////////////////////////////////////////////////////////////////////////////////
  4026. STDMETHODIMP CInformationManager::GetOldestApplicationDataByDeviceWithIndex(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
  4027. {
  4028. FUNCTION("CInfoMgr::GetOldestApplicationDataByDeviceWithIndex ()");
  4029. CLock sLock(&m_CriticalSection);
  4030. DEVICE_RECORD sDeviceRecord;
  4031. APPLICATION_DATA sApplicationData;
  4032. DWORD dwIndex;
  4033. HRESULT hResult = E_FAIL;
  4034. sLock.Lock();
  4035. //
  4036. // Get the device information
  4037. //
  4038. if (FAILED(GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord)))
  4039. {
  4040. THROW(APPMAN_E_INVALIDINDEX);
  4041. }
  4042. //
  4043. // By default, lpApplicationRecord will represent the first viable application
  4044. //
  4045. dwIndex = 0;
  4046. do
  4047. {
  4048. hResult = GetApplicationDataWithIndex(dwIndex, lpApplicationData);
  4049. dwIndex++;
  4050. if (SUCCEEDED(hResult))
  4051. {
  4052. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID)))
  4053. {
  4054. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
  4055. {
  4056. break;
  4057. }
  4058. }
  4059. }
  4060. }
  4061. while (SUCCEEDED(hResult));
  4062. //
  4063. // If we have a viable initial application record, we move on to try and find the oldest one
  4064. //
  4065. if (SUCCEEDED(hResult))
  4066. {
  4067. //
  4068. // Now we enumerate the remaining application and figure out which one is the oldest
  4069. //
  4070. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  4071. {
  4072. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
  4073. {
  4074. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
  4075. {
  4076. if (GetAgingCount(&sApplicationData) < GetAgingCount(lpApplicationData))
  4077. {
  4078. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4079. }
  4080. else
  4081. {
  4082. if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
  4083. {
  4084. //
  4085. // Both applications have the same aging count. We use the application guid as a bias to decide
  4086. // which of the two apps is actually older
  4087. //
  4088. if (0 < memcmp(&(lpApplicationData->sBaseInfo.sApplicationGuid), &(sApplicationData.sBaseInfo.sApplicationGuid), sizeof(GUID)))
  4089. {
  4090. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4091. }
  4092. }
  4093. }
  4094. }
  4095. }
  4096. dwIndex++;
  4097. }
  4098. }
  4099. sLock.UnLock();
  4100. return hResult;
  4101. }
  4102. //////////////////////////////////////////////////////////////////////////////////////////////
  4103. //
  4104. //////////////////////////////////////////////////////////////////////////////////////////////
  4105. STDMETHODIMP CInformationManager::GetNextOldestApplicationDataByDeviceWithIndex(const DWORD dwDeviceIndex, LPAPPLICATION_DATA lpApplicationData)
  4106. {
  4107. FUNCTION("CInfoMgr::GetNextOldestApplicationDataByDeviceWithIndex ()");
  4108. CLock sLock(&m_CriticalSection);
  4109. DEVICE_RECORD sDeviceRecord;
  4110. APPLICATION_DATA sApplicationData;
  4111. DWORD dwOriginalAgeInSeconds;
  4112. GUID sOriginalApplicationGuid;
  4113. DWORD dwIndex;
  4114. HRESULT hResult = E_FAIL;
  4115. sLock.Lock();
  4116. //
  4117. // Save the original information
  4118. //
  4119. dwOriginalAgeInSeconds = GetAgingCount(lpApplicationData);
  4120. memcpy(&sOriginalApplicationGuid, &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID));
  4121. //
  4122. // Get the device information
  4123. //
  4124. if (FAILED(GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord)))
  4125. {
  4126. THROW(APPMAN_E_INVALIDINDEX);
  4127. }
  4128. //
  4129. // By default, lpApplicationRecord will represent the first viable application
  4130. //
  4131. dwIndex = 0;
  4132. do
  4133. {
  4134. hResult = GetApplicationDataWithIndex(dwIndex, lpApplicationData);
  4135. dwIndex++;
  4136. if (SUCCEEDED(hResult))
  4137. {
  4138. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &lpApplicationData->sBaseInfo.sDeviceGuid, sizeof(GUID)))
  4139. {
  4140. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & lpApplicationData->sBaseInfo.dwState)
  4141. {
  4142. break;
  4143. }
  4144. }
  4145. }
  4146. }
  4147. while (SUCCEEDED(hResult));
  4148. //
  4149. // First we need to find the newest application
  4150. //
  4151. if (SUCCEEDED(hResult))
  4152. {
  4153. //
  4154. // Now we enumerate the remaining application and figure out which one is the newest
  4155. //
  4156. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  4157. {
  4158. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
  4159. {
  4160. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
  4161. {
  4162. if (GetAgingCount(&sApplicationData) > GetAgingCount(lpApplicationData))
  4163. {
  4164. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4165. }
  4166. else
  4167. {
  4168. if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
  4169. {
  4170. //
  4171. // Both applications have the same aging count. We use the application guid as a bias to decide
  4172. // which of the two apps is actually older
  4173. //
  4174. if (0 < memcmp(&(sApplicationData.sBaseInfo.sApplicationGuid), &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  4175. {
  4176. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4177. }
  4178. }
  4179. }
  4180. }
  4181. }
  4182. dwIndex++;
  4183. }
  4184. //
  4185. // Ok we have the newest application represented by lpApplicationRecor. Now we go looking
  4186. // for the Oldest app that is newer that dwOriginalAgeInSeconds
  4187. //
  4188. dwIndex = 0;
  4189. while (SUCCEEDED(GetApplicationDataWithIndex(dwIndex, &sApplicationData)))
  4190. {
  4191. if (0 == memcmp((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID)))
  4192. {
  4193. if ((APP_STATE_READY | APP_STATE_DOWNSIZED) & sApplicationData.sBaseInfo.dwState)
  4194. {
  4195. //
  4196. // Is sApplicationRecord older than lpApplicationRecord
  4197. //
  4198. if (GetAgingCount(&sApplicationData) < GetAgingCount(lpApplicationData))
  4199. {
  4200. //
  4201. // Is sApplicationRecord newer than sAgingInfo
  4202. //
  4203. if (GetAgingCount(&sApplicationData) > dwOriginalAgeInSeconds)
  4204. {
  4205. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4206. }
  4207. else
  4208. {
  4209. if (GetAgingCount(&sApplicationData) == GetAgingCount(lpApplicationData))
  4210. {
  4211. //
  4212. // Both applications have the same aging count. We use the application guid as a bias to decide
  4213. // which of the two apps is actually older
  4214. //
  4215. if (0 < memcmp(&(sApplicationData.sBaseInfo.sApplicationGuid), &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  4216. {
  4217. memcpy(lpApplicationData, &(sApplicationData), sizeof(APPLICATION_DATA));
  4218. }
  4219. }
  4220. }
  4221. }
  4222. }
  4223. }
  4224. dwIndex++;
  4225. }
  4226. }
  4227. //
  4228. // Check to make sure that lpApplicationRecord represents a valid application record
  4229. //
  4230. if (SUCCEEDED(hResult))
  4231. {
  4232. //
  4233. // Ok now we need to check and make sure that the outgoing lpApplicationRecord is not identical
  4234. // to the incoming one (i.e. in the case where we only have a single app in system, this will
  4235. // occur
  4236. //
  4237. if (!memcmp(&sOriginalApplicationGuid, &(lpApplicationData->sBaseInfo.sApplicationGuid), sizeof(GUID)))
  4238. {
  4239. ZeroMemory(lpApplicationData, sizeof(APPLICATION_DATA));
  4240. hResult = E_FAIL;
  4241. }
  4242. else
  4243. {
  4244. hResult = S_OK;
  4245. }
  4246. }
  4247. sLock.UnLock();
  4248. return hResult;
  4249. }
  4250. //////////////////////////////////////////////////////////////////////////////////////////////
  4251. //
  4252. //////////////////////////////////////////////////////////////////////////////////////////////
  4253. STDMETHODIMP CInformationManager::AddTempSpace(LPTEMP_SPACE_RECORD lpTempSpaceRecord)
  4254. {
  4255. FUNCTION("CInfoMgr::AddTempSpace ()");
  4256. CLock sLock(&m_CriticalSection);
  4257. DWORD dwDeviceIndex;
  4258. HRESULT hResult;
  4259. CWin32API Win32API;
  4260. DEVICE_RECORD sDeviceRecord;
  4261. CRegistryKey sRegistryKey;
  4262. CHAR szString[MAX_PATH_CHARCOUNT];
  4263. hResult = GetSpace(0, lpTempSpaceRecord->dwKilobytes, &dwDeviceIndex);
  4264. if (SUCCEEDED(hResult))
  4265. {
  4266. sLock.Lock();
  4267. //
  4268. // update and retrieve the device information
  4269. //
  4270. UpdateDeviceInfoWithIndex(dwDeviceIndex);
  4271. GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
  4272. //
  4273. // Fill in the TEMP_SPACE_RECORD var
  4274. //
  4275. if (FAILED(CoCreateGuid(&lpTempSpaceRecord->sGuid)))
  4276. {
  4277. THROW(E_UNEXPECTED);
  4278. }
  4279. memcpy((LPVOID) &lpTempSpaceRecord->sDeviceGuid, (LPVOID) &sDeviceRecord.sDeviceGuid, sizeof(GUID));
  4280. 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]);
  4281. //
  4282. // Add the entry to the registry
  4283. //
  4284. sRegistryKey.CreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, TRUE, NULL);
  4285. 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]);
  4286. sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpTempSpaceRecord, sizeof(TEMP_SPACE_RECORD));
  4287. //
  4288. // Create the directory
  4289. //
  4290. Win32API.CreateDirectory(lpTempSpaceRecord->wszDirectory, FALSE);
  4291. sLock.UnLock();
  4292. }
  4293. return hResult;
  4294. }
  4295. //////////////////////////////////////////////////////////////////////////////////////////////
  4296. //
  4297. //////////////////////////////////////////////////////////////////////////////////////////////
  4298. STDMETHODIMP CInformationManager::RemoveTempSpace(LPTEMP_SPACE_RECORD lpTempSpaceRecord)
  4299. {
  4300. FUNCTION("CInfoMgr::RemoveTempSpace ()");
  4301. CLock sLock(&m_CriticalSection);
  4302. TEMP_SPACE_RECORD sTempSpaceRecord;
  4303. DWORD dwIndex;
  4304. HRESULT hResult = E_FAIL;
  4305. CWin32API Win32API;
  4306. CRegistryKey sRegistryKey;
  4307. CHAR szString[MAX_PATH_CHARCOUNT];
  4308. BOOL fRemoved;
  4309. sLock.Lock();
  4310. //
  4311. // First we need to find the matching entry (based on path and sApplicationGuid)
  4312. //
  4313. fRemoved = FALSE;
  4314. dwIndex = 0;
  4315. while (S_OK == EnumTempSpace(dwIndex, &sTempSpaceRecord))
  4316. {
  4317. //
  4318. // Does the enumerated temp space belong to the current application
  4319. //
  4320. if (0 == memcmp((LPVOID) &sTempSpaceRecord.sApplicationGuid, (LPVOID) &lpTempSpaceRecord->sApplicationGuid, sizeof(GUID)))
  4321. {
  4322. //
  4323. // Does the enumerated temp space have the same directory
  4324. //
  4325. if (0 == _wcsnicmp(sTempSpaceRecord.wszDirectory, lpTempSpaceRecord->wszDirectory, MAX_PATH_CHARCOUNT))
  4326. {
  4327. //
  4328. // This is the winner. Let's wack it
  4329. //
  4330. //
  4331. // Delete the directory
  4332. //
  4333. if (FAILED(DeleteDirectoryTree(sTempSpaceRecord.wszDirectory)))
  4334. {
  4335. RegFutureDirectoryCleanup(sTempSpaceRecord.wszDirectory);
  4336. }
  4337. //
  4338. // Remove the entry from the registry
  4339. //
  4340. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", KEY_ALL_ACCESS);
  4341. 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]);
  4342. hResult = sRegistryKey.DeleteValue(szString);
  4343. fRemoved = TRUE;
  4344. }
  4345. }
  4346. dwIndex++;
  4347. }
  4348. sLock.UnLock();
  4349. //
  4350. // Did we actually find the matching temp space entry and remove it ?
  4351. //
  4352. if (FALSE == fRemoved)
  4353. {
  4354. hResult = APPMAN_E_INVALIDDATA;
  4355. }
  4356. return hResult;
  4357. }
  4358. //////////////////////////////////////////////////////////////////////////////////////////////
  4359. //
  4360. //////////////////////////////////////////////////////////////////////////////////////////////
  4361. STDMETHODIMP CInformationManager::EnumTempSpace(const DWORD dwIndex, LPTEMP_SPACE_RECORD lpTempSpaceRecord)
  4362. {
  4363. FUNCTION("CInfoMgr::EnumTempSpace ()");
  4364. CLock sLock(&m_CriticalSection);
  4365. CRegistryKey sRegistryKey;
  4366. TEMP_SPACE_RECORD sTempSpaceRecord;
  4367. HRESULT hResult = S_OK;
  4368. DWORD dwLoopIndex, dwTargetIndex, dwStringLen, dwSize, dwType;
  4369. CHAR szString[MAX_PATH_CHARCOUNT];
  4370. sLock.Lock();
  4371. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\TempSpaceAllocation", KEY_READ);
  4372. //
  4373. // Because of the way the registry works, we have to start enumerating keys with
  4374. // a starting index of 0 and increment constantly until we get to the desired index
  4375. //
  4376. dwTargetIndex = dwIndex;
  4377. dwLoopIndex = 0;
  4378. while ((dwLoopIndex <= dwTargetIndex)&&(S_OK == hResult))
  4379. {
  4380. dwStringLen = MAX_PATH_CHARCOUNT;
  4381. dwSize = sizeof(sTempSpaceRecord);
  4382. hResult = sRegistryKey.EnumValues(dwLoopIndex, szString, &dwStringLen, &dwType, (LPBYTE) &sTempSpaceRecord, &dwSize);
  4383. if (S_OK == hResult)
  4384. {
  4385. if (dwSize != sizeof(sTempSpaceRecord))
  4386. {
  4387. dwTargetIndex++;
  4388. }
  4389. }
  4390. dwLoopIndex++;
  4391. }
  4392. if (S_OK == hResult)
  4393. {
  4394. memcpy((LPVOID) lpTempSpaceRecord, (LPVOID) &sTempSpaceRecord, sizeof(TEMP_SPACE_RECORD));
  4395. }
  4396. else
  4397. {
  4398. hResult = APPMAN_E_INVALIDINDEX;
  4399. }
  4400. sRegistryKey.CloseKey();
  4401. sLock.UnLock();
  4402. return hResult;
  4403. }
  4404. //////////////////////////////////////////////////////////////////////////////////////////////
  4405. //
  4406. //////////////////////////////////////////////////////////////////////////////////////////////
  4407. STDMETHODIMP CInformationManager::AddAssociation(LPASSOCIATION_INFO lpAssociationInfo)
  4408. {
  4409. FUNCTION("CInfoMgr::AddAssociation ()");
  4410. CLock sLock(&m_CriticalSection);
  4411. CRegistryKey sRegistryKey;
  4412. CHAR szString[MAX_PATH_CHARCOUNT];
  4413. GUID sAssociationGuid;
  4414. sLock.Lock();
  4415. //
  4416. // Open the root registry key
  4417. //
  4418. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
  4419. //
  4420. // Assign a GUID to the association
  4421. //
  4422. if (FAILED(CoCreateGuid(&sAssociationGuid)))
  4423. {
  4424. THROW(E_UNEXPECTED);
  4425. }
  4426. 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]);
  4427. sRegistryKey.SetValue(szString, REG_BINARY, (LPBYTE) lpAssociationInfo, sizeof(ASSOCIATION_INFO));
  4428. sRegistryKey.CloseKey();
  4429. sLock.UnLock();
  4430. return S_OK;
  4431. }
  4432. //////////////////////////////////////////////////////////////////////////////////////////////
  4433. //
  4434. //////////////////////////////////////////////////////////////////////////////////////////////
  4435. STDMETHODIMP CInformationManager::RemoveAssociation(LPASSOCIATION_INFO lpAssociationInfo)
  4436. {
  4437. FUNCTION("CInfoMgr::RemoveAssociation ()");
  4438. CLock sLock(&m_CriticalSection);
  4439. CRegistryKey sRegistryKey;
  4440. ASSOCIATION_INFO sAssociationInfo;
  4441. CHAR szString[MAX_PATH_CHARCOUNT];
  4442. DWORD dwIndex, dwValueNameLen, dwDataType, dwDataLen;
  4443. sLock.Lock();
  4444. //
  4445. // Open the root registry key
  4446. //
  4447. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
  4448. //
  4449. // Enumerate all of the associations and find the matching one
  4450. //
  4451. dwIndex = 0;
  4452. dwDataLen = sizeof(ASSOCIATION_INFO);
  4453. dwValueNameLen = MAX_PATH_CHARCOUNT;
  4454. while (S_OK == sRegistryKey.EnumValues(dwIndex, szString, &dwValueNameLen, &dwDataType, (LPBYTE) &sAssociationInfo, &dwDataLen))
  4455. {
  4456. //
  4457. // Did we find the match
  4458. //
  4459. if (!memcmp(&sAssociationInfo, lpAssociationInfo, sizeof(ASSOCIATION_INFO)))
  4460. {
  4461. sRegistryKey.DeleteValue(szString);
  4462. break;
  4463. }
  4464. dwIndex++;
  4465. dwDataLen = sizeof(ASSOCIATION_INFO);
  4466. dwValueNameLen = MAX_PATH_CHARCOUNT;
  4467. }
  4468. sRegistryKey.CloseKey();
  4469. sLock.UnLock();
  4470. return S_OK;
  4471. }
  4472. //////////////////////////////////////////////////////////////////////////////////////////////
  4473. //
  4474. //////////////////////////////////////////////////////////////////////////////////////////////
  4475. STDMETHODIMP CInformationManager::EnumAssociations(const DWORD dwTargetIndex, LPASSOCIATION_INFO lpAssociationInfo)
  4476. {
  4477. FUNCTION("CInfoMgr::EnumAssociations ()");
  4478. CLock sLock(&m_CriticalSection);
  4479. CRegistryKey sRegistryKey;
  4480. ASSOCIATION_INFO sAssociationInfo;
  4481. CHAR szString[MAX_PATH_CHARCOUNT];
  4482. HRESULT hResult;
  4483. DWORD dwIndex, dwValueNameLen, dwDataType, dwDataLen;
  4484. sLock.Lock();
  4485. //
  4486. // Open the root registry key
  4487. //
  4488. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan\\Associations", KEY_ALL_ACCESS);
  4489. //
  4490. // Enumerate all of the associations and find the matching one
  4491. //
  4492. dwIndex = 0;
  4493. do
  4494. {
  4495. dwDataLen = sizeof(ASSOCIATION_INFO);
  4496. dwValueNameLen = MAX_PATH_CHARCOUNT;
  4497. hResult = sRegistryKey.EnumValues(dwIndex, szString, &dwValueNameLen, &dwDataType, (LPBYTE) &sAssociationInfo, &dwDataLen);
  4498. dwIndex++;
  4499. }
  4500. while ((dwIndex <= dwTargetIndex)&&(S_OK == hResult));
  4501. //
  4502. // Did the while loop terminate because we read in our target entry ?
  4503. //
  4504. if (S_OK == hResult)
  4505. {
  4506. memcpy((LPVOID) lpAssociationInfo, (LPVOID) &sAssociationInfo, sizeof(ASSOCIATION_INFO));
  4507. }
  4508. else
  4509. {
  4510. hResult = APPMAN_E_INVALIDINDEX;
  4511. }
  4512. sRegistryKey.CloseKey();
  4513. sLock.UnLock();
  4514. return hResult;
  4515. }
  4516. //////////////////////////////////////////////////////////////////////////////////////////////
  4517. //
  4518. // Returns the number of extra milliseconds that AppMan should wait for an Entry event
  4519. //
  4520. //////////////////////////////////////////////////////////////////////////////////////////////
  4521. DWORD CInformationManager::GetExtraWaitEventEntryTime(void)
  4522. {
  4523. CLock sLock(&m_CriticalSection);
  4524. CRegistryKey sRegistryKey;
  4525. DWORD dwType, dwSize;
  4526. DWORD dwWaitTime = 0;
  4527. sLock.Lock();
  4528. //
  4529. // Open the root AppMan key
  4530. //
  4531. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
  4532. dwSize = sizeof(dwWaitTime);
  4533. sRegistryKey.GetValue("WaitEntryEventExtraTime", &dwType, (BYTE *) &dwWaitTime, &dwSize);
  4534. sRegistryKey.CloseKey();
  4535. sLock.UnLock();
  4536. return dwWaitTime;
  4537. }
  4538. //////////////////////////////////////////////////////////////////////////////////////////////
  4539. //
  4540. // Returns the number of extra milliseconds that AppMan should wait for a Leave event
  4541. //
  4542. //////////////////////////////////////////////////////////////////////////////////////////////
  4543. DWORD CInformationManager::GetExtraWaitEventExitTime(void)
  4544. {
  4545. CLock sLock(&m_CriticalSection);
  4546. CRegistryKey sRegistryKey;
  4547. DWORD dwType, dwSize;
  4548. DWORD dwWaitTime = 0;
  4549. sLock.Lock();
  4550. //
  4551. // Open the root AppMan key
  4552. //
  4553. sRegistryKey.OpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppMan", KEY_READ);
  4554. dwSize = sizeof(dwWaitTime);
  4555. sRegistryKey.GetValue("WaitLeaveEventExtraTime", &dwType, (BYTE *) &dwWaitTime, &dwSize);
  4556. sRegistryKey.CloseKey();
  4557. sLock.UnLock();
  4558. return dwWaitTime;
  4559. }