Leaked source code of windows server 2003
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.

1669 lines
45 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. migrate.cpp
  5. Environment:
  6. WIN32 User Mode
  7. --*/
  8. #ifndef WIN32_LEAN_AND_MEAN
  9. #define WIN32_LEAN_AND_MEAN
  10. #endif
  11. #include <initguid.h>
  12. #include "migrate.h"
  13. #include <regstr.h>
  14. #include <ccstock.h>
  15. // this will change when the .h is moved to a public location
  16. #include "comp.h"
  17. const TCHAR szWhackDevice[] = TEXT("\\Device");
  18. #define IsRegStringType(x) (((x) == REG_SZ) || ((x) == REG_EXPAND_SZ) || ((x) == REG_MULTI_SZ))
  19. //
  20. // Data
  21. //
  22. PFN_CM_LOCATE_DEVNODE gpfn_CM_Locate_DevNode = NULL;
  23. PFN_SETUP_DI_ENUM_DEVICES_INTERFACES gpfn_SetupDiEnumDeviceInterfaces = NULL;
  24. PFN_SETUP_DI_GET_DEVICE_INTERFACE_DETAIL gpfn_SetupDiGetDeviceInterfaceDetail = NULL;
  25. PFN_SETUP_DI_CREATE_DEVICE_INTERFACE_REG_KEY gpfn_SetupDiCreateDeviceInterfaceRegKey = NULL;
  26. PFN_SETUP_DI_OPEN_DEVICE_INTERFACE_REG_KEY gpfn_SetupDiOpenDeviceInterfaceRegKey = NULL;
  27. PFN_SETUP_DI_CREATE_DEVICE_INTERFACE gpfn_SetupDiCreateDeviceInterface = NULL;
  28. //
  29. // DllMain
  30. //
  31. extern "C" {
  32. BOOL APIENTRY
  33. DllMain(HINSTANCE hDll,
  34. DWORD dwReason,
  35. LPVOID lpReserved)
  36. {
  37. switch (dwReason)
  38. {
  39. case DLL_PROCESS_ATTACH:
  40. break;
  41. case DLL_PROCESS_DETACH:
  42. break;
  43. case DLL_THREAD_DETACH:
  44. break;
  45. case DLL_THREAD_ATTACH:
  46. break;
  47. default:
  48. break;
  49. }
  50. return TRUE;
  51. }
  52. }
  53. BOOL
  54. VideoUpgradeCheck(
  55. PCOMPAIBILITYCALLBACK CompatibilityCallback,
  56. LPVOID Context
  57. )
  58. {
  59. DWORD dwDisposition;
  60. HKEY hKey = 0;
  61. OSVERSIONINFO osVer;
  62. BOOL bSuccess = FALSE;
  63. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  64. SZ_UPDATE_SETTINGS,
  65. 0,
  66. NULL,
  67. REG_OPTION_NON_VOLATILE,
  68. KEY_WRITE,
  69. NULL,
  70. &hKey,
  71. &dwDisposition) != ERROR_SUCCESS)
  72. {
  73. //
  74. // Oh well, guess we can't write it, no big deal
  75. //
  76. hKey = 0;
  77. goto Cleanup;
  78. }
  79. ZeroMemory(&osVer, sizeof(osVer));
  80. osVer.dwOSVersionInfoSize = sizeof(osVer);
  81. if (!GetVersionEx(&osVer))
  82. {
  83. //
  84. // We can't get the version info, no big deal
  85. //
  86. goto Cleanup;
  87. }
  88. //
  89. // Get the current device caps and store them away for the
  90. // display applet to apply later.
  91. // Do it only if this is not a remote session.
  92. //
  93. if (!GetSystemMetrics(SM_REMOTESESSION))
  94. {
  95. SaveDisplaySettings(hKey, &osVer);
  96. }
  97. //
  98. // Store the OS version we are upgrading from
  99. //
  100. SaveOsInfo(hKey, &osVer);
  101. //
  102. // Save the video services
  103. //
  104. if ((osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  105. (osVer.dwMajorVersion <= 4))
  106. {
  107. SaveNT4Services(hKey);
  108. }
  109. //
  110. // Save the applet extensions
  111. //
  112. if ((osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  113. (osVer.dwMajorVersion <= 5))
  114. {
  115. SaveAppletExtensions(hKey);
  116. }
  117. bSuccess = TRUE;
  118. Cleanup:
  119. if (hKey != 0)
  120. {
  121. RegCloseKey(hKey);
  122. }
  123. return bSuccess;
  124. }
  125. VOID
  126. SaveOsInfo(
  127. HKEY hKey,
  128. POSVERSIONINFO posVer
  129. )
  130. {
  131. DWORD cb;
  132. //
  133. // Can't just dump the struct into the registry b/c of the size
  134. // difference between CHAR and WCHAR (ie, szCSDVersion)
  135. //
  136. cb = sizeof(DWORD);
  137. RegSetValueEx(hKey,
  138. SZ_UPGRADE_FROM_PLATFORM,
  139. 0,
  140. REG_DWORD,
  141. (PBYTE)&(posVer->dwPlatformId),
  142. cb);
  143. cb = sizeof(DWORD);
  144. RegSetValueEx(hKey,
  145. SZ_UPGRADE_FROM_MAJOR_VERSION,
  146. 0,
  147. REG_DWORD,
  148. (PBYTE)&(posVer->dwMajorVersion),
  149. cb);
  150. cb = sizeof(DWORD);
  151. RegSetValueEx(hKey,
  152. SZ_UPGRADE_FROM_MINOR_VERSION,
  153. 0,
  154. REG_DWORD,
  155. (PBYTE)&(posVer->dwMinorVersion),
  156. cb);
  157. cb = sizeof(DWORD);
  158. RegSetValueEx(hKey,
  159. SZ_UPGRADE_FROM_BUILD_NUMBER,
  160. 0,
  161. REG_DWORD,
  162. (PBYTE)&(posVer->dwBuildNumber),
  163. cb);
  164. cb = lstrlen(posVer->szCSDVersion);
  165. RegSetValueEx(hKey,
  166. SZ_UPGRADE_FROM_VERSION_DESC,
  167. 0,
  168. REG_SZ,
  169. (PBYTE)&(posVer->szCSDVersion),
  170. cb);
  171. }
  172. BOOL
  173. SaveDisplaySettings(
  174. HKEY hKey,
  175. POSVERSIONINFO posVer
  176. )
  177. {
  178. PVU_PHYSICAL_DEVICE pPhysicalDevice = NULL;
  179. BOOL bSuccess = FALSE;
  180. if ((posVer->dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  181. (posVer->dwMajorVersion >= 5))
  182. {
  183. //
  184. // Try the new way to get the display settings
  185. //
  186. CollectDisplaySettings(&pPhysicalDevice);
  187. }
  188. if (pPhysicalDevice == NULL)
  189. {
  190. //
  191. // Try the old way to get the display settings
  192. //
  193. LegacyCollectDisplaySettings(&pPhysicalDevice);
  194. }
  195. if (pPhysicalDevice != NULL)
  196. {
  197. //
  198. // Save the display settings to registry
  199. //
  200. bSuccess = WriteDisplaySettingsToRegistry(hKey, pPhysicalDevice);
  201. //
  202. // Cleanup
  203. //
  204. FreeAllNodes(pPhysicalDevice);
  205. }
  206. return bSuccess;
  207. }
  208. BOOL
  209. GetDevInfoData(
  210. IN LPTSTR pDeviceKey,
  211. OUT HDEVINFO* phDevInfo,
  212. OUT PSP_DEVINFO_DATA pDevInfoData
  213. )
  214. /*
  215. Note: If this function retuns success, the caller is responsible
  216. to destroy the device info list returned in phDevInfo
  217. */
  218. {
  219. LPWSTR pwInterfaceName = NULL;
  220. LPWSTR pwInstanceID = NULL;
  221. BOOL bSuccess = FALSE;
  222. ASSERT (pDeviceKey != NULL);
  223. if (AllocAndReadInterfaceName(pDeviceKey, &pwInterfaceName))
  224. {
  225. bSuccess = GetDevInfoDataFromInterfaceName(pwInterfaceName,
  226. phDevInfo,
  227. pDevInfoData);
  228. LocalFree(pwInterfaceName);
  229. }
  230. if ((!bSuccess) &&
  231. AllocAndReadInstanceID(pDeviceKey, &pwInstanceID))
  232. {
  233. bSuccess = GetDevInfoDataFromInstanceID(pwInstanceID,
  234. phDevInfo,
  235. pDevInfoData);
  236. LocalFree(pwInstanceID);
  237. }
  238. return bSuccess;
  239. }
  240. BOOL
  241. GetDevInfoDataFromInterfaceName(
  242. IN LPWSTR pwInterfaceName,
  243. OUT HDEVINFO* phDevInfo,
  244. OUT PSP_DEVINFO_DATA pDevInfoData
  245. )
  246. /*
  247. Note: If this function retuns success, the caller is responsible
  248. to destroy the device info list returned in phDevInfo
  249. */
  250. {
  251. LPWSTR pwDevicePath = NULL;
  252. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  253. SP_DEVINFO_DATA DevInfoData;
  254. SP_DEVICE_INTERFACE_DATA InterfaceData;
  255. PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
  256. DWORD InterfaceIndex = 0;
  257. DWORD InterfaceSize = 0;
  258. BOOL bMatch = FALSE;
  259. ASSERT (pwInterfaceName != NULL);
  260. ASSERT (phDevInfo != NULL);
  261. ASSERT (pDevInfoData != NULL);
  262. ASSERT(gpfn_SetupDiEnumDeviceInterfaces != NULL);
  263. ASSERT(gpfn_SetupDiGetDeviceInterfaceDetail != NULL);
  264. //
  265. // Enumerate all display adapter interfaces
  266. //
  267. hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE,
  268. NULL,
  269. NULL,
  270. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  271. if (hDevInfo == INVALID_HANDLE_VALUE)
  272. {
  273. goto Cleanup;
  274. }
  275. InterfaceData.cbSize = sizeof(InterfaceData);
  276. while ((*gpfn_SetupDiEnumDeviceInterfaces)(hDevInfo,
  277. NULL,
  278. &GUID_DISPLAY_ADAPTER_INTERFACE,
  279. InterfaceIndex,
  280. &InterfaceData))
  281. {
  282. //
  283. // Get the required size for the interface
  284. //
  285. InterfaceSize = 0;
  286. (*gpfn_SetupDiGetDeviceInterfaceDetail)(hDevInfo,
  287. &InterfaceData,
  288. NULL,
  289. 0,
  290. &InterfaceSize,
  291. NULL);
  292. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  293. {
  294. goto Cleanup;
  295. }
  296. //
  297. // Alloc memory for the interface
  298. //
  299. pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) LocalAlloc(LPTR, InterfaceSize);
  300. if (pInterfaceDetailData == NULL)
  301. goto Cleanup;
  302. //
  303. // Get the interface
  304. //
  305. pInterfaceDetailData->cbSize = sizeof(*pInterfaceDetailData);
  306. DevInfoData.cbSize = sizeof(DevInfoData);
  307. if ((*gpfn_SetupDiGetDeviceInterfaceDetail)(hDevInfo,
  308. &InterfaceData,
  309. pInterfaceDetailData,
  310. InterfaceSize,
  311. &InterfaceSize,
  312. &DevInfoData))
  313. {
  314. //
  315. // Is the InterfaceName the same as the DevicePath?
  316. //
  317. pwDevicePath = pInterfaceDetailData->DevicePath;
  318. //
  319. // The first 4 characters of the interface name are different
  320. // between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
  321. // Therefore, ignore them.
  322. //
  323. bMatch = (_wcsnicmp(pwInterfaceName + 4,
  324. pwDevicePath + 4,
  325. wcslen(pwInterfaceName + 4)) == 0);
  326. if (bMatch)
  327. {
  328. //
  329. // We found the device
  330. //
  331. *phDevInfo = hDevInfo;
  332. CopyMemory(pDevInfoData, &DevInfoData, sizeof(*pDevInfoData));
  333. break;
  334. }
  335. }
  336. //
  337. // Clean-up
  338. //
  339. LocalFree(pInterfaceDetailData);
  340. pInterfaceDetailData = NULL;
  341. //
  342. // Next interface ...
  343. //
  344. InterfaceData.cbSize = sizeof(InterfaceData);
  345. ++InterfaceIndex;
  346. }
  347. Cleanup:
  348. if (pInterfaceDetailData != NULL)
  349. {
  350. LocalFree(pInterfaceDetailData);
  351. }
  352. //
  353. // Upon success, the caller is responsible to destroy the list
  354. //
  355. if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE))
  356. {
  357. SetupDiDestroyDeviceInfoList(hDevInfo);
  358. }
  359. return bMatch;
  360. }
  361. BOOL
  362. GetDevInfoDataFromInstanceID(
  363. IN LPWSTR pwInstanceID,
  364. OUT HDEVINFO* phDevInfo,
  365. OUT PSP_DEVINFO_DATA pDevInfoData
  366. )
  367. /*
  368. Note: If this function retuns success, the caller is responsible
  369. to destroy the device info list returned in phDevInfo
  370. */
  371. {
  372. LPTSTR pInstanceID = NULL;
  373. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  374. DWORD DeviceIndex = 0;
  375. SP_DEVINFO_DATA DevInfoData;
  376. DEVINST DevInst;
  377. BOOL bSuccess = FALSE, bLocate = FALSE;
  378. ASSERT (pwInstanceID != NULL);
  379. ASSERT (phDevInfo != NULL);
  380. ASSERT (pDevInfoData != NULL);
  381. ASSERT (gpfn_CM_Locate_DevNode != NULL);
  382. pInstanceID = pwInstanceID;
  383. bLocate = ((*gpfn_CM_Locate_DevNode)(&DevInst, pInstanceID, 0) == CR_SUCCESS);
  384. if (!bLocate)
  385. {
  386. goto Cleanup;
  387. }
  388. //
  389. // Enumerate all display adapters
  390. //
  391. hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVCLASS_DISPLAY,
  392. NULL,
  393. NULL,
  394. DIGCF_PRESENT);
  395. if (hDevInfo == INVALID_HANDLE_VALUE)
  396. {
  397. goto Cleanup;
  398. }
  399. DevInfoData.cbSize = sizeof(DevInfoData);
  400. while (SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex, &DevInfoData))
  401. {
  402. if (DevInfoData.DevInst == DevInst)
  403. {
  404. //
  405. // We found it
  406. //
  407. *phDevInfo = hDevInfo;
  408. CopyMemory(pDevInfoData, &DevInfoData, sizeof(*pDevInfoData));
  409. bSuccess = TRUE;
  410. break;
  411. }
  412. //
  413. // Next display adapter
  414. //
  415. ++DeviceIndex;
  416. DevInfoData.cbSize = sizeof(DevInfoData);
  417. }
  418. Cleanup:
  419. //
  420. // Upon success, the caller is responsible to destroy the list
  421. //
  422. if (!bSuccess && (hDevInfo != INVALID_HANDLE_VALUE))
  423. {
  424. SetupDiDestroyDeviceInfoList(hDevInfo);
  425. }
  426. return bSuccess;
  427. }
  428. VOID
  429. CollectDisplaySettings(
  430. PVU_PHYSICAL_DEVICE* ppPhysicalDevice
  431. )
  432. {
  433. DISPLAY_DEVICE DisplayDevice;
  434. DEVMODE DevMode;
  435. PVU_LOGICAL_DEVICE pLogicalDevice = NULL;
  436. DWORD dwEnum = 0;
  437. BOOL bGoOn = FALSE;
  438. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  439. SP_DEVINFO_DATA DevInfoData;
  440. DWORD BusNumber = 0, Address = 0;
  441. LPTSTR pDeviceX = NULL, pX = NULL;
  442. HINSTANCE hinstSetupApi = NULL;
  443. BOOL bInserted = FALSE;
  444. HKEY hDeviceKey = NULL;
  445. hinstSetupApi = LoadLibrary(TEXT("SETUPAPI.DLL"));
  446. if (hinstSetupApi == NULL)
  447. {
  448. goto Cleanup;
  449. }
  450. gpfn_CM_Locate_DevNode = (PFN_CM_LOCATE_DEVNODE)
  451. GetProcAddress(hinstSetupApi, "CM_Locate_DevNodeW");
  452. gpfn_SetupDiGetDeviceInterfaceDetail = (PFN_SETUP_DI_GET_DEVICE_INTERFACE_DETAIL)
  453. GetProcAddress(hinstSetupApi, "SetupDiGetDeviceInterfaceDetailW");
  454. gpfn_SetupDiCreateDeviceInterfaceRegKey = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE_REG_KEY)
  455. GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceRegKeyW");
  456. gpfn_SetupDiCreateDeviceInterface = (PFN_SETUP_DI_CREATE_DEVICE_INTERFACE)
  457. GetProcAddress(hinstSetupApi, "SetupDiCreateDeviceInterfaceW");
  458. gpfn_SetupDiEnumDeviceInterfaces = (PFN_SETUP_DI_ENUM_DEVICES_INTERFACES)
  459. GetProcAddress(hinstSetupApi, "SetupDiEnumDeviceInterfaces");
  460. gpfn_SetupDiOpenDeviceInterfaceRegKey = (PFN_SETUP_DI_OPEN_DEVICE_INTERFACE_REG_KEY)
  461. GetProcAddress(hinstSetupApi, "SetupDiOpenDeviceInterfaceRegKey");
  462. if ((gpfn_CM_Locate_DevNode == NULL) ||
  463. (gpfn_SetupDiEnumDeviceInterfaces == NULL) ||
  464. (gpfn_SetupDiGetDeviceInterfaceDetail == NULL) ||
  465. (gpfn_SetupDiCreateDeviceInterfaceRegKey == NULL) ||
  466. (gpfn_SetupDiOpenDeviceInterfaceRegKey == NULL) ||
  467. (gpfn_SetupDiCreateDeviceInterface == NULL))
  468. {
  469. goto Cleanup;
  470. }
  471. //
  472. // Enumerate all video devices
  473. //
  474. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  475. while (EnumDisplayDevices(NULL, dwEnum, &DisplayDevice, 0))
  476. {
  477. bInserted = FALSE;
  478. pLogicalDevice = NULL;
  479. //
  480. // Get the device info data corresponding to the current
  481. // video device
  482. //
  483. if (!GetDevInfoData(DisplayDevice.DeviceKey,
  484. &hDevInfo,
  485. &DevInfoData))
  486. {
  487. goto NextDevice;
  488. }
  489. ASSERT (hDevInfo != INVALID_HANDLE_VALUE);
  490. //
  491. // Retrieve the bus number and address
  492. //
  493. bGoOn = SetupDiGetDeviceRegistryProperty(hDevInfo,
  494. &DevInfoData,
  495. SPDRP_BUSNUMBER,
  496. NULL,
  497. (PBYTE)&BusNumber,
  498. sizeof(BusNumber),
  499. NULL) &&
  500. SetupDiGetDeviceRegistryProperty(hDevInfo,
  501. &DevInfoData,
  502. SPDRP_ADDRESS,
  503. NULL,
  504. (PBYTE)&Address,
  505. sizeof(Address),
  506. NULL);
  507. SetupDiDestroyDeviceInfoList(hDevInfo);
  508. if (!bGoOn)
  509. {
  510. goto NextDevice;
  511. }
  512. //
  513. // Allocate memory for the logical device
  514. //
  515. pLogicalDevice = (PVU_LOGICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_LOGICAL_DEVICE));
  516. if (pLogicalDevice == NULL)
  517. {
  518. goto NextDevice;
  519. }
  520. //
  521. // DeviceX
  522. //
  523. pDeviceX = DisplayDevice.DeviceKey + _tcslen(DisplayDevice.DeviceKey);
  524. while ((pDeviceX != DisplayDevice.DeviceKey) &&
  525. (*pDeviceX != TEXT('\\')))
  526. {
  527. pDeviceX--;
  528. }
  529. if (pDeviceX == DisplayDevice.DeviceKey)
  530. {
  531. goto NextDevice;
  532. }
  533. pX = SubStrEnd(SZ_DEVICE, pDeviceX);
  534. if (pX == pDeviceX)
  535. {
  536. //
  537. // The new key is used: CCS\Control\Video\[GUID]\000X
  538. //
  539. pX++;
  540. pLogicalDevice->DeviceX = _ttoi(pX);
  541. } else
  542. {
  543. //
  544. // The old key is used: CCS\Services\[SrvName]\DeviceX
  545. //
  546. pLogicalDevice->DeviceX = _ttoi(pX);
  547. }
  548. //
  549. // AttachedToDesktop
  550. //
  551. pLogicalDevice->AttachedToDesktop =
  552. ((DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0);
  553. pLogicalDevice->ValidFields |= VU_ATTACHED_TO_DESKTOP;
  554. if (pLogicalDevice->AttachedToDesktop)
  555. {
  556. //
  557. // Get the current mode
  558. //
  559. DevMode.dmSize = sizeof(DEVMODE);
  560. if (EnumDisplaySettings(DisplayDevice.DeviceName,
  561. ENUM_CURRENT_SETTINGS,
  562. &DevMode))
  563. {
  564. //
  565. // RelativeX, RelativeY, BitsPerPel, XResolution,
  566. // YResolution, VRefresh & Flags
  567. //
  568. pLogicalDevice->ValidFields |= VU_RELATIVE_X;
  569. pLogicalDevice->RelativeX = DevMode.dmPosition.x;
  570. pLogicalDevice->ValidFields |= VU_RELATIVE_Y;
  571. pLogicalDevice->RelativeY = DevMode.dmPosition.y;
  572. pLogicalDevice->ValidFields |= VU_BITS_PER_PEL;
  573. pLogicalDevice->BitsPerPel = DevMode.dmBitsPerPel;
  574. pLogicalDevice->ValidFields |= VU_X_RESOLUTION;
  575. pLogicalDevice->XResolution = DevMode.dmPelsWidth;
  576. pLogicalDevice->ValidFields |= VU_Y_RESOLUTION;
  577. pLogicalDevice->YResolution = DevMode.dmPelsHeight;
  578. pLogicalDevice->ValidFields |= VU_VREFRESH;
  579. pLogicalDevice->VRefresh = DevMode.dmDisplayFrequency;
  580. pLogicalDevice->ValidFields |= VU_FLAGS;
  581. pLogicalDevice->Flags = DevMode.dmDisplayFlags;
  582. //
  583. // Ignore the following settings for now:
  584. // DefaultSettings.XPanning - DevMode.dmPanningWidth
  585. // DefaultSettings.YPanning - DevMode.dmPanningHeight
  586. // DefaultSettings.DriverExtra - DevMode.dmDriverExtra
  587. //
  588. }
  589. }
  590. if (GetDeviceRegKey(DisplayDevice.DeviceKey,
  591. &hDeviceKey))
  592. {
  593. DWORD dwTemp, cb;
  594. //
  595. // Hardware acceleration
  596. //
  597. cb = sizeof(dwTemp);
  598. if (RegQueryValueEx(hDeviceKey,
  599. SZ_HW_ACCELERATION,
  600. NULL,
  601. NULL,
  602. (LPBYTE)&dwTemp,
  603. &cb) == ERROR_SUCCESS)
  604. {
  605. pLogicalDevice->ValidFields |= VU_HW_ACCELERATION;
  606. pLogicalDevice->HwAcceleration = dwTemp;
  607. }
  608. //
  609. // Pruning mode
  610. //
  611. cb = sizeof(dwTemp);
  612. if (RegQueryValueEx(hDeviceKey,
  613. SZ_PRUNNING_MODE,
  614. NULL,
  615. NULL,
  616. (LPBYTE)&dwTemp,
  617. &cb) == ERROR_SUCCESS)
  618. {
  619. pLogicalDevice->ValidFields |= VU_PRUNING_MODE;
  620. pLogicalDevice->PruningMode = dwTemp;
  621. }
  622. RegCloseKey(hDeviceKey);
  623. }
  624. bInserted = InsertNode(ppPhysicalDevice,
  625. pLogicalDevice,
  626. 0,
  627. BusNumber,
  628. Address);
  629. NextDevice:
  630. if (!bInserted && (pLogicalDevice != NULL))
  631. {
  632. LocalFree(pLogicalDevice);
  633. pLogicalDevice = NULL;
  634. }
  635. DisplayDevice.cb = sizeof(DISPLAY_DEVICE);
  636. ++dwEnum;
  637. }
  638. Cleanup:
  639. if (hinstSetupApi != NULL)
  640. {
  641. gpfn_CM_Locate_DevNode = NULL;
  642. gpfn_SetupDiEnumDeviceInterfaces = NULL;
  643. gpfn_SetupDiGetDeviceInterfaceDetail = NULL;
  644. gpfn_SetupDiCreateDeviceInterfaceRegKey = NULL;
  645. gpfn_SetupDiOpenDeviceInterfaceRegKey = NULL;
  646. gpfn_SetupDiCreateDeviceInterface = NULL;
  647. FreeLibrary(hinstSetupApi);
  648. }
  649. }
  650. BOOL
  651. InsertNode(
  652. PVU_PHYSICAL_DEVICE* ppPhysicalDevice,
  653. PVU_LOGICAL_DEVICE pLogicalDevice,
  654. DWORD Legacy,
  655. DWORD BusNumber,
  656. DWORD Address
  657. )
  658. {
  659. PVU_PHYSICAL_DEVICE pPhysicalDevice = *ppPhysicalDevice;
  660. BOOL bSuccess = FALSE;
  661. PVU_LOGICAL_DEVICE pPrevLogicalDevice = NULL;
  662. PVU_LOGICAL_DEVICE pNextLogicalDevice = NULL;
  663. ASSERT (pLogicalDevice != NULL);
  664. ASSERT((Legacy == 0) || (*ppPhysicalDevice == NULL));
  665. if (Legacy == 0)
  666. {
  667. //
  668. // If not Legacy, try to find if there is a device
  669. // with the same bus location
  670. //
  671. while (pPhysicalDevice != NULL)
  672. {
  673. if ((pPhysicalDevice->BusNumber == BusNumber) &&
  674. (pPhysicalDevice->Address == Address))
  675. {
  676. break;
  677. }
  678. pPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice;
  679. }
  680. }
  681. if (pPhysicalDevice != NULL)
  682. {
  683. //
  684. // There is already a logical device with the same address
  685. //
  686. ASSERT (pPhysicalDevice->pFirstLogicalDevice != NULL);
  687. pPhysicalDevice->CountOfLogicalDevices++;
  688. pPrevLogicalDevice = pNextLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
  689. while (pNextLogicalDevice &&
  690. (pNextLogicalDevice->DeviceX <= pLogicalDevice->DeviceX))
  691. {
  692. pPrevLogicalDevice = pNextLogicalDevice;
  693. pNextLogicalDevice = pNextLogicalDevice->pNextLogicalDevice;
  694. }
  695. if (pPrevLogicalDevice == pNextLogicalDevice)
  696. {
  697. ASSERT (pPrevLogicalDevice == pPhysicalDevice->pFirstLogicalDevice);
  698. pLogicalDevice->pNextLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
  699. pPhysicalDevice->pFirstLogicalDevice = pLogicalDevice;
  700. } else
  701. {
  702. pPrevLogicalDevice->pNextLogicalDevice = pLogicalDevice;
  703. pLogicalDevice->pNextLogicalDevice = pNextLogicalDevice;
  704. }
  705. bSuccess = TRUE;
  706. } else
  707. {
  708. //
  709. // This is a new physical device
  710. //
  711. pPhysicalDevice = (PVU_PHYSICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_PHYSICAL_DEVICE));
  712. if (pPhysicalDevice != NULL)
  713. {
  714. pPhysicalDevice->pNextPhysicalDevice = *ppPhysicalDevice;
  715. *ppPhysicalDevice = pPhysicalDevice;
  716. pPhysicalDevice->pFirstLogicalDevice = pLogicalDevice;
  717. pPhysicalDevice->CountOfLogicalDevices = 1;
  718. pPhysicalDevice->Legacy = Legacy;
  719. pPhysicalDevice->BusNumber = BusNumber;
  720. pPhysicalDevice->Address = Address;
  721. bSuccess = TRUE;
  722. }
  723. }
  724. return bSuccess;
  725. }
  726. VOID
  727. FreeAllNodes(
  728. PVU_PHYSICAL_DEVICE pPhysicalDevice
  729. )
  730. {
  731. PVU_PHYSICAL_DEVICE pTempPhysicalDevice = NULL;
  732. PVU_LOGICAL_DEVICE pLogicalDevice = NULL, pTempLogicalDevice = NULL;
  733. while (pPhysicalDevice != NULL)
  734. {
  735. pTempPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice;
  736. pLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
  737. while (pLogicalDevice != NULL)
  738. {
  739. pTempLogicalDevice = pLogicalDevice->pNextLogicalDevice;
  740. LocalFree(pLogicalDevice);
  741. pLogicalDevice = pTempLogicalDevice;
  742. }
  743. LocalFree(pPhysicalDevice);
  744. pPhysicalDevice = pTempPhysicalDevice;
  745. }
  746. }
  747. BOOL
  748. WriteDisplaySettingsToRegistry(
  749. HKEY hKey,
  750. PVU_PHYSICAL_DEVICE pPhysicalDevice
  751. )
  752. {
  753. PVU_LOGICAL_DEVICE pLogicalDevice = NULL;
  754. DWORD CountOfPhysicalDevices = 0;
  755. DWORD CountOfLogicalDevices = 0;
  756. HKEY hPysicalDeviceKey = 0;
  757. HKEY hLogicalDeviceKey = 0;
  758. BOOL bSuccess = FALSE;
  759. TCHAR Buffer[20];
  760. while (pPhysicalDevice != NULL)
  761. {
  762. //
  763. // Create physical device subkey
  764. //
  765. StringCchPrintf(Buffer, ARRAYSIZE(Buffer), TEXT("%s%d"), SZ_VU_PHYSICAL, CountOfPhysicalDevices);
  766. DeleteKeyAndSubkeys(hKey, Buffer);
  767. if (RegCreateKeyEx(hKey,
  768. Buffer,
  769. 0,
  770. NULL,
  771. REG_OPTION_NON_VOLATILE,
  772. KEY_WRITE,
  773. NULL,
  774. &hPysicalDeviceKey,
  775. NULL) != ERROR_SUCCESS)
  776. {
  777. hPysicalDeviceKey = 0;
  778. goto NextPhysicalDevice;
  779. }
  780. if (pPhysicalDevice->Legacy == 0)
  781. {
  782. //
  783. // BusNumber
  784. //
  785. if (RegSetValueEx(hPysicalDeviceKey,
  786. SZ_VU_BUS_NUMBER,
  787. 0,
  788. REG_DWORD,
  789. (PBYTE)&pPhysicalDevice->BusNumber,
  790. sizeof(pPhysicalDevice->BusNumber)) != ERROR_SUCCESS)
  791. {
  792. goto NextPhysicalDevice;
  793. }
  794. //
  795. // Address
  796. //
  797. if (RegSetValueEx(hPysicalDeviceKey,
  798. SZ_VU_ADDRESS,
  799. 0,
  800. REG_DWORD,
  801. (PBYTE)&pPhysicalDevice->Address,
  802. sizeof(pPhysicalDevice->Address)) != ERROR_SUCCESS)
  803. {
  804. goto NextPhysicalDevice;
  805. }
  806. }
  807. pLogicalDevice = pPhysicalDevice->pFirstLogicalDevice;
  808. CountOfLogicalDevices = 0;
  809. while (pLogicalDevice != NULL)
  810. {
  811. //
  812. // Create logical device subkey
  813. //
  814. StringCchPrintf(Buffer, ARRAYSIZE(Buffer), TEXT("%s%d"), SZ_VU_LOGICAL, CountOfLogicalDevices);
  815. if (RegCreateKeyEx(hPysicalDeviceKey,
  816. Buffer,
  817. 0,
  818. NULL,
  819. REG_OPTION_NON_VOLATILE,
  820. KEY_WRITE,
  821. NULL,
  822. &hLogicalDeviceKey,
  823. NULL) != ERROR_SUCCESS)
  824. {
  825. hLogicalDeviceKey = 0;
  826. //
  827. // Cannot go on with this physical device.
  828. // The order of logical devices DOES matter in the dual-view case.
  829. //
  830. break;
  831. }
  832. //
  833. // AttachedToDesktop
  834. //
  835. if (pLogicalDevice->ValidFields & VU_ATTACHED_TO_DESKTOP)
  836. {
  837. RegSetValueEx(hLogicalDeviceKey,
  838. SZ_VU_ATTACHED_TO_DESKTOP,
  839. 0,
  840. REG_DWORD,
  841. (PBYTE)&pLogicalDevice->AttachedToDesktop,
  842. sizeof(pLogicalDevice->AttachedToDesktop));
  843. }
  844. //
  845. // RelativeX
  846. //
  847. if (pLogicalDevice->ValidFields & VU_RELATIVE_X)
  848. {
  849. RegSetValueEx(hLogicalDeviceKey,
  850. SZ_VU_RELATIVE_X,
  851. 0,
  852. REG_DWORD,
  853. (PBYTE)&pLogicalDevice->RelativeX,
  854. sizeof(pLogicalDevice->RelativeX));
  855. }
  856. //
  857. // RelativeY
  858. //
  859. if (pLogicalDevice->ValidFields & VU_RELATIVE_Y)
  860. {
  861. RegSetValueEx(hLogicalDeviceKey,
  862. SZ_VU_RELATIVE_Y,
  863. 0,
  864. REG_DWORD,
  865. (PBYTE)&pLogicalDevice->RelativeY,
  866. sizeof(pLogicalDevice->RelativeY));
  867. }
  868. //
  869. // BitsPerPel
  870. //
  871. if (pLogicalDevice->ValidFields & VU_BITS_PER_PEL)
  872. {
  873. RegSetValueEx(hLogicalDeviceKey,
  874. SZ_VU_BITS_PER_PEL,
  875. 0,
  876. REG_DWORD,
  877. (PBYTE)&pLogicalDevice->BitsPerPel,
  878. sizeof(pLogicalDevice->BitsPerPel));
  879. }
  880. //
  881. // XResolution
  882. //
  883. if (pLogicalDevice->ValidFields & VU_X_RESOLUTION)
  884. {
  885. RegSetValueEx(hLogicalDeviceKey,
  886. SZ_VU_X_RESOLUTION,
  887. 0,
  888. REG_DWORD,
  889. (PBYTE)&pLogicalDevice->XResolution,
  890. sizeof(pLogicalDevice->XResolution));
  891. }
  892. //
  893. // YResolution
  894. //
  895. if (pLogicalDevice->ValidFields & VU_Y_RESOLUTION)
  896. {
  897. RegSetValueEx(hLogicalDeviceKey,
  898. SZ_VU_Y_RESOLUTION,
  899. 0,
  900. REG_DWORD,
  901. (PBYTE)&pLogicalDevice->YResolution,
  902. sizeof(pLogicalDevice->YResolution));
  903. }
  904. //
  905. // VRefresh
  906. //
  907. if (pLogicalDevice->ValidFields & VU_VREFRESH)
  908. {
  909. RegSetValueEx(hLogicalDeviceKey,
  910. SZ_VU_VREFRESH,
  911. 0,
  912. REG_DWORD,
  913. (PBYTE)&pLogicalDevice->VRefresh,
  914. sizeof(pLogicalDevice->VRefresh));
  915. }
  916. //
  917. // Flags
  918. //
  919. if (pLogicalDevice->ValidFields & VU_FLAGS)
  920. {
  921. RegSetValueEx(hLogicalDeviceKey,
  922. SZ_VU_FLAGS,
  923. 0,
  924. REG_DWORD,
  925. (PBYTE)&pLogicalDevice->Flags,
  926. sizeof(pLogicalDevice->Flags));
  927. }
  928. //
  929. // Hardware acceleration
  930. //
  931. if (pLogicalDevice->ValidFields & VU_HW_ACCELERATION)
  932. {
  933. RegSetValueEx(hLogicalDeviceKey,
  934. SZ_HW_ACCELERATION,
  935. 0,
  936. REG_DWORD,
  937. (PBYTE)&pLogicalDevice->HwAcceleration,
  938. sizeof(pLogicalDevice->HwAcceleration));
  939. }
  940. //
  941. // Pruning mode
  942. //
  943. if (pLogicalDevice->ValidFields & VU_PRUNING_MODE)
  944. {
  945. RegSetValueEx(hLogicalDeviceKey,
  946. SZ_PRUNNING_MODE,
  947. 0,
  948. REG_DWORD,
  949. (PBYTE)&pLogicalDevice->PruningMode,
  950. sizeof(pLogicalDevice->PruningMode));
  951. }
  952. ++CountOfLogicalDevices;
  953. RegCloseKey(hLogicalDeviceKey);
  954. hLogicalDeviceKey = 0;
  955. pLogicalDevice = pLogicalDevice->pNextLogicalDevice;
  956. }
  957. if ((CountOfLogicalDevices > 0) &&
  958. (RegSetValueEx(hPysicalDeviceKey,
  959. SZ_VU_COUNT,
  960. 0,
  961. REG_DWORD,
  962. (PBYTE)&CountOfLogicalDevices,
  963. sizeof(CountOfLogicalDevices)) == ERROR_SUCCESS))
  964. {
  965. ++CountOfPhysicalDevices;
  966. }
  967. NextPhysicalDevice:
  968. if (hPysicalDeviceKey != 0)
  969. {
  970. RegCloseKey(hPysicalDeviceKey);
  971. hPysicalDeviceKey = 0;
  972. }
  973. pPhysicalDevice = pPhysicalDevice->pNextPhysicalDevice;
  974. }
  975. if (CountOfPhysicalDevices > 0)
  976. {
  977. bSuccess = (RegSetValueEx(hKey,
  978. SZ_VU_COUNT,
  979. 0,
  980. REG_DWORD,
  981. (PBYTE)&CountOfPhysicalDevices,
  982. sizeof(CountOfPhysicalDevices)) != ERROR_SUCCESS);
  983. }
  984. return bSuccess;
  985. }
  986. VOID
  987. LegacyCollectDisplaySettings(
  988. PVU_PHYSICAL_DEVICE* ppPhysicalDevice
  989. )
  990. {
  991. PVU_LOGICAL_DEVICE pLogicalDevice = NULL;
  992. INT Width, Height, Index;
  993. BOOL useVga = FALSE;
  994. HDC hDisplay;
  995. POINT Res[] = {
  996. { 640, 480},
  997. { 800, 600},
  998. { 1024, 768},
  999. { 1152, 900},
  1000. { 1280, 1024},
  1001. { 1600, 1200},
  1002. { 0, 0} // end of table
  1003. };
  1004. ASSERT (*ppPhysicalDevice == NULL);
  1005. //
  1006. // Allocate memory for the logical device
  1007. //
  1008. pLogicalDevice = (PVU_LOGICAL_DEVICE) LocalAlloc(LPTR, sizeof(VU_LOGICAL_DEVICE));
  1009. if (pLogicalDevice == NULL)
  1010. {
  1011. return;
  1012. }
  1013. Width = GetSystemMetrics(SM_CXSCREEN);
  1014. Height = GetSystemMetrics(SM_CYSCREEN);
  1015. if (Width == 0 || Height == 0)
  1016. {
  1017. //
  1018. // Something went wrong, default to lowest common res
  1019. //
  1020. useVga = TRUE;
  1021. }
  1022. //
  1023. // NT 4.0 multimon via driver vendor, not the OS ... adjust the width and height
  1024. // back to normal values. Once setup is complete, the second card will come
  1025. // on line and it will be taken care of. In both cases, the video area must
  1026. // be rectangular, not like MM on 5.0 where we can have "holes"
  1027. //
  1028. else if (Width >= 2 * Height)
  1029. {
  1030. //
  1031. // Wide
  1032. //
  1033. for (Index = 0; Res[Index].x != 0; Index++)
  1034. {
  1035. if (Res[Index].y == Height)
  1036. {
  1037. Width = Res[Index].x;
  1038. break;
  1039. }
  1040. }
  1041. useVga = (Res[Index].x == 0);
  1042. } else if (Height > Width)
  1043. {
  1044. //
  1045. // Tall
  1046. //
  1047. for (Index = 0; Res[Index].x != 0; Index++)
  1048. {
  1049. if (Res[Index].x == Width)
  1050. {
  1051. Height = Res[Index].y;
  1052. break;
  1053. }
  1054. }
  1055. useVga = (Res[Index].x == 0);
  1056. }
  1057. if (useVga)
  1058. {
  1059. //
  1060. // No match, default to VGA
  1061. //
  1062. Width = 640;
  1063. Height = 480;
  1064. }
  1065. pLogicalDevice->ValidFields |= VU_ATTACHED_TO_DESKTOP;
  1066. pLogicalDevice->AttachedToDesktop = 1;
  1067. pLogicalDevice->ValidFields |= VU_X_RESOLUTION;
  1068. pLogicalDevice->XResolution = Width;
  1069. pLogicalDevice->ValidFields |= VU_Y_RESOLUTION;
  1070. pLogicalDevice->YResolution = Height;
  1071. hDisplay = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  1072. if (hDisplay)
  1073. {
  1074. pLogicalDevice->ValidFields |= VU_BITS_PER_PEL;
  1075. pLogicalDevice->BitsPerPel = GetDeviceCaps(hDisplay, BITSPIXEL);
  1076. pLogicalDevice->ValidFields |= VU_VREFRESH;
  1077. pLogicalDevice->VRefresh = GetDeviceCaps(hDisplay, VREFRESH);
  1078. DeleteDC(hDisplay);
  1079. }
  1080. if (!InsertNode(ppPhysicalDevice,
  1081. pLogicalDevice,
  1082. 1,
  1083. 0,
  1084. 0))
  1085. {
  1086. //
  1087. // Clean-up
  1088. //
  1089. LocalFree(pLogicalDevice);
  1090. }
  1091. }
  1092. VOID
  1093. SaveNT4Services(
  1094. HKEY hKey
  1095. )
  1096. {
  1097. SC_HANDLE hSCManager = NULL;
  1098. ENUM_SERVICE_STATUS* pmszAllServices = NULL;
  1099. QUERY_SERVICE_CONFIG* pServiceConfig = NULL;
  1100. SC_HANDLE hService = NULL;
  1101. DWORD cbBytesNeeded = 0;
  1102. DWORD ServicesReturned = 0;
  1103. DWORD ResumeHandle = 0;
  1104. DWORD ServiceLen = 0, TotalLen = 0, AllocatedLen = 128;
  1105. PTCHAR pmszVideoServices = NULL, pmszTemp = NULL;
  1106. //
  1107. // Allocate initial memory
  1108. //
  1109. pmszVideoServices = (PTCHAR)LocalAlloc(LPTR, AllocatedLen * sizeof(TCHAR));
  1110. if (pmszVideoServices == NULL)
  1111. {
  1112. goto Fallout;
  1113. }
  1114. //
  1115. // Open the service control manager
  1116. //
  1117. hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  1118. if (hSCManager == NULL)
  1119. {
  1120. goto Fallout;
  1121. }
  1122. //
  1123. // Get the required size
  1124. //
  1125. if ((!EnumServicesStatus(hSCManager,
  1126. SERVICE_DRIVER,
  1127. SERVICE_STATE_ALL,
  1128. NULL,
  1129. 0,
  1130. &cbBytesNeeded,
  1131. &ServicesReturned,
  1132. &ResumeHandle)) &&
  1133. (GetLastError() != ERROR_MORE_DATA))
  1134. {
  1135. goto Fallout;
  1136. }
  1137. //
  1138. // Allocate the memory
  1139. //
  1140. pmszAllServices = (ENUM_SERVICE_STATUS*)LocalAlloc(LPTR, cbBytesNeeded);
  1141. if (pmszAllServices == NULL)
  1142. {
  1143. goto Fallout;
  1144. }
  1145. //
  1146. // Get the services
  1147. //
  1148. ServicesReturned = ResumeHandle = 0;
  1149. if (!EnumServicesStatus(hSCManager,
  1150. SERVICE_DRIVER,
  1151. SERVICE_STATE_ALL,
  1152. pmszAllServices,
  1153. cbBytesNeeded,
  1154. &cbBytesNeeded,
  1155. &ServicesReturned,
  1156. &ResumeHandle))
  1157. {
  1158. goto Fallout;
  1159. }
  1160. while (ServicesReturned--)
  1161. {
  1162. //
  1163. // Open the service
  1164. //
  1165. hService = OpenService(hSCManager,
  1166. pmszAllServices[ServicesReturned].lpServiceName,
  1167. SERVICE_ALL_ACCESS);
  1168. if (hService != NULL)
  1169. {
  1170. //
  1171. // Get the required size to store the config info
  1172. //
  1173. cbBytesNeeded = 0;
  1174. if (QueryServiceConfig(hService,
  1175. NULL,
  1176. 0,
  1177. &cbBytesNeeded) ||
  1178. (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  1179. {
  1180. //
  1181. // Allocate the memory
  1182. //
  1183. pServiceConfig = (QUERY_SERVICE_CONFIG*) LocalAlloc(LPTR, cbBytesNeeded);
  1184. if (pServiceConfig != NULL)
  1185. {
  1186. //
  1187. // Get the config info
  1188. //
  1189. if (QueryServiceConfig(hService,
  1190. pServiceConfig,
  1191. cbBytesNeeded,
  1192. &cbBytesNeeded) &&
  1193. (pServiceConfig->dwStartType != SERVICE_DISABLED) &&
  1194. (_tcsicmp(pServiceConfig->lpLoadOrderGroup, TEXT("Video")) == 0))
  1195. {
  1196. ServiceLen = _tcslen(pmszAllServices[ServicesReturned].lpServiceName);
  1197. if (TotalLen + ServiceLen + 2 > AllocatedLen)
  1198. {
  1199. AllocatedLen = TotalLen + ServiceLen + 128;
  1200. pmszTemp = (PTCHAR)LocalAlloc(LPTR, AllocatedLen * sizeof(TCHAR));
  1201. if (pmszTemp == NULL)
  1202. {
  1203. goto Fallout;
  1204. }
  1205. CopyMemory(pmszTemp, pmszVideoServices, TotalLen * sizeof(TCHAR));
  1206. LocalFree(pmszVideoServices);
  1207. pmszVideoServices = pmszTemp;
  1208. pmszTemp = NULL;
  1209. }
  1210. StringCchCopy(pmszVideoServices + TotalLen, AllocatedLen - TotalLen, pmszAllServices[ServicesReturned].lpServiceName);
  1211. TotalLen += ServiceLen + 1;
  1212. }
  1213. LocalFree(pServiceConfig);
  1214. pServiceConfig = NULL;
  1215. }
  1216. }
  1217. CloseServiceHandle(hService);
  1218. hService = NULL;
  1219. }
  1220. }
  1221. //
  1222. // Save the services to the registry
  1223. //
  1224. pmszVideoServices[TotalLen++] = TEXT('\0');
  1225. RegSetValueEx(hKey,
  1226. SZ_SERVICES_TO_DISABLE,
  1227. 0,
  1228. REG_MULTI_SZ,
  1229. (BYTE*)pmszVideoServices,
  1230. TotalLen * sizeof(TCHAR));
  1231. Fallout:
  1232. if (hService != NULL)
  1233. {
  1234. CloseServiceHandle(hService);
  1235. }
  1236. if (pServiceConfig != NULL)
  1237. {
  1238. LocalFree(pServiceConfig);
  1239. }
  1240. if (pmszAllServices != NULL)
  1241. {
  1242. LocalFree(pmszAllServices);
  1243. }
  1244. if (hSCManager != NULL)
  1245. {
  1246. CloseServiceHandle(hSCManager);
  1247. }
  1248. if (pmszVideoServices != NULL)
  1249. {
  1250. LocalFree(pmszVideoServices);
  1251. }
  1252. } // SaveNT4Services
  1253. BOOL
  1254. DeleteKeyAndSubkeys(
  1255. HKEY hKey,
  1256. LPCTSTR lpSubKey
  1257. )
  1258. {
  1259. HKEY hkDeleteKey;
  1260. TCHAR szChild[MAX_PATH + 1];
  1261. BOOL bReturn = FALSE;
  1262. if (RegOpenKeyEx(hKey,
  1263. lpSubKey,
  1264. 0,
  1265. KEY_READ | KEY_WRITE,
  1266. &hkDeleteKey) == ERROR_SUCCESS)
  1267. {
  1268. bReturn = TRUE;
  1269. while (RegEnumKey(hkDeleteKey, 0, szChild, ARRAYSIZE(szChild)) == ERROR_SUCCESS)
  1270. {
  1271. if (!DeleteKeyAndSubkeys(hkDeleteKey, szChild))
  1272. {
  1273. bReturn = FALSE;
  1274. break;
  1275. }
  1276. }
  1277. RegCloseKey(hkDeleteKey);
  1278. if (bReturn)
  1279. bReturn = (RegDeleteKey(hKey, lpSubKey) == ERROR_SUCCESS);
  1280. }
  1281. return bReturn;
  1282. }
  1283. VOID
  1284. SaveAppletExtensions(
  1285. HKEY hKey
  1286. )
  1287. {
  1288. PAPPEXT pAppExt = NULL;
  1289. PAPPEXT pAppExtTemp;
  1290. DWORD Len = 0;
  1291. PTCHAR pmszAppExt = NULL;
  1292. DWORD cchAppExt;
  1293. HKEY hkDisplay;
  1294. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1295. REGSTR_PATH_CONTROLSFOLDER_DISPLAY_SHEX_PROPSHEET,
  1296. 0,
  1297. KEY_READ,
  1298. &hkDisplay) == ERROR_SUCCESS)
  1299. {
  1300. DeskAESnapshot(hkDisplay, &pAppExt);
  1301. if (pAppExt != NULL)
  1302. {
  1303. pAppExtTemp = pAppExt;
  1304. while (pAppExtTemp)
  1305. {
  1306. Len += lstrlen(pAppExtTemp->szDefaultValue) + 1;
  1307. pAppExtTemp = pAppExtTemp->pNext;
  1308. }
  1309. cchAppExt = (Len + 1);
  1310. pmszAppExt = (PTCHAR)LocalAlloc(LPTR, cchAppExt * sizeof(TCHAR));
  1311. if (pmszAppExt != NULL) {
  1312. pAppExtTemp = pAppExt;
  1313. Len = 0;
  1314. while (pAppExtTemp) {
  1315. StringCchCopy(pmszAppExt + Len, cchAppExt - Len, pAppExtTemp->szDefaultValue);
  1316. Len += lstrlen(pAppExtTemp->szDefaultValue) + 1;
  1317. pAppExtTemp = pAppExtTemp->pNext;
  1318. }
  1319. RegSetValueEx(hKey,
  1320. SZ_APPEXT_TO_DELETE,
  1321. 0,
  1322. REG_MULTI_SZ,
  1323. (BYTE*)pmszAppExt,
  1324. (Len + 1) * sizeof(TCHAR));
  1325. LocalFree(pmszAppExt);
  1326. }
  1327. DeskAECleanup(pAppExt);
  1328. }
  1329. RegCloseKey(hkDisplay);
  1330. }
  1331. }