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.

593 lines
15 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 "precomp.h"
  13. #include <tchar.h>
  14. #include "ntreg.hxx"
  15. #include <devguid.h>
  16. #ifdef WINNT
  17. //
  18. // CRegistrySettings constructor
  19. //
  20. CRegistrySettings::CRegistrySettings(LPTSTR pstrDeviceKey)
  21. : _hkVideoReg(NULL)
  22. , _pszDrvName(NULL)
  23. , _pszKeyName(NULL)
  24. , _pszDeviceInstanceId(NULL)
  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(hInstance,
  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. //
  282. // Clean-up
  283. //
  284. if (NULL != _pszDeviceInstanceId) {
  285. LocalFree(_pszDeviceInstanceId);
  286. _pszDeviceInstanceId = NULL;
  287. }
  288. }
  289. SetupDiDestroyDeviceInfoList(hDevInfo);
  290. }
  291. LocalFree(pwInterfaceName);
  292. }
  293. if ((!bSuccess) &&
  294. AllocAndReadInstanceID(pstrDeviceKey, &pwInstanceID)) {
  295. #ifdef UNICODE
  296. _pszDeviceInstanceId = pwInstanceID;
  297. #else
  298. SIZE_T cch = wcslen(pwInstanceID) + 1;
  299. _pszDeviceInstanceId = LocalAlloc(LPTR, cch);
  300. if (_pszDeviceInstanceId != NULL) {
  301. WideCharToMultiByte(CP_ACP, 0,
  302. pwInstanceID, -1,
  303. _pszDeviceInstanceId,
  304. cch, NULL, NULL);
  305. }
  306. LocalFree(pwInstanceID);
  307. #endif
  308. }
  309. } // InitDeviceInstanceID
  310. BOOL
  311. CRegistrySettings::GetDevInfoDataFromInterfaceName(
  312. IN LPWSTR pwInterfaceName,
  313. OUT HDEVINFO* phDevInfo,
  314. OUT PSP_DEVINFO_DATA pDevInfoData
  315. )
  316. /*
  317. Note: If this function retuns success, the caller is responsible
  318. to destroy the device info list returned in phDevInfo
  319. */
  320. {
  321. LPWSTR pwDevicePath = NULL;
  322. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  323. SP_DEVINFO_DATA DevInfoData;
  324. SP_DEVICE_INTERFACE_DATA InterfaceData;
  325. PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
  326. DWORD InterfaceIndex = 0;
  327. DWORD InterfaceSize = 0;
  328. BOOL bMatch = FALSE;
  329. ASSERT (pwInterfaceName != NULL);
  330. ASSERT (phDevInfo != NULL);
  331. ASSERT (pDevInfoData != NULL);
  332. //
  333. // Enumerate all display adapter interfaces
  334. //
  335. hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE,
  336. NULL,
  337. NULL,
  338. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  339. if (hDevInfo == INVALID_HANDLE_VALUE) {
  340. goto Cleanup;
  341. }
  342. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  343. while (SetupDiEnumDeviceInterfaces(hDevInfo,
  344. NULL,
  345. &GUID_DISPLAY_ADAPTER_INTERFACE,
  346. InterfaceIndex,
  347. &InterfaceData)) {
  348. //
  349. // Get the required size for the interface
  350. //
  351. InterfaceSize = 0;
  352. SetupDiGetDeviceInterfaceDetail(hDevInfo,
  353. &InterfaceData,
  354. NULL,
  355. 0,
  356. &InterfaceSize,
  357. NULL);
  358. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  359. goto Cleanup;
  360. }
  361. //
  362. // Alloc memory for the interface
  363. //
  364. pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
  365. LocalAlloc(LPTR, InterfaceSize);
  366. if (pInterfaceDetailData == NULL)
  367. goto Cleanup;
  368. //
  369. // Get the interface
  370. //
  371. pInterfaceDetailData->cbSize =
  372. sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  373. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  374. if (SetupDiGetDeviceInterfaceDetail(hDevInfo,
  375. &InterfaceData,
  376. pInterfaceDetailData,
  377. InterfaceSize,
  378. &InterfaceSize,
  379. &DevInfoData)) {
  380. //
  381. // Is the InterfaceName the same as the DevicePath?
  382. //
  383. #ifdef UNICODE
  384. pwDevicePath = pInterfaceDetailData->DevicePath;
  385. #else
  386. {
  387. SIZE_T cch = strlen(pInterfaceDetailData->DevicePath) + 1;
  388. pwDevicePath = LocalAlloc(LPTR, cch * sizeof(WCHAR));
  389. if (pwDevicePath == NULL) {
  390. goto Cleanup;
  391. }
  392. MultiByteToWideChar(CP_ACP, 0,
  393. pInterfaceDetailData->DevicePath,
  394. -1, pwDevicePath, cch);
  395. }
  396. #endif
  397. //
  398. // The first 4 characters of the interface name are different
  399. // between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
  400. // Therefore, ignore them.
  401. //
  402. bMatch = (_wcsnicmp(pwInterfaceName + 4,
  403. pwDevicePath + 4,
  404. wcslen(pwInterfaceName + 4)) == 0);
  405. #ifndef UNICODE
  406. LocalFree(pwDevicePath);
  407. pwDevicePath = NULL;
  408. #endif
  409. if (bMatch) {
  410. //
  411. // We found the device
  412. //
  413. *phDevInfo = hDevInfo;
  414. CopyMemory(pDevInfoData, &DevInfoData, sizeof(SP_DEVINFO_DATA));
  415. break;
  416. }
  417. }
  418. //
  419. // Clean-up
  420. //
  421. LocalFree(pInterfaceDetailData);
  422. pInterfaceDetailData = NULL;
  423. //
  424. // Next interface ...
  425. //
  426. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  427. ++InterfaceIndex;
  428. }
  429. Cleanup:
  430. if (pInterfaceDetailData != NULL) {
  431. LocalFree(pInterfaceDetailData);
  432. }
  433. //
  434. // Upon success, the caller is responsible to destroy the list
  435. //
  436. if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE)) {
  437. SetupDiDestroyDeviceInfoList(hDevInfo);
  438. }
  439. return bMatch;
  440. }
  441. #endif // WINNT