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.

644 lines
21 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. infoset.h
  5. Abstract:
  6. Handles setup API device infosets
  7. Author:
  8. Vlad Sadovsky (vlads) 10-Jan-1999
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 6-Jan-1999 VladS created
  13. --*/
  14. #ifndef _INFOSET_H_
  15. #define _INFOSET_H_
  16. #include <base.h>
  17. #include <buffer.h>
  18. #include <dbt.h>
  19. #include <setupapi.h>
  20. class DEVICE_INFOSET {
  21. public:
  22. DEVICE_INFOSET(IN GUID guidClass)
  23. {
  24. m_DeviceInfoSet = NULL;
  25. m_ClassGuid = guidClass;
  26. Initialize();
  27. m_fValid = TRUE;
  28. }
  29. ~DEVICE_INFOSET( VOID )
  30. {
  31. Reset();
  32. }
  33. inline BOOL
  34. IsValid(
  35. VOID
  36. )
  37. {
  38. return(m_fValid);
  39. }
  40. inline void
  41. EnterCrit(VOID)
  42. {
  43. m_dwCritSec.Lock();
  44. }
  45. inline void
  46. LeaveCrit(VOID)
  47. {
  48. m_dwCritSec.Unlock();
  49. }
  50. inline
  51. HDEVINFO
  52. QueryInfoSetHandle(VOID)
  53. {
  54. return(m_DeviceInfoSet);
  55. }
  56. //
  57. // Initialize info set for given class
  58. //
  59. BOOL
  60. Initialize(VOID)
  61. {
  62. HDEVINFO NewDeviceInfoSet;
  63. DWORD dwErr;
  64. m_DeviceInfoSet = SetupDiCreateDeviceInfoList(NULL, NULL);
  65. Refresh();
  66. #ifdef DEBUG
  67. Dump();
  68. #endif
  69. return (TRUE);
  70. }
  71. BOOL
  72. Refresh(VOID)
  73. {
  74. HDEVINFO NewDeviceInfoSet;
  75. DWORD dwErr;
  76. if ( m_DeviceInfoSet && (m_DeviceInfoSet != INVALID_HANDLE_VALUE)) {
  77. #ifdef WINNT
  78. //
  79. // Now we can retrieve the existing list of active device
  80. // interfaces into the device information set we created above.
  81. //
  82. NewDeviceInfoSet = SetupDiGetClassDevsEx(&(m_ClassGuid),
  83. NULL,
  84. NULL,
  85. // DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
  86. DIGCF_DEVICEINTERFACE,
  87. m_DeviceInfoSet,
  88. NULL,
  89. NULL
  90. );
  91. NewDeviceInfoSet = SetupDiGetClassDevsEx(&(m_ClassGuid),
  92. NULL,
  93. NULL,
  94. // DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
  95. 0,
  96. NewDeviceInfoSet,
  97. NULL,
  98. NULL
  99. );
  100. if (NewDeviceInfoSet == INVALID_HANDLE_VALUE) {
  101. dwErr = ::GetLastError();
  102. DBG_ERR(("SetupDiGetClassDevsEx failed with 0x%lx\n", dwErr));
  103. return (FALSE);
  104. }
  105. #else
  106. //
  107. // BUGBUG
  108. //
  109. #pragma message("Rewrite for Win98")
  110. return (FALSE);
  111. #endif
  112. //
  113. // If SetupDiGetClassDevsEx succeeds and it was passed in an
  114. // existing device information set to be used, then the HDEVINFO
  115. // it returns is the same as the one it was passed in. Thus, we
  116. // can just use the original DeviceInfoSet handle from here on.
  117. //
  118. }
  119. return (TRUE);
  120. }
  121. //
  122. //
  123. //
  124. BOOL
  125. Reset(VOID)
  126. {
  127. SetupDiDestroyDeviceInfoList(m_DeviceInfoSet);
  128. return (TRUE);
  129. }
  130. //
  131. // Look up driver name by interface name
  132. //
  133. BOOL
  134. LookupDriverNameFromInterfaceName(
  135. LPCTSTR pszInterfaceName,
  136. StiCString* pstrDriverName
  137. )
  138. {
  139. BUFFER bufDetailData;
  140. SP_DEVINFO_DATA spDevInfoData;
  141. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  142. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  143. TCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
  144. DWORD cbData;
  145. DWORD dwErr;
  146. HKEY hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  147. LONG lResult = ERROR_SUCCESS;
  148. DWORD dwType = REG_SZ;
  149. BOOL fRet = FALSE;
  150. BOOL fDataAcquired = FALSE;
  151. bufDetailData.Resize(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  152. MAX_PATH * sizeof(TCHAR) +
  153. 16
  154. );
  155. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr();
  156. if (!pspDevInterfaceDetailData) {
  157. return (CR_OUT_OF_MEMORY);
  158. }
  159. //
  160. // Locate this device interface in our device information set.
  161. //
  162. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  163. if (SetupDiOpenDeviceInterface(m_DeviceInfoSet,
  164. pszInterfaceName,
  165. DIODI_NO_ADD,
  166. &spDevInterfaceData)) {
  167. //
  168. // First try to open interface regkey.
  169. //
  170. hkDevice = SetupDiOpenDeviceInterfaceRegKey(m_DeviceInfoSet,
  171. &spDevInterfaceData,
  172. 0,
  173. KEY_READ);
  174. if(INVALID_HANDLE_VALUE != hkDevice){
  175. *szDevDriver = TEXT('\0');
  176. cbData = sizeof(szDevDriver);
  177. lResult = RegQueryValueEx(hkDevice,
  178. REGSTR_VAL_DEVICE_ID,
  179. NULL,
  180. &dwType,
  181. (LPBYTE)szDevDriver,
  182. &cbData);
  183. dwErr = ::GetLastError();
  184. RegCloseKey(hkDevice);
  185. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  186. if(ERROR_SUCCESS == lResult){
  187. fDataAcquired = TRUE;
  188. } // if(ERROR_SUCCESS == lResult)
  189. } // if(INVALID_HANDLE_VALUE != hkDevice)
  190. if(!fDataAcquired){
  191. //
  192. // Try to open devnode regkey.
  193. //
  194. cbData = 0;
  195. pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  196. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  197. fRet = SetupDiGetDeviceInterfaceDetail(m_DeviceInfoSet,
  198. &spDevInterfaceData,
  199. pspDevInterfaceDetailData,
  200. bufDetailData.QuerySize(),
  201. &cbData,
  202. &spDevInfoData);
  203. if(fRet){
  204. //
  205. // Get device interface registry key.
  206. //
  207. hkDevice = SetupDiOpenDevRegKey(m_DeviceInfoSet,
  208. &spDevInfoData,
  209. DICS_FLAG_GLOBAL,
  210. 0,
  211. DIREG_DRV,
  212. KEY_READ);
  213. dwErr = ::GetLastError();
  214. } else {
  215. DBG_ERR(("SetupDiGetDeviceInterfaceDetail() Failed Err=0x%x",GetLastError()));
  216. }
  217. if (INVALID_HANDLE_VALUE != hkDevice) {
  218. *szDevDriver = TEXT('\0');
  219. cbData = sizeof(szDevDriver);
  220. lResult = RegQueryValueEx(hkDevice,
  221. REGSTR_VAL_DEVICE_ID,
  222. NULL,
  223. &dwType,
  224. (LPBYTE)szDevDriver,
  225. &cbData);
  226. dwErr = ::GetLastError();
  227. RegCloseKey(hkDevice);
  228. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  229. if(ERROR_SUCCESS == lResult){
  230. fDataAcquired = TRUE;
  231. } // if(ERROR_SUCCESS == lResult)
  232. } else { // if (INVALID_HANDLE_VALUE != hkDevice)
  233. DBG_ERR(("SetupDiOpenDevRegKey() Failed Err=0x%x",GetLastError()));
  234. fRet = FALSE;
  235. } // if (INVALID_HANDLE_VALUE != hkDevice)
  236. } // if(!fDataAcquired)
  237. if (fDataAcquired) {
  238. // Got it
  239. pstrDriverName->CopyString(szDevDriver);
  240. fRet = TRUE;
  241. } // if (fDataAcquired)
  242. } else {
  243. DBG_ERR(("SetupDiOpenDeviceInterface() Failed Err=0x%x",GetLastError()));
  244. fRet = FALSE;
  245. }
  246. return (fRet);
  247. }
  248. //
  249. // Look up device info data by driver name
  250. //
  251. BOOL
  252. LookupDeviceInfoFromDriverName(
  253. LPCTSTR pszDriverName,
  254. StiCString* pstrInterfaceName,
  255. DEVINST*pDeviceInstance = NULL
  256. )
  257. {
  258. SP_DEVINFO_DATA spDevInfoData;
  259. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  260. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  261. BUFFER bufDetailData;
  262. TCHAR szDevDriver[STI_MAX_INTERNAL_NAME_LENGTH];
  263. ULONG cbData;
  264. CONFIGRET cmRet = CR_NO_SUCH_DEVINST;
  265. DWORD dwRequired;
  266. DWORD Idx;
  267. DWORD dwError;
  268. DWORD dwType;
  269. BOOL fRet = FALSE;
  270. BOOL fFoundMatch = FALSE;
  271. LONG lResult = ERROR_SUCCESS;
  272. HKEY hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  273. Refresh();
  274. dwRequired = 0;
  275. ZeroMemory(&spDevInterfaceData,sizeof(spDevInterfaceData));
  276. bufDetailData.Resize(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) +
  277. MAX_PATH * sizeof(TCHAR) +
  278. 16
  279. );
  280. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr();
  281. if (!pspDevInterfaceDetailData) {
  282. ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  283. return (FALSE);
  284. }
  285. if (m_DeviceInfoSet != INVALID_HANDLE_VALUE) {
  286. ZeroMemory(&spDevInfoData,sizeof(spDevInfoData));
  287. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  288. spDevInfoData.ClassGuid = m_ClassGuid;
  289. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) bufDetailData.QueryPtr();
  290. for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++) {
  291. //
  292. // Get driver name property
  293. //
  294. hkDevice = SetupDiOpenDevRegKey(m_DeviceInfoSet,
  295. &spDevInfoData,
  296. DICS_FLAG_GLOBAL,
  297. 0,
  298. DIREG_DRV,
  299. KEY_READ);
  300. if(INVALID_HANDLE_VALUE != hkDevice){
  301. *szDevDriver = TEXT('\0');
  302. cbData = sizeof(szDevDriver);
  303. lResult = RegQueryValueEx(hkDevice,
  304. REGSTR_VAL_DEVICE_ID,
  305. NULL,
  306. &dwType,
  307. (LPBYTE)szDevDriver,
  308. &cbData);
  309. RegCloseKey(hkDevice);
  310. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  311. if(ERROR_SUCCESS == lResult){
  312. if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) {
  313. //
  314. // Get interface.
  315. //
  316. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  317. spDevInterfaceData.InterfaceClassGuid = m_ClassGuid;
  318. fRet = SetupDiEnumDeviceInterfaces (m_DeviceInfoSet,
  319. &spDevInfoData,
  320. &(m_ClassGuid),
  321. 0,
  322. &spDevInterfaceData);
  323. if(!fRet){
  324. DBG_ERR(("SetupDiEnumDeviceInterfaces() Failed Err=0x%x",GetLastError()));
  325. fFoundMatch = FALSE;
  326. continue;
  327. }
  328. //
  329. // Found match ..
  330. //
  331. fFoundMatch = TRUE;
  332. break;
  333. } // if (lstrcmpi(pszDriverName,szDevDriver) == 0 )
  334. } //if(ERROR_SUCCESS == lResult)
  335. } // if(INVALID_HANDLE_VALUE != hkDevice)
  336. } // for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++)
  337. if(!fFoundMatch){
  338. //
  339. // Try to get interface regkey.
  340. //
  341. spDevInterfaceData.InterfaceClassGuid = m_ClassGuid;
  342. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  343. for(Idx = 0; SetupDiEnumDeviceInterfaces (m_DeviceInfoSet, NULL, &m_ClassGuid, Idx, &spDevInterfaceData); Idx++) {
  344. hkDevice = SetupDiOpenDeviceInterfaceRegKey(m_DeviceInfoSet,
  345. &spDevInterfaceData,
  346. 0,
  347. KEY_READ);
  348. if(INVALID_HANDLE_VALUE != hkDevice){
  349. *szDevDriver = TEXT('\0');
  350. cbData = sizeof(szDevDriver);
  351. lResult = RegQueryValueEx(hkDevice,
  352. REGSTR_VAL_DEVICE_ID,
  353. NULL,
  354. &dwType,
  355. (LPBYTE)szDevDriver,
  356. &cbData);
  357. RegCloseKey(hkDevice);
  358. hkDevice = (HKEY)INVALID_HANDLE_VALUE;
  359. if(ERROR_SUCCESS == lResult){
  360. if (lstrcmpi(pszDriverName,szDevDriver) == 0 ) {
  361. //
  362. // Found match ..
  363. //
  364. fFoundMatch = TRUE;
  365. break;
  366. } // if (lstrcmpi(pszDriverName,szDevDriver) == 0 )
  367. } //if(ERROR_SUCCESS == lResult)
  368. } // if(INVALID_HANDLE_VALUE != hkDevice)
  369. } // for(Idx = 0; SetupDiEnumDeviceInterfaces (m_DeviceInfoSet, NULL, &m_ClassGuid, Idx, &spDevInterfaceData); Idx++)
  370. } // if(!fFoundMatch)
  371. if (fFoundMatch) {
  372. dwRequired = 0;
  373. pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  374. fRet = SetupDiGetDeviceInterfaceDetail(m_DeviceInfoSet,
  375. &spDevInterfaceData,
  376. pspDevInterfaceDetailData,
  377. bufDetailData.QuerySize(),
  378. &dwRequired,
  379. &spDevInfoData);
  380. dwError = ::GetLastError();
  381. if (fRet) {
  382. pstrInterfaceName -> CopyString(pspDevInterfaceDetailData->DevicePath);
  383. fRet = TRUE;
  384. } else {
  385. // DPRINTF failed to get interface detail
  386. }
  387. } // if (fFoundMatch)
  388. } else {
  389. // DPRINTF - invalid dev info set handle
  390. }
  391. return (fRet);
  392. }
  393. //
  394. // Process refresh message
  395. //
  396. BOOL
  397. ProcessNewDeviceChangeMessage(
  398. IN LPARAM lParam
  399. )
  400. {
  401. DWORD dwErr;
  402. PDEV_BROADCAST_DEVICEINTERFACE pDevBroadcastDeviceInterface;
  403. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  404. pDevBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
  405. //
  406. // Open this new device interface into our device information
  407. // set.
  408. //
  409. if (!SetupDiOpenDeviceInterface(m_DeviceInfoSet,
  410. pDevBroadcastDeviceInterface->dbcc_name,
  411. 0,
  412. NULL)) {
  413. dwErr = GetLastError();
  414. }
  415. #ifdef DEBUG
  416. Dump();
  417. #endif
  418. return (TRUE);
  419. }
  420. BOOL
  421. ProcessDeleteDeviceChangeMessage(
  422. IN LPARAM lParam
  423. )
  424. {
  425. DBG_FN(ProcessDeleteDeviceChangeMessage);
  426. DWORD dwErr;
  427. PDEV_BROADCAST_DEVICEINTERFACE pDevBroadcastDeviceInterface;
  428. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  429. pDevBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
  430. //
  431. // First, locate this device interface in our device information
  432. // set.
  433. //
  434. spDevInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  435. if (SetupDiOpenDeviceInterface(m_DeviceInfoSet,
  436. pDevBroadcastDeviceInterface->dbcc_name,
  437. DIODI_NO_ADD,
  438. &spDevInterfaceData)) {
  439. if (!SetupDiDeleteDeviceInterfaceData(m_DeviceInfoSet,
  440. &spDevInterfaceData)) {
  441. dwErr = GetLastError();
  442. }
  443. }
  444. // Do we need to do refresh now ? BUGBUG
  445. Refresh();
  446. #ifdef DEBUG
  447. Dump();
  448. #endif
  449. return (TRUE);
  450. }
  451. VOID
  452. Dump(VOID)
  453. {
  454. SP_DEVINFO_DATA spDevInfoData;
  455. UINT Idx;
  456. ZeroMemory(&spDevInfoData,sizeof(spDevInfoData));
  457. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  458. spDevInfoData.ClassGuid = m_ClassGuid;
  459. for (Idx = 0; SetupDiEnumDeviceInfo (m_DeviceInfoSet, Idx, &spDevInfoData); Idx++) {
  460. Idx = Idx;
  461. }
  462. }
  463. //
  464. DWORD m_dwSignature;
  465. private:
  466. BOOL m_fValid;
  467. CRIT_SECT m_dwCritSec;
  468. DWORD m_dwFlags;
  469. GUID m_ClassGuid;
  470. HDEVINFO m_DeviceInfoSet;
  471. };
  472. //
  473. // Take device class
  474. //
  475. class TAKE_DEVICE_INFOSET {
  476. private:
  477. DEVICE_INFOSET* m_pInfoSet;
  478. public:
  479. inline TAKE_DEVICE_INFOSET(DEVICE_INFOSET* pInfoSet) : m_pInfoSet(pInfoSet)
  480. {
  481. m_pInfoSet->EnterCrit();
  482. }
  483. inline ~TAKE_DEVICE_INFOSET()
  484. {
  485. m_pInfoSet->LeaveCrit();
  486. }
  487. };
  488. #endif // _INFOSET_H_