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.

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