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.

873 lines
26 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. enum.cpp
  5. Abstract:
  6. Enumerates WIA device registry.
  7. Author:
  8. Keisuke Tsuchida (KeisukeT) 01-Jun-2000
  9. History:
  10. --*/
  11. //
  12. // Include Headers
  13. //
  14. #define INIT_GUID
  15. #include "cplusinc.h"
  16. #include "sticomm.h"
  17. #include <setupapi.h>
  18. #include <cfg.h>
  19. #include <cfgmgr32.h>
  20. #include <devguid.h>
  21. #include <initguid.h>
  22. #include <ntddpar.h>
  23. #include "enum.h"
  24. VOID
  25. DebugOutputDeviceName(
  26. HDEVINFO hDevInfo,
  27. PSP_DEVINFO_DATA pspDevInfoData,
  28. LPCTSTR szKeyName
  29. );
  30. VOID
  31. DebugOutputInterfaceName(
  32. HDEVINFO hDevInfo,
  33. PSP_DEVICE_INTERFACE_DATA pspDevInterfaceData,
  34. LPCTSTR szKeyName
  35. );
  36. BOOL
  37. IsStiRegKey(
  38. HKEY hkDevRegKey
  39. );
  40. //
  41. // Define
  42. //
  43. // from sti_ci.h
  44. #define WIA_DEVKEYLIST_INITIAL_SIZE 1024
  45. #define STILL_IMAGE TEXT("StillImage")
  46. #define SUBCLASS TEXT("SubClass")
  47. //
  48. // Functions
  49. //
  50. extern "C"{
  51. PWIA_DEVKEYLIST
  52. WiaCreateDeviceRegistryList(
  53. BOOL bEnumActiveOnly
  54. )
  55. {
  56. PWIA_DEVKEYLIST pReturn;
  57. PWIA_DEVKEYLIST pTempBuffer;
  58. HKEY hkDevRegKey;
  59. DWORD dwError;
  60. DWORD dwCurrentSize;
  61. DWORD dwRequiredSize;
  62. DWORD dwNumberOfDevices;
  63. DWORD dwFlags;
  64. DWORD dwValueSize;
  65. DWORD dwDetailDataSize;
  66. BOOL bIsPlugged;
  67. HANDLE hDevInfo;
  68. CONFIGRET ConfigRet;
  69. ULONG ulStatus;
  70. ULONG ulProblemNumber;
  71. DWORD Idx;
  72. GUID Guid;
  73. SP_DEVINFO_DATA spDevInfoData;
  74. SP_DEVICE_INTERFACE_DATA spDevInterfaceData;
  75. PSP_DEVICE_INTERFACE_DETAIL_DATA pspDevInterfaceDetailData;
  76. // DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: Enter... bEnumActiveOnly=%d"), bEnumActiveOnly);
  77. //
  78. // Initialize local.
  79. //
  80. pReturn = NULL;
  81. pTempBuffer = NULL;
  82. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  83. dwError = ERROR_SUCCESS;
  84. dwCurrentSize = WIA_DEVKEYLIST_INITIAL_SIZE;
  85. dwRequiredSize = sizeof(DWORD);
  86. dwNumberOfDevices = 0;
  87. dwFlags = (bEnumActiveOnly ? DIGCF_PRESENT : 0) | DIGCF_PROFILE;
  88. hDevInfo = INVALID_HANDLE_VALUE;
  89. Idx = 0;
  90. Guid = GUID_DEVCLASS_IMAGE;
  91. ConfigRet = CR_SUCCESS;
  92. ulStatus = 0;
  93. ulProblemNumber = 0;
  94. bIsPlugged = FALSE;
  95. pspDevInterfaceDetailData = NULL;
  96. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  97. memset(&spDevInterfaceData, 0, sizeof(spDevInterfaceData));
  98. //
  99. // Allocate buffer.
  100. //
  101. pTempBuffer = (PWIA_DEVKEYLIST)new BYTE[dwCurrentSize];
  102. if(NULL == pTempBuffer){
  103. DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: ERROR!! Insufficient system resources. Err=0x%x\n"), GetLastError());
  104. pReturn = NULL;
  105. goto WiaCreateDeviceRegistryList_return;
  106. } // if(NULL == pTempBuffer)
  107. memset(pTempBuffer, 0, dwCurrentSize);
  108. //
  109. // Enumerate "devnode" devices.
  110. //
  111. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, dwFlags);
  112. if (hDevInfo == INVALID_HANDLE_VALUE) {
  113. DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: ERROR!! SetupDiGetClassDevs (devnodes) fails. Err=0x%x\n"), GetLastError());
  114. pReturn = NULL;
  115. goto WiaCreateDeviceRegistryList_return;
  116. }
  117. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  118. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  119. // DebugOutputDeviceName(hDevInfo, &spDevInfoData, TEXT("DriverDesc"));
  120. //
  121. // Get device regkey.
  122. //
  123. hkDevRegKey = SetupDiOpenDevRegKey(hDevInfo,
  124. &spDevInfoData,
  125. DICS_FLAG_GLOBAL,
  126. 0,
  127. DIREG_DRV,
  128. KEY_READ | KEY_WRITE);
  129. if(INVALID_HANDLE_VALUE == hkDevRegKey){
  130. //
  131. // Attempt to open the key as READ ONLY instead...
  132. //
  133. hkDevRegKey = SetupDiOpenDevRegKey(hDevInfo,
  134. &spDevInfoData,
  135. DICS_FLAG_GLOBAL,
  136. 0,
  137. DIREG_DRV,
  138. KEY_READ);
  139. if(INVALID_HANDLE_VALUE == hkDevRegKey){
  140. DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: ERROR!! SetupDiOpenDevRegKey (devnodes) fails. Err=0x%x\n"), GetLastError());
  141. continue;
  142. } // if(INVALID_HANDLE_VALUE == hkDevRegKey)
  143. } // if(INVALID_HANDLE_VALUE == hkDevRegKey)
  144. //
  145. // See if it has "StillImage" in SubClass key.
  146. //
  147. if(!IsStiRegKey(hkDevRegKey)){
  148. RegCloseKey(hkDevRegKey);
  149. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  150. continue;
  151. } // if(!IsStiRegKey(hkDevRegKey))
  152. //
  153. // See if this node is active.
  154. //
  155. bIsPlugged = TRUE;
  156. ulStatus = 0;
  157. ulProblemNumber = 0;
  158. ConfigRet = CM_Get_DevNode_Status(&ulStatus,
  159. &ulProblemNumber,
  160. spDevInfoData.DevInst,
  161. 0);
  162. if(CR_SUCCESS != ConfigRet){
  163. // DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: Unable to get devnode status. CR=0x%x.\n"), ConfigRet);
  164. if(bEnumActiveOnly){
  165. RegCloseKey(hkDevRegKey);
  166. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  167. continue;
  168. } else {
  169. bIsPlugged = FALSE;
  170. }
  171. } // if(CR_SUCCESS != ConfigRet)
  172. // DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: Devnode status=0x%x, Problem=0x%x.\n"), ulStatus, ulProblemNumber);
  173. //
  174. // Skip a node with problem if enumerating only active devices.
  175. //
  176. if(bEnumActiveOnly){
  177. if(!(ulStatus & DN_STARTED)){
  178. RegCloseKey(hkDevRegKey);
  179. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  180. continue;
  181. } // if(!(ulStatus & DN_STARTED))
  182. } // if(bEnumActiveOnly)
  183. //
  184. // Add acquired regkey handle. If running out of buffer, enlarge.
  185. //
  186. dwRequiredSize += sizeof(WIA_DEVPROP);
  187. if(dwCurrentSize < dwRequiredSize){
  188. PWIA_DEVKEYLIST pTempNew;
  189. DWORD dwNewSize;
  190. dwNewSize = dwCurrentSize + WIA_DEVKEYLIST_INITIAL_SIZE;
  191. pTempNew = (PWIA_DEVKEYLIST)new BYTE[dwNewSize];
  192. if(NULL == pTempNew){
  193. pReturn = NULL;
  194. goto WiaCreateDeviceRegistryList_return;
  195. } // if(NULL == pTempNew)
  196. memset(pTempNew, 0, dwNewSize);
  197. memcpy(pTempNew, pTempBuffer, dwCurrentSize);
  198. delete pTempBuffer;
  199. pTempBuffer = pTempNew;
  200. dwCurrentSize = dwNewSize;
  201. } // if(dwCurrentSize < dwRequiredSize)
  202. //
  203. // Fill in the structure.
  204. //
  205. pTempBuffer->Dev[dwNumberOfDevices].bIsPlugged = bIsPlugged;
  206. pTempBuffer->Dev[dwNumberOfDevices].ulProblem = ulProblemNumber;
  207. pTempBuffer->Dev[dwNumberOfDevices].ulStatus = ulStatus;
  208. pTempBuffer->Dev[dwNumberOfDevices].hkDeviceRegistry = hkDevRegKey;
  209. dwNumberOfDevices++;
  210. } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  211. //
  212. // Free device info set.
  213. //
  214. SetupDiDestroyDeviceInfoList(hDevInfo);
  215. hDevInfo = INVALID_HANDLE_VALUE;
  216. //
  217. // Enumerate "interface" devices.
  218. //
  219. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE | DIGCF_DEVICEINTERFACE);
  220. if (hDevInfo == INVALID_HANDLE_VALUE) {
  221. pReturn = NULL;
  222. goto WiaCreateDeviceRegistryList_return;
  223. }
  224. spDevInterfaceData.cbSize = sizeof (spDevInterfaceData);
  225. for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++) {
  226. // DebugOutputInterfaceName(hDevInfo, &spDevInterfaceData, TEXT("FriendlyName"));
  227. hkDevRegKey = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  228. &spDevInterfaceData,
  229. 0,
  230. KEY_READ | KEY_WRITE);
  231. if(INVALID_HANDLE_VALUE == hkDevRegKey){
  232. //
  233. // Attempt to open the key as READ ONLY instead...
  234. //
  235. hkDevRegKey = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  236. &spDevInterfaceData,
  237. 0,
  238. KEY_READ);
  239. if(INVALID_HANDLE_VALUE == hkDevRegKey){
  240. continue;
  241. } // if(INVALID_HANDLE_VALUE == hkDevRegKey)
  242. } // if(INVALID_HANDLE_VALUE == hkDevRegKey)
  243. //
  244. // See if it has "StillImage" in SubClass key.
  245. //
  246. if(!IsStiRegKey(hkDevRegKey)){
  247. RegCloseKey(hkDevRegKey);
  248. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  249. continue;
  250. } // if(!IsStiRegKey(hkDevRegKey))
  251. bIsPlugged = TRUE;
  252. ulStatus = 0;
  253. ulProblemNumber = 0;
  254. //
  255. // Get devnode which this interface is created on.
  256. //
  257. SetupDiGetDeviceInterfaceDetail(hDevInfo,
  258. &spDevInterfaceData,
  259. NULL,
  260. 0,
  261. &dwDetailDataSize,
  262. NULL);
  263. if(0 == dwDetailDataSize){
  264. DPRINTF(DM_ERROR, TEXT("IsInterfaceActive: SetupDiGetDeviceInterfaceDetail() failed. Err=0x%x. ReqSize=0x%x"), GetLastError(), dwDetailDataSize);
  265. if(bEnumActiveOnly){
  266. RegCloseKey(hkDevRegKey);
  267. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  268. continue;
  269. } else {
  270. bIsPlugged = FALSE;
  271. }
  272. } // if(0 == dwDetailDataSize)
  273. //
  274. // Allocate memory for data.
  275. //
  276. pspDevInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new char[dwDetailDataSize];
  277. if(NULL == pspDevInterfaceDetailData){
  278. DPRINTF(DM_ERROR, TEXT("IsInterfaceActive: Insufficient buffer."));
  279. RegCloseKey(hkDevRegKey);
  280. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  281. continue;
  282. } // if(NULL == pspDevInterfaceDetailData)
  283. //
  284. // Get the actual data.
  285. //
  286. spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  287. pspDevInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  288. if(!SetupDiGetDeviceInterfaceDetail(hDevInfo,
  289. &spDevInterfaceData,
  290. pspDevInterfaceDetailData,
  291. dwDetailDataSize,
  292. &dwDetailDataSize,
  293. &spDevInfoData)){
  294. DPRINTF(DM_ERROR, TEXT("IsInterfaceActive: SetupDiGetDeviceInterfaceDetail() failed. Err=0x%x. ReqSize=0x%x"), GetLastError(), dwRequiredSize);
  295. delete pspDevInterfaceDetailData;
  296. pspDevInterfaceDetailData = NULL;
  297. if(bEnumActiveOnly){
  298. RegCloseKey(hkDevRegKey);
  299. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  300. continue;
  301. } else {
  302. bIsPlugged = FALSE;
  303. }
  304. }// if(!SetupDiGetDeviceInterfaceDetail()
  305. if(NULL != pspDevInterfaceDetailData){
  306. delete pspDevInterfaceDetailData;
  307. pspDevInterfaceDetailData = NULL;
  308. } // if(NULL != pspDevInterfaceDetailData)
  309. //
  310. // See its devnode is active.
  311. //
  312. ConfigRet = CM_Get_DevNode_Status(&ulStatus,
  313. &ulProblemNumber,
  314. spDevInfoData.DevInst,
  315. 0);
  316. if(CR_SUCCESS != ConfigRet){
  317. DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: Unable to get devnode status. CR=0x%x.\n"), ConfigRet);
  318. if(bEnumActiveOnly){
  319. RegCloseKey(hkDevRegKey);
  320. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  321. continue;
  322. } else {
  323. bIsPlugged = FALSE;
  324. }
  325. } // if(CR_SUCCESS != ConfigRet)
  326. if(bEnumActiveOnly){
  327. if(!(ulStatus & DN_STARTED)){
  328. RegCloseKey(hkDevRegKey);
  329. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  330. continue;
  331. } // if(!(ulStatus & DN_STARTED))
  332. } // if(bEnumActiveOnly)
  333. //
  334. // Add acquired regkey handle. If running out of buffer, enlarge.
  335. //
  336. dwRequiredSize += sizeof(WIA_DEVPROP);
  337. if(dwCurrentSize < dwRequiredSize){
  338. PWIA_DEVKEYLIST pTempNew;
  339. DWORD dwNewSize;
  340. dwNewSize = dwCurrentSize + WIA_DEVKEYLIST_INITIAL_SIZE;
  341. pTempNew = (PWIA_DEVKEYLIST)new BYTE[dwNewSize];
  342. if(NULL == pTempNew){
  343. pReturn = NULL;
  344. goto WiaCreateDeviceRegistryList_return;
  345. } // if(NULL == pTempNew)
  346. memset(pTempNew, 0, dwNewSize);
  347. memcpy(pTempNew, pTempBuffer, dwCurrentSize);
  348. delete pTempBuffer;
  349. pTempBuffer = pTempNew;
  350. dwCurrentSize = dwNewSize;
  351. } // if(dwCurrentSize < dwRequiredSize)
  352. //
  353. // Fill in the structure.
  354. //
  355. pTempBuffer->Dev[dwNumberOfDevices].bIsPlugged = bIsPlugged;
  356. pTempBuffer->Dev[dwNumberOfDevices].ulProblem = ulProblemNumber;
  357. pTempBuffer->Dev[dwNumberOfDevices].ulStatus = ulStatus;
  358. pTempBuffer->Dev[dwNumberOfDevices].hkDeviceRegistry = hkDevRegKey;
  359. dwNumberOfDevices++;
  360. } // for (Idx = 0; SetupDiEnumDeviceInterfaces (hDevInfo, NULL, &Guid, Idx, &spDevInterfaceData); Idx++)
  361. //
  362. // Operation succeeded.
  363. //
  364. if(0 != dwNumberOfDevices){
  365. pTempBuffer->dwNumberOfDevices = dwNumberOfDevices;
  366. pReturn = pTempBuffer;
  367. pTempBuffer = NULL;
  368. } // if(0 != dwNumberOfDevices)
  369. WiaCreateDeviceRegistryList_return:
  370. //
  371. // Clean up.
  372. //
  373. if(INVALID_HANDLE_VALUE != hDevInfo){
  374. SetupDiDestroyDeviceInfoList(hDevInfo);
  375. } // if(INVALID_HANDLE_VALUE != hDevInfo)
  376. if(NULL != pTempBuffer){
  377. pTempBuffer->dwNumberOfDevices = dwNumberOfDevices;
  378. WiaDestroyDeviceRegistryList(pTempBuffer);
  379. } // if(NULL != pTempBuffer)
  380. // DPRINTF(DM_ERROR, TEXT("WiaCreateDeviceRegistryList: Leave... %d devices. Ret=0x%p."), dwNumberOfDevices, pReturn);
  381. return pReturn;
  382. } // WiaCreateDeviceRegistryList()
  383. VOID
  384. WiaDestroyDeviceRegistryList(
  385. PWIA_DEVKEYLIST pWiaDevKeyList
  386. )
  387. {
  388. DWORD Idx;
  389. //
  390. // Check argument.
  391. //
  392. if(NULL == pWiaDevKeyList){
  393. goto WiaFreeDeviceRegistryList_return;
  394. }
  395. for(Idx = 0; Idx < pWiaDevKeyList->dwNumberOfDevices; Idx++){
  396. if(INVALID_HANDLE_VALUE != pWiaDevKeyList->Dev[Idx].hkDeviceRegistry){
  397. RegCloseKey(pWiaDevKeyList->Dev[Idx].hkDeviceRegistry);
  398. } // if(INVALID_HANDLE_VALUE != pWiaDevKeyList->Dev[Idx].hkDeviceRegistry)
  399. } // for(Idx = 0; Idx < pWiaDevKeyList->dwNumberOfDevices; Idx++)
  400. delete pWiaDevKeyList;
  401. WiaFreeDeviceRegistryList_return:
  402. return;
  403. }
  404. VOID
  405. EnumLpt(
  406. VOID
  407. )
  408. {
  409. CONFIGRET ConfigRet;
  410. HDEVINFO hLptDevInfo;
  411. SP_DEVINFO_DATA spDevInfoData;
  412. DWORD Idx;
  413. GUID Guid;
  414. DWORD dwCurrentTickCount;
  415. static DWORD s_dwLastTickCount = 0;
  416. //
  417. // Initialize local.
  418. //
  419. ConfigRet = CR_SUCCESS;
  420. hLptDevInfo = (HDEVINFO) INVALID_HANDLE_VALUE;
  421. Idx = 0;
  422. Guid = GUID_PARALLEL_DEVICE;
  423. dwCurrentTickCount = 0;
  424. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  425. //
  426. // Get current system tick.
  427. //
  428. dwCurrentTickCount = GetTickCount();
  429. //
  430. // Bail out if the function is called within ENUMLPT_HOLDTIME millisec.
  431. //
  432. if( (dwCurrentTickCount - s_dwLastTickCount) < ENUMLPT_HOLDTIME){
  433. goto EnumLpt_return;
  434. }
  435. //
  436. // Save current tick
  437. //
  438. s_dwLastTickCount = dwCurrentTickCount;
  439. //
  440. // Enum LPT port as needed.
  441. //
  442. if(IsPnpLptExisting()){
  443. //
  444. // Get LPT devnodes.
  445. //
  446. Guid = GUID_PARALLEL_DEVICE;
  447. hLptDevInfo = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_INTERFACEDEVICE);
  448. if(INVALID_HANDLE_VALUE == hLptDevInfo){
  449. goto EnumLpt_return;
  450. }
  451. //
  452. // Re-enumerate LPT port.
  453. //
  454. spDevInfoData.cbSize = sizeof(spDevInfoData);
  455. for(Idx = 0; SetupDiEnumDeviceInfo(hLptDevInfo, Idx, &spDevInfoData); Idx++){
  456. ConfigRet = CM_Reenumerate_DevNode(spDevInfoData.DevInst, CM_REENUMERATE_NORMAL);
  457. if(CR_SUCCESS != ConfigRet){
  458. DPRINTF(DM_ERROR,TEXT("EnumLpt: ERROR!! CM_Reenumerate_DevNode() fails. Idx=0x%x, ConfigRet=0x%x\n"), Idx, ConfigRet);
  459. } // if(CR_SUCCESS != ConfigRet)
  460. } // for(Idx = 0; SetupDiEnumDeviceInfo(hLptDevInfo, Idx, &spDevInfoData); Idx++)
  461. } // if(IsPnpLptExisting())
  462. EnumLpt_return:
  463. //
  464. // Clean up.
  465. //
  466. if(INVALID_HANDLE_VALUE != hLptDevInfo){
  467. SetupDiDestroyDeviceInfoList(hLptDevInfo);
  468. } // if(INVALID_HANDLE_HALUE != hLptDevInfo)
  469. return;
  470. } // EnumLpt()
  471. BOOL
  472. IsPnpLptExisting(
  473. VOID
  474. )
  475. {
  476. HDEVINFO hDevInfo;
  477. CONFIGRET ConfigRet;
  478. DWORD Idx;
  479. GUID Guid;
  480. SP_DEVINFO_DATA spDevInfoData;
  481. HKEY hkDevRegKey;
  482. DWORD dwHardwareConfig;
  483. LONG lResult;
  484. ULONG ulStatus;
  485. ULONG ulProblemNumber;
  486. BOOL bRet;
  487. //
  488. // Initialize local.
  489. //
  490. hDevInfo = INVALID_HANDLE_VALUE;
  491. ConfigRet = CR_SUCCESS;
  492. Idx = 0;
  493. Guid = GUID_DEVCLASS_IMAGE;
  494. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  495. ulStatus = 0;
  496. ulProblemNumber = 0;
  497. bRet = FALSE;
  498. memset(&spDevInfoData, 0, sizeof(spDevInfoData));
  499. //
  500. // Enum Imaging class devnode.
  501. //
  502. hDevInfo = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PROFILE);
  503. if(hDevInfo == INVALID_HANDLE_VALUE){
  504. goto IsPnpLptExisting_return;
  505. } // if(hDevInfo == INVALID_HANDLE_VALUE)}
  506. spDevInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  507. for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++) {
  508. hkDevRegKey = SetupDiOpenDevRegKey(hDevInfo,
  509. &spDevInfoData,
  510. DICS_FLAG_GLOBAL,
  511. 0,
  512. DIREG_DRV,
  513. KEY_READ);
  514. if(INVALID_HANDLE_VALUE == hkDevRegKey){
  515. DPRINTF(DM_ERROR,TEXT("WiaCreateDeviceRegistryList: ERROR!! SetupDiOpenDevRegKey (devnodes) fails. Err=0x%x\n"), GetLastError());
  516. continue;
  517. } // if(INVALID_HANDLE_VALUE == hkDevRegKey)
  518. //
  519. // Make sure it's STI/WIA device.
  520. //
  521. if(!IsStiRegKey(hkDevRegKey)){
  522. RegCloseKey(hkDevRegKey);
  523. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  524. continue;
  525. } // if(!IsStiRegKey(hkDevRegKey))
  526. //
  527. // Get "Hardware config" key.
  528. //
  529. dwHardwareConfig = ReadRegistryDwordW(hkDevRegKey, REGSTR_VAL_HARDWARE_W, 0);
  530. RegCloseKey(hkDevRegKey);
  531. hkDevRegKey = (HKEY)INVALID_HANDLE_VALUE;
  532. if(!(dwHardwareConfig & STI_HW_CONFIG_PARALLEL)){
  533. //
  534. // This is not a parallel device.
  535. //
  536. continue;
  537. } // if(!IsStiRegKey(hkDevRegKey))
  538. //
  539. // See if device is detected by system.
  540. //
  541. ulStatus = 0;
  542. ulProblemNumber = 0;
  543. ConfigRet = CM_Get_DevNode_Status(&ulStatus,
  544. &ulProblemNumber,
  545. spDevInfoData.DevInst,
  546. 0);
  547. if(CR_SUCCESS != ConfigRet){
  548. //
  549. // There is a Pnp LPT device installed but not been detected on boot. Let enum LPT.
  550. //
  551. bRet = TRUE;
  552. break;
  553. } // if(CR_SUCCESS != ConfigRet)
  554. } // for (Idx = 0; SetupDiEnumDeviceInfo (hDevInfo, Idx, &spDevInfoData); Idx++)
  555. IsPnpLptExisting_return:
  556. //
  557. // Clean up.
  558. //
  559. if(INVALID_HANDLE_VALUE != hDevInfo){
  560. SetupDiDestroyDeviceInfoList(hDevInfo);
  561. } // if(INVALID_HANDLE_VALUE != hDevInfo)
  562. return bRet;
  563. } // IsPnpLptExisting()
  564. } // extern "C"
  565. VOID
  566. DebugOutputDeviceName(
  567. HDEVINFO hDevInfo,
  568. PSP_DEVINFO_DATA pspDevInfoData,
  569. LPCTSTR szKeyName
  570. )
  571. {
  572. HKEY hkDev = NULL;
  573. TCHAR szBuffer[1024];
  574. DWORD dwSize;
  575. LONG lResult;
  576. DWORD dwType;
  577. hkDev = SetupDiOpenDevRegKey(hDevInfo,
  578. pspDevInfoData,
  579. DICS_FLAG_GLOBAL,
  580. 0,
  581. DIREG_DRV,
  582. KEY_READ);
  583. if(INVALID_HANDLE_VALUE == hkDev){
  584. DPRINTF(DM_ERROR, TEXT("DebugOutputDeviceName: SetupDiOpenDevRegKey() failed. Err=0x%x"), GetLastError());
  585. goto DebugOutputDeviceName_return;
  586. } // if(INVALID_HANDLE_VALUE == hkDev)
  587. dwSize = sizeof(szBuffer);
  588. lResult = RegQueryValueEx(hkDev,
  589. szKeyName,
  590. NULL,
  591. &dwType,
  592. (LPBYTE)szBuffer,
  593. &dwSize);
  594. if(ERROR_SUCCESS != lResult){
  595. DPRINTF(DM_ERROR, TEXT("DebugOutputDeviceName: RegQueryValueEx() failed. Err=0x%x"), lResult);
  596. goto DebugOutputDeviceName_return;
  597. }
  598. switch(dwType){
  599. case REG_DWORD:
  600. DPRINTF(DM_ERROR, TEXT("DebugOutputDeviceName: Value: %s, Data: 0x%x"), szKeyName, szBuffer);
  601. break;
  602. case REG_SZ:
  603. DPRINTF(DM_ERROR, TEXT("DebugOutputDeviceName: Value: %s, Data: %s"), szKeyName, szBuffer);
  604. }
  605. DebugOutputDeviceName_return:
  606. // Close opened key
  607. if(hkDev && (INVALID_HANDLE_VALUE != hkDev) ){
  608. RegCloseKey(hkDev);
  609. hkDev = (HKEY)INVALID_HANDLE_VALUE;
  610. }
  611. return;
  612. } // DebugOutputDeviceRegistry(
  613. VOID
  614. DebugOutputInterfaceName(
  615. HDEVINFO hDevInfo,
  616. PSP_DEVICE_INTERFACE_DATA pspDevInterfaceData,
  617. LPCTSTR szKeyName
  618. )
  619. {
  620. HKEY hkDev = NULL;
  621. TCHAR szBuffer[1024];
  622. DWORD dwSize;
  623. LONG lResult;
  624. DWORD dwType;
  625. hkDev = SetupDiOpenDeviceInterfaceRegKey(hDevInfo,
  626. pspDevInterfaceData,
  627. 0,
  628. KEY_READ);
  629. if(INVALID_HANDLE_VALUE == hkDev){
  630. // DPRINTF(DM_ERROR, TEXT("DebugOutputInterfaceName: SetupDiOpenDeviceInterfaceRegKey() failed. Err=0x%x"), GetLastError());
  631. goto DebugOutputInterfaceName_return;
  632. } // if(INVALID_HANDLE_VALUE == hkDev)
  633. dwSize = sizeof(szBuffer);
  634. lResult = RegQueryValueEx(hkDev,
  635. szKeyName,
  636. NULL,
  637. &dwType,
  638. (LPBYTE)szBuffer,
  639. &dwSize);
  640. if(ERROR_SUCCESS != lResult){
  641. // DPRINTF(DM_ERROR, TEXT("DebugOutputInterfaceName: RegQueryValueEx() failed. Err=0x%x"), lResult);
  642. goto DebugOutputInterfaceName_return;
  643. }
  644. switch(dwType){
  645. case REG_DWORD:
  646. DPRINTF(DM_ERROR, TEXT("DebugOutputInterfaceName: Value: %s, Data: 0x%x"), szKeyName, szBuffer);
  647. break;
  648. case REG_SZ:
  649. DPRINTF(DM_ERROR, TEXT("DebugOutputInterfaceName: Value: %s, Data: %s"), szKeyName, szBuffer);
  650. }
  651. DebugOutputInterfaceName_return:
  652. // Close opened key
  653. if(hkDev && (INVALID_HANDLE_VALUE != hkDev) ){
  654. RegCloseKey(hkDev);
  655. hkDev = (HKEY)INVALID_HANDLE_VALUE;
  656. }
  657. return;
  658. } // DebugOutputInterfaceName()
  659. BOOL
  660. IsStiRegKey(
  661. HKEY hkDevRegKey
  662. )
  663. {
  664. DWORD dwValueSize;
  665. TCHAR szSubClass[MAX_PATH];
  666. BOOL bRet;
  667. bRet = TRUE;
  668. dwValueSize = sizeof(szSubClass);
  669. memset(&szSubClass, 0, sizeof(szSubClass));
  670. RegQueryValueEx(hkDevRegKey,
  671. SUBCLASS,
  672. NULL,
  673. NULL,
  674. (LPBYTE)szSubClass,
  675. &dwValueSize);
  676. if( (0 == lstrlen(szSubClass))
  677. || (lstrcmpi(szSubClass, STILL_IMAGE)) )
  678. {
  679. bRet = FALSE;
  680. }
  681. return bRet;
  682. } // IsStiRegKey()
  683. /********************************* End of File ***************************/