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.

642 lines
16 KiB

  1. /**************************************************************************\
  2. * Module Name: ntreg.cpp
  3. *
  4. * CRegistrySettings class
  5. *
  6. * This class handles getting registry information for display driver
  7. * information.
  8. *
  9. * Copyright (c) Microsoft Corp. 1992-1998 All Rights Reserved
  10. *
  11. \**************************************************************************/
  12. #include "priv.h"
  13. #include <tchar.h>
  14. #include "ntreg.hxx"
  15. #include <devguid.h>
  16. //
  17. // CRegistrySettings constructor
  18. //
  19. CRegistrySettings::CRegistrySettings(LPTSTR pstrDeviceKey)
  20. : _hkVideoReg(NULL)
  21. , _pszDrvName(NULL)
  22. , _pszKeyName(NULL)
  23. , _pszDeviceInstanceId(NULL)
  24. , _dwDevInst(0)
  25. {
  26. TCHAR szBuffer[MAX_PATH];
  27. LPTSTR pszPath;
  28. HKEY hkeyCommon, hkeyDriver;
  29. DWORD cb;
  30. LPTSTR pszName = NULL;
  31. LPTSTR pszEnd;
  32. ASSERT(lstrlen(pstrDeviceKey) < MAX_PATH);
  33. //
  34. // Copy the data to local buffer.
  35. //
  36. lstrcpy(szBuffer, pstrDeviceKey);
  37. //
  38. // Initialize the device instance id
  39. //
  40. InitDeviceInstanceID(szBuffer);
  41. //
  42. // At this point, szBuffer has something like:
  43. // \REGISTRY\Machine\System\ControlSet001\...
  44. //
  45. // To use the Win32 registry calls, we have to strip off the \REGISTRY
  46. // and convert \Machine to HKEY_LOCAL_MACHINE
  47. //
  48. pszPath = SubStrEnd(SZ_REGISTRYMACHINE, szBuffer);
  49. //
  50. // Try to open the registry key
  51. //
  52. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  53. pszPath,
  54. 0,
  55. KEY_READ,
  56. &_hkVideoReg) != ERROR_SUCCESS) {
  57. _hkVideoReg = 0;
  58. }
  59. //
  60. // Go to the video subkey
  61. //
  62. pszEnd = pszPath + lstrlen(pszPath);
  63. while (pszEnd != pszPath && *pszEnd != TEXT('\\')) {
  64. pszEnd--;
  65. }
  66. *pszEnd = UNICODE_NULL;
  67. lstrcat(pszPath, SZ_COMMON_SUBKEY);
  68. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  69. pszPath,
  70. 0,
  71. KEY_READ,
  72. &hkeyCommon) == ERROR_SUCCESS) {
  73. cb = sizeof(szBuffer);
  74. ZeroMemory(szBuffer, cb);
  75. if (RegQueryValueEx(hkeyCommon,
  76. SZ_SERVICE,
  77. NULL,
  78. NULL,
  79. (LPBYTE)szBuffer,
  80. &cb) == ERROR_SUCCESS) {
  81. //
  82. // Save the key name
  83. //
  84. _pszKeyName = (LPTSTR)LocalAlloc(LPTR,
  85. (lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  86. if (_pszKeyName != NULL) {
  87. lstrcpy(_pszKeyName, szBuffer);
  88. lstrcpy(szBuffer, SZ_SERVICES_PATH);
  89. lstrcat(szBuffer, _pszKeyName);
  90. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  91. szBuffer,
  92. 0,
  93. KEY_READ,
  94. &hkeyDriver) == ERROR_SUCCESS) {
  95. cb = sizeof(szBuffer);
  96. ZeroMemory(szBuffer, cb);
  97. if (RegQueryValueEx(hkeyDriver,
  98. L"ImagePath",
  99. NULL,
  100. NULL,
  101. (LPBYTE)szBuffer,
  102. &cb) == ERROR_SUCCESS) {
  103. //
  104. // This is a binary.
  105. // Extract the name, which will be of the form ...\driver.sys
  106. //
  107. LPTSTR pszDriver, pszDriverEnd;
  108. pszDriver = szBuffer;
  109. pszDriverEnd = pszDriver + lstrlen(pszDriver);
  110. while(pszDriverEnd != pszDriver &&
  111. *pszDriverEnd != TEXT('.')) {
  112. pszDriverEnd--;
  113. }
  114. *pszDriverEnd = UNICODE_NULL;
  115. while(pszDriverEnd != pszDriver &&
  116. *pszDriverEnd != TEXT('\\')) {
  117. pszDriverEnd--;
  118. }
  119. //
  120. // If pszDriver and pszDriverEnd are different, we now
  121. // have the driver name.
  122. //
  123. if (pszDriverEnd > pszDriver) {
  124. pszDriverEnd++;
  125. pszName = pszDriverEnd;
  126. }
  127. }
  128. RegCloseKey(hkeyDriver);
  129. }
  130. if (!pszName) {
  131. //
  132. // Something failed trying to get the binary name.just get the device name
  133. //
  134. _pszDrvName = _pszKeyName;
  135. } else {
  136. _pszDrvName = (LPTSTR)LocalAlloc(LPTR,
  137. (lstrlen(pszName) + 1) * sizeof(TCHAR));
  138. if (_pszDrvName != NULL) {
  139. lstrcpy(_pszDrvName, pszName);
  140. }
  141. }
  142. }
  143. }
  144. RegCloseKey(hkeyCommon);
  145. }
  146. }
  147. //
  148. // CRegistrySettings destructor
  149. //
  150. CRegistrySettings::~CRegistrySettings()
  151. {
  152. //
  153. // Close the registry
  154. //
  155. if (_hkVideoReg) {
  156. RegCloseKey(_hkVideoReg);
  157. }
  158. //
  159. // Free the strings
  160. //
  161. if (_pszKeyName) {
  162. LocalFree(_pszKeyName);
  163. }
  164. if ((_pszKeyName != _pszDrvName) && _pszDrvName) {
  165. LocalFree(_pszDrvName);
  166. }
  167. if(_pszDeviceInstanceId) {
  168. LocalFree(_pszDeviceInstanceId);
  169. }
  170. }
  171. //
  172. // Method to get the hardware information fields.
  173. //
  174. VOID
  175. CRegistrySettings::GetHardwareInformation(
  176. PDISPLAY_REGISTRY_HARDWARE_INFO pInfo)
  177. {
  178. DWORD cb, dwType;
  179. DWORD i;
  180. LONG lRet;
  181. LPWSTR pKeyNames[5] = {
  182. L"HardwareInformation.MemorySize",
  183. L"HardwareInformation.ChipType",
  184. L"HardwareInformation.DacType",
  185. L"HardwareInformation.AdapterString",
  186. L"HardwareInformation.BiosString"
  187. };
  188. ZeroMemory(pInfo, sizeof(DISPLAY_REGISTRY_HARDWARE_INFO));
  189. //
  190. // Query each entry one after the other.
  191. //
  192. for (i = 0; i < 5; i++) {
  193. //
  194. // query the size of the string
  195. //
  196. cb = 256;
  197. lRet = RegQueryValueExW(_hkVideoReg,
  198. pKeyNames[i],
  199. NULL,
  200. &dwType,
  201. NULL,
  202. &cb);
  203. if (lRet == ERROR_SUCCESS) {
  204. if (i == 0) {
  205. ULONG mem;
  206. cb = 4;
  207. RegQueryValueExW(_hkVideoReg,
  208. pKeyNames[i],
  209. NULL,
  210. &dwType,
  211. (PUCHAR) (&mem),
  212. &cb);
  213. //
  214. // If we queried the memory size, we actually have
  215. // a DWORD. Transform the DWORD to a string
  216. //
  217. // Divide down to Ks
  218. mem = mem >> 10;
  219. // if a MB multiple, divide again.
  220. if ((mem & 0x3FF) != 0) {
  221. wsprintf((LPWSTR)pInfo, L"%d KB", mem );
  222. } else {
  223. wsprintf((LPWSTR)pInfo, L"%d MB", mem >> 10 );
  224. }
  225. } else {
  226. cb = 256;
  227. //
  228. // get the string
  229. //
  230. RegQueryValueExW(_hkVideoReg,
  231. pKeyNames[i],
  232. NULL,
  233. &dwType,
  234. (LPBYTE) pInfo,
  235. &cb);
  236. }
  237. }
  238. else
  239. {
  240. //
  241. // Put in the default string
  242. //
  243. LoadString(HINST_THISDLL,
  244. IDS_UNAVAILABLE,
  245. (LPWSTR)pInfo,
  246. 256);
  247. }
  248. pInfo = (PDISPLAY_REGISTRY_HARDWARE_INFO)((PUCHAR)pInfo + 256);
  249. }
  250. return;
  251. }
  252. VOID CRegistrySettings::InitDeviceInstanceID(
  253. LPTSTR pstrDeviceKey
  254. )
  255. {
  256. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE ;
  257. SP_DEVINFO_DATA DevInfoData;
  258. ULONG InstanceIDSize = 0;
  259. BOOL bSuccess = FALSE;
  260. LPWSTR pwInterfaceName = NULL;
  261. LPWSTR pwInstanceID = NULL;
  262. ASSERT (pstrDeviceKey != NULL);
  263. ASSERT (_pszDeviceInstanceId == NULL);
  264. if (AllocAndReadInterfaceName(pstrDeviceKey, &pwInterfaceName)) {
  265. bSuccess = GetDevInfoDataFromInterfaceName(pwInterfaceName,
  266. &hDevInfo,
  267. &DevInfoData);
  268. if (bSuccess) {
  269. InstanceIDSize = 0;
  270. bSuccess =
  271. ((CM_Get_Device_ID_Size(&InstanceIDSize,
  272. DevInfoData.DevInst,
  273. 0) == CR_SUCCESS) &&
  274. ((_pszDeviceInstanceId = (LPTSTR)LocalAlloc(LPTR,
  275. (InstanceIDSize + 1) * sizeof(TCHAR))) != NULL) &&
  276. (CM_Get_Device_ID(DevInfoData.DevInst,
  277. _pszDeviceInstanceId,
  278. InstanceIDSize,
  279. 0) == CR_SUCCESS));
  280. if (bSuccess) {
  281. _dwDevInst = DevInfoData.DevInst;
  282. } else {
  283. //
  284. // Clean-up
  285. //
  286. if (NULL != _pszDeviceInstanceId) {
  287. LocalFree(_pszDeviceInstanceId);
  288. _pszDeviceInstanceId = NULL;
  289. }
  290. }
  291. SetupDiDestroyDeviceInfoList(hDevInfo);
  292. }
  293. LocalFree(pwInterfaceName);
  294. }
  295. if ((!bSuccess) &&
  296. AllocAndReadInstanceID(pstrDeviceKey, &pwInstanceID)) {
  297. #ifdef UNICODE
  298. _pszDeviceInstanceId = pwInstanceID;
  299. #else
  300. SIZE_T cch = wcslen(pwInstanceID) + 1;
  301. _pszDeviceInstanceId = LocalAlloc(LPTR, cch);
  302. if (_pszDeviceInstanceId != NULL) {
  303. WideCharToMultiByte(CP_ACP, 0,
  304. pwInstanceID, -1,
  305. _pszDeviceInstanceId,
  306. cch, NULL, NULL);
  307. }
  308. LocalFree(pwInstanceID);
  309. #endif
  310. }
  311. } // InitDeviceInstanceID
  312. BOOL
  313. CRegistrySettings::GetDevInfoDataFromInterfaceName(
  314. IN LPWSTR pwInterfaceName,
  315. OUT HDEVINFO* phDevInfo,
  316. OUT PSP_DEVINFO_DATA pDevInfoData
  317. )
  318. /*
  319. Note: If this function retuns success, the caller is responsible
  320. to destroy the device info list returned in phDevInfo
  321. */
  322. {
  323. LPWSTR pwDevicePath = NULL;
  324. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  325. SP_DEVINFO_DATA DevInfoData;
  326. SP_DEVICE_INTERFACE_DATA InterfaceData;
  327. PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
  328. DWORD InterfaceIndex = 0;
  329. DWORD InterfaceSize = 0;
  330. BOOL bMatch = FALSE;
  331. ASSERT (pwInterfaceName != NULL);
  332. ASSERT (phDevInfo != NULL);
  333. ASSERT (pDevInfoData != NULL);
  334. //
  335. // Enumerate all display adapter interfaces
  336. //
  337. hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE,
  338. NULL,
  339. NULL,
  340. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  341. if (hDevInfo == INVALID_HANDLE_VALUE) {
  342. goto Cleanup;
  343. }
  344. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  345. while (SetupDiEnumDeviceInterfaces(hDevInfo,
  346. NULL,
  347. &GUID_DISPLAY_ADAPTER_INTERFACE,
  348. InterfaceIndex,
  349. &InterfaceData)) {
  350. //
  351. // Get the required size for the interface
  352. //
  353. InterfaceSize = 0;
  354. SetupDiGetDeviceInterfaceDetail(hDevInfo,
  355. &InterfaceData,
  356. NULL,
  357. 0,
  358. &InterfaceSize,
  359. NULL);
  360. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  361. goto Cleanup;
  362. }
  363. //
  364. // Alloc memory for the interface
  365. //
  366. pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
  367. LocalAlloc(LPTR, InterfaceSize);
  368. if (pInterfaceDetailData == NULL)
  369. goto Cleanup;
  370. //
  371. // Get the interface
  372. //
  373. pInterfaceDetailData->cbSize =
  374. sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  375. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  376. if (SetupDiGetDeviceInterfaceDetail(hDevInfo,
  377. &InterfaceData,
  378. pInterfaceDetailData,
  379. InterfaceSize,
  380. &InterfaceSize,
  381. &DevInfoData)) {
  382. //
  383. // Is the InterfaceName the same as the DevicePath?
  384. //
  385. #ifdef UNICODE
  386. pwDevicePath = pInterfaceDetailData->DevicePath;
  387. #else
  388. {
  389. SIZE_T cch = strlen(pInterfaceDetailData->DevicePath) + 1;
  390. pwDevicePath = LocalAlloc(LPTR, cch * sizeof(WCHAR));
  391. if (pwDevicePath == NULL) {
  392. goto Cleanup;
  393. }
  394. MultiByteToWideChar(CP_ACP, 0,
  395. pInterfaceDetailData->DevicePath,
  396. -1, pwDevicePath, cch);
  397. }
  398. #endif
  399. //
  400. // The first 4 characters of the interface name are different
  401. // between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
  402. // Therefore, ignore them.
  403. //
  404. bMatch = (_wcsnicmp(pwInterfaceName + 4,
  405. pwDevicePath + 4,
  406. wcslen(pwInterfaceName + 4)) == 0);
  407. #ifndef UNICODE
  408. LocalFree(pwDevicePath);
  409. pwDevicePath = NULL;
  410. #endif
  411. if (bMatch) {
  412. //
  413. // We found the device
  414. //
  415. *phDevInfo = hDevInfo;
  416. CopyMemory(pDevInfoData, &DevInfoData, sizeof(SP_DEVINFO_DATA));
  417. break;
  418. }
  419. }
  420. //
  421. // Clean-up
  422. //
  423. LocalFree(pInterfaceDetailData);
  424. pInterfaceDetailData = NULL;
  425. //
  426. // Next interface ...
  427. //
  428. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  429. ++InterfaceIndex;
  430. }
  431. Cleanup:
  432. if (pInterfaceDetailData != NULL) {
  433. LocalFree(pInterfaceDetailData);
  434. }
  435. //
  436. // Upon success, the caller is responsible to destroy the list
  437. //
  438. if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE)) {
  439. SetupDiDestroyDeviceInfoList(hDevInfo);
  440. }
  441. return bMatch;
  442. }
  443. HKEY
  444. CRegistrySettings::OpenDrvRegKey()
  445. {
  446. HKEY hkDriver = (HKEY)INVALID_HANDLE_VALUE;
  447. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  448. SP_DEVINFO_DATA did;
  449. DWORD index = 0;
  450. if (_dwDevInst == 0) {
  451. goto Fallout;
  452. }
  453. hDevInfo = SetupDiGetClassDevs((LPGUID) &GUID_DEVCLASS_DISPLAY,
  454. NULL,
  455. NULL,
  456. 0);
  457. if (hDevInfo == INVALID_HANDLE_VALUE) {
  458. goto Fallout;
  459. }
  460. ZeroMemory(&did, sizeof(SP_DEVINFO_DATA));
  461. did.cbSize = sizeof(SP_DEVINFO_DATA);
  462. while (SetupDiEnumDeviceInfo(hDevInfo, index, &did)) {
  463. if (did.DevInst == _dwDevInst) {
  464. hkDriver = SetupDiOpenDevRegKey(hDevInfo,
  465. &did,
  466. DICS_FLAG_GLOBAL,
  467. 0,
  468. DIREG_DRV ,
  469. KEY_ALL_ACCESS);
  470. break;
  471. }
  472. did.cbSize = sizeof(SP_DEVINFO_DATA);
  473. index++;
  474. }
  475. Fallout:
  476. if (hDevInfo != INVALID_HANDLE_VALUE) {
  477. SetupDiDestroyDeviceInfoList(hDevInfo);
  478. }
  479. return hkDriver;
  480. }