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.

614 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. StringCchCopy(szBuffer, ARRAYSIZE(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. StringCchCat(pszPath, ARRAYSIZE(szBuffer) - (pszEnd - szBuffer), 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. DWORD cchKeyName = (lstrlen(szBuffer) + 1);
  85. _pszKeyName = (LPTSTR)LocalAlloc(LPTR, cchKeyName * sizeof(TCHAR));
  86. if (_pszKeyName != NULL) {
  87. StringCchCopy(_pszKeyName, cchKeyName, szBuffer);
  88. StringCchPrintf(szBuffer, ARRAYSIZE(szBuffer), TEXT("%s%s"), SZ_SERVICES_PATH, _pszKeyName);
  89. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  90. szBuffer,
  91. 0,
  92. KEY_READ,
  93. &hkeyDriver) == ERROR_SUCCESS) {
  94. cb = sizeof(szBuffer);
  95. ZeroMemory(szBuffer, cb);
  96. if (RegQueryValueEx(hkeyDriver,
  97. L"ImagePath",
  98. NULL,
  99. NULL,
  100. (LPBYTE)szBuffer,
  101. &cb) == ERROR_SUCCESS) {
  102. //
  103. // This is a binary.
  104. // Extract the name, which will be of the form ...\driver.sys
  105. //
  106. LPTSTR pszDriver, pszDriverEnd;
  107. pszDriver = szBuffer;
  108. pszDriverEnd = pszDriver + lstrlen(pszDriver);
  109. while(pszDriverEnd != pszDriver &&
  110. *pszDriverEnd != TEXT('.')) {
  111. pszDriverEnd--;
  112. }
  113. *pszDriverEnd = UNICODE_NULL;
  114. while(pszDriverEnd != pszDriver &&
  115. *pszDriverEnd != TEXT('\\')) {
  116. pszDriverEnd--;
  117. }
  118. //
  119. // If pszDriver and pszDriverEnd are different, we now
  120. // have the driver name.
  121. //
  122. if (pszDriverEnd > pszDriver) {
  123. pszDriverEnd++;
  124. pszName = pszDriverEnd;
  125. }
  126. }
  127. RegCloseKey(hkeyDriver);
  128. }
  129. if (!pszName) {
  130. //
  131. // Something failed trying to get the binary name.just get the device name
  132. //
  133. _pszDrvName = _pszKeyName;
  134. } else {
  135. DWORD cchDrvName = lstrlen(pszName) + 1;
  136. _pszDrvName = (LPTSTR)LocalAlloc(LPTR, cchDrvName * sizeof(TCHAR));
  137. if (_pszDrvName != NULL) {
  138. StringCchCopy(_pszDrvName, cchDrvName, pszName);
  139. }
  140. }
  141. }
  142. }
  143. RegCloseKey(hkeyCommon);
  144. }
  145. }
  146. //
  147. // CRegistrySettings destructor
  148. //
  149. CRegistrySettings::~CRegistrySettings()
  150. {
  151. //
  152. // Close the registry
  153. //
  154. if (_hkVideoReg) {
  155. RegCloseKey(_hkVideoReg);
  156. }
  157. //
  158. // Free the strings
  159. //
  160. if (_pszKeyName) {
  161. LocalFree(_pszKeyName);
  162. }
  163. if ((_pszKeyName != _pszDrvName) && _pszDrvName) {
  164. LocalFree(_pszDrvName);
  165. }
  166. if(_pszDeviceInstanceId) {
  167. LocalFree(_pszDeviceInstanceId);
  168. }
  169. }
  170. //
  171. // Method to get the hardware information fields.
  172. //
  173. VOID
  174. CRegistrySettings::GetHardwareInformation(
  175. PDISPLAY_REGISTRY_HARDWARE_INFO pInfo)
  176. {
  177. DWORD cb, dwType;
  178. DWORD i;
  179. LONG lRet;
  180. LPWSTR pKeyNames[5] = {
  181. L"HardwareInformation.MemorySize",
  182. L"HardwareInformation.ChipType",
  183. L"HardwareInformation.DacType",
  184. L"HardwareInformation.AdapterString",
  185. L"HardwareInformation.BiosString"
  186. };
  187. ZeroMemory(pInfo, sizeof(*pInfo));
  188. //
  189. // Query each entry one after the other.
  190. //
  191. for (i = 0; i < 5; i++) {
  192. //
  193. // query the size of the string
  194. //
  195. cb = sizeof(pInfo->MemSize);
  196. lRet = RegQueryValueExW(_hkVideoReg,
  197. pKeyNames[i],
  198. NULL,
  199. &dwType,
  200. NULL,
  201. &cb);
  202. if (lRet == ERROR_SUCCESS) {
  203. if (i == 0) {
  204. ULONG mem;
  205. cb = sizeof(mem);
  206. if (RegQueryValueExW(_hkVideoReg,
  207. pKeyNames[i],
  208. NULL,
  209. &dwType,
  210. (PUCHAR) (&mem),
  211. &cb) == ERROR_SUCCESS)
  212. {
  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. StringCchPrintf((LPWSTR)pInfo, ARRAYSIZE(pInfo->MemSize), L"%d KB", mem );
  222. } else {
  223. StringCchPrintf((LPWSTR)pInfo, ARRAYSIZE(pInfo->MemSize), L"%d MB", mem >> 10 );
  224. }
  225. }
  226. else
  227. {
  228. goto Default;
  229. }
  230. } else {
  231. cb = sizeof(pInfo->MemSize);
  232. //
  233. // get the string
  234. //
  235. if (RegQueryValueExW(_hkVideoReg,
  236. pKeyNames[i],
  237. NULL,
  238. &dwType,
  239. (LPBYTE) pInfo,
  240. &cb) != ERROR_SUCCESS)
  241. {
  242. goto Default;
  243. }
  244. }
  245. }
  246. else
  247. {
  248. //
  249. // Put in the default string
  250. //
  251. Default:
  252. LoadString(HINST_THISDLL,
  253. IDS_UNAVAILABLE,
  254. (LPWSTR)pInfo,
  255. ARRAYSIZE(pInfo->MemSize));
  256. }
  257. pInfo = (PDISPLAY_REGISTRY_HARDWARE_INFO)((PUCHAR)pInfo + sizeof(pInfo->MemSize));
  258. }
  259. }
  260. VOID CRegistrySettings::InitDeviceInstanceID(
  261. LPTSTR pstrDeviceKey
  262. )
  263. {
  264. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE ;
  265. SP_DEVINFO_DATA DevInfoData;
  266. ULONG InstanceIDSize = 0;
  267. BOOL bSuccess = FALSE;
  268. LPWSTR pwInterfaceName = NULL;
  269. LPWSTR pwInstanceID = NULL;
  270. ASSERT (pstrDeviceKey != NULL);
  271. ASSERT (_pszDeviceInstanceId == NULL);
  272. if (AllocAndReadInterfaceName(pstrDeviceKey, &pwInterfaceName)) {
  273. bSuccess = GetDevInfoDataFromInterfaceName(pwInterfaceName,
  274. &hDevInfo,
  275. &DevInfoData);
  276. if (bSuccess) {
  277. InstanceIDSize = 0;
  278. bSuccess =
  279. ((CM_Get_Device_ID_Size(&InstanceIDSize,
  280. DevInfoData.DevInst,
  281. 0) == CR_SUCCESS) &&
  282. ((_pszDeviceInstanceId = (LPTSTR)LocalAlloc(LPTR,
  283. (InstanceIDSize + 1) * sizeof(TCHAR))) != NULL) &&
  284. (CM_Get_Device_ID(DevInfoData.DevInst,
  285. _pszDeviceInstanceId,
  286. InstanceIDSize,
  287. 0) == CR_SUCCESS));
  288. if (bSuccess) {
  289. _dwDevInst = DevInfoData.DevInst;
  290. } else {
  291. //
  292. // Clean-up
  293. //
  294. if (NULL != _pszDeviceInstanceId) {
  295. LocalFree(_pszDeviceInstanceId);
  296. _pszDeviceInstanceId = NULL;
  297. }
  298. }
  299. SetupDiDestroyDeviceInfoList(hDevInfo);
  300. }
  301. LocalFree(pwInterfaceName);
  302. }
  303. if ((!bSuccess) &&
  304. AllocAndReadInstanceID(pstrDeviceKey, &pwInstanceID)) {
  305. _pszDeviceInstanceId = pwInstanceID;
  306. }
  307. } // InitDeviceInstanceID
  308. BOOL
  309. CRegistrySettings::GetDevInfoDataFromInterfaceName(
  310. IN LPWSTR pwInterfaceName,
  311. OUT HDEVINFO* phDevInfo,
  312. OUT PSP_DEVINFO_DATA pDevInfoData
  313. )
  314. /*
  315. Note: If this function retuns success, the caller is responsible
  316. to destroy the device info list returned in phDevInfo
  317. */
  318. {
  319. LPWSTR pwDevicePath = NULL;
  320. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  321. SP_DEVINFO_DATA DevInfoData;
  322. SP_DEVICE_INTERFACE_DATA InterfaceData;
  323. PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
  324. DWORD InterfaceIndex = 0;
  325. DWORD InterfaceSize = 0;
  326. BOOL bMatch = FALSE;
  327. ASSERT (pwInterfaceName != NULL);
  328. ASSERT (phDevInfo != NULL);
  329. ASSERT (pDevInfoData != NULL);
  330. //
  331. // Enumerate all display adapter interfaces
  332. //
  333. hDevInfo = SetupDiGetClassDevs(&GUID_DISPLAY_ADAPTER_INTERFACE,
  334. NULL,
  335. NULL,
  336. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  337. if (hDevInfo == INVALID_HANDLE_VALUE) {
  338. goto Cleanup;
  339. }
  340. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  341. while (SetupDiEnumDeviceInterfaces(hDevInfo,
  342. NULL,
  343. &GUID_DISPLAY_ADAPTER_INTERFACE,
  344. InterfaceIndex,
  345. &InterfaceData)) {
  346. //
  347. // Get the required size for the interface
  348. //
  349. InterfaceSize = 0;
  350. SetupDiGetDeviceInterfaceDetail(hDevInfo,
  351. &InterfaceData,
  352. NULL,
  353. 0,
  354. &InterfaceSize,
  355. NULL);
  356. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  357. goto Cleanup;
  358. }
  359. //
  360. // Alloc memory for the interface
  361. //
  362. pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
  363. LocalAlloc(LPTR, InterfaceSize);
  364. if (pInterfaceDetailData == NULL)
  365. goto Cleanup;
  366. //
  367. // Get the interface
  368. //
  369. pInterfaceDetailData->cbSize =
  370. sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  371. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  372. if (SetupDiGetDeviceInterfaceDetail(hDevInfo,
  373. &InterfaceData,
  374. pInterfaceDetailData,
  375. InterfaceSize,
  376. &InterfaceSize,
  377. &DevInfoData)) {
  378. //
  379. // Is the InterfaceName the same as the DevicePath?
  380. //
  381. pwDevicePath = pInterfaceDetailData->DevicePath;
  382. //
  383. // The first 4 characters of the interface name are different
  384. // between user mode and kernel mode (e.g. "\\?\" vs "\\.\")
  385. // Therefore, ignore them.
  386. //
  387. bMatch = (_wcsnicmp(pwInterfaceName + 4,
  388. pwDevicePath + 4,
  389. wcslen(pwInterfaceName + 4)) == 0);
  390. if (bMatch) {
  391. //
  392. // We found the device
  393. //
  394. *phDevInfo = hDevInfo;
  395. CopyMemory(pDevInfoData, &DevInfoData, sizeof(*pDevInfoData));
  396. break;
  397. }
  398. }
  399. //
  400. // Clean-up
  401. //
  402. LocalFree(pInterfaceDetailData);
  403. pInterfaceDetailData = NULL;
  404. //
  405. // Next interface ...
  406. //
  407. InterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  408. ++InterfaceIndex;
  409. }
  410. Cleanup:
  411. if (pInterfaceDetailData != NULL) {
  412. LocalFree(pInterfaceDetailData);
  413. }
  414. //
  415. // Upon success, the caller is responsible to destroy the list
  416. //
  417. if (!bMatch && (hDevInfo != INVALID_HANDLE_VALUE)) {
  418. SetupDiDestroyDeviceInfoList(hDevInfo);
  419. }
  420. return bMatch;
  421. }
  422. HKEY
  423. CRegistrySettings::OpenDrvRegKey()
  424. {
  425. HKEY hkDriver = (HKEY)INVALID_HANDLE_VALUE;
  426. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  427. SP_DEVINFO_DATA did;
  428. DWORD index = 0;
  429. if (_dwDevInst == 0) {
  430. goto Fallout;
  431. }
  432. hDevInfo = SetupDiGetClassDevs((LPGUID) &GUID_DEVCLASS_DISPLAY,
  433. NULL,
  434. NULL,
  435. 0);
  436. if (hDevInfo == INVALID_HANDLE_VALUE) {
  437. goto Fallout;
  438. }
  439. ZeroMemory(&did, sizeof(did));
  440. did.cbSize = sizeof(did);
  441. while (SetupDiEnumDeviceInfo(hDevInfo, index, &did)) {
  442. if (did.DevInst == _dwDevInst) {
  443. hkDriver = SetupDiOpenDevRegKey(hDevInfo,
  444. &did,
  445. DICS_FLAG_GLOBAL,
  446. 0,
  447. DIREG_DRV ,
  448. KEY_READ);
  449. break;
  450. }
  451. did.cbSize = sizeof(SP_DEVINFO_DATA);
  452. index++;
  453. }
  454. Fallout:
  455. if (hDevInfo != INVALID_HANDLE_VALUE) {
  456. SetupDiDestroyDeviceInfoList(hDevInfo);
  457. }
  458. return hkDriver;
  459. }