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.

876 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This module contains the code
  7. for finding, adding, removing, and identifying hid devices.
  8. Environment:
  9. User mode
  10. @@BEGIN_DDKSPLIT
  11. Revision History:
  12. Nov-96 : Created by Kenneth D. Ray
  13. @@END_DDKSPLIT
  14. --*/
  15. #include <basetyps.h>
  16. #include <stdlib.h>
  17. #include <wtypes.h>
  18. #include <setupapi.h>
  19. #include "hidsdi.h"
  20. #include "hid.h"
  21. #include <strsafe.h>
  22. BOOLEAN
  23. FindKnownHidDevices (
  24. OUT PHID_DEVICE * HidDevices, // A array of struct _HID_DEVICE
  25. OUT PULONG NumberDevices // the length of this array.
  26. )
  27. /*++
  28. Routine Description:
  29. Do the required PnP things in order to find all the HID devices in
  30. the system at this time.
  31. --*/
  32. {
  33. HDEVINFO hardwareDeviceInfo;
  34. SP_DEVICE_INTERFACE_DATA deviceInfoData;
  35. ULONG i;
  36. BOOLEAN done;
  37. PHID_DEVICE hidDeviceInst;
  38. GUID hidGuid;
  39. PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
  40. ULONG predictedLength = 0;
  41. ULONG requiredLength = 0;
  42. PHID_DEVICE newHidDevices;
  43. HidD_GetHidGuid (&hidGuid);
  44. *HidDevices = NULL;
  45. *NumberDevices = 0;
  46. //
  47. // Open a handle to the plug and play dev node.
  48. //
  49. hardwareDeviceInfo = SetupDiGetClassDevs ( &hidGuid,
  50. NULL, // Define no enumerator (global)
  51. NULL, // Define no
  52. (DIGCF_PRESENT | // Only Devices present
  53. DIGCF_DEVICEINTERFACE)); // Function class devices.
  54. //
  55. // Take a wild guess to start
  56. //
  57. *NumberDevices = 4;
  58. done = FALSE;
  59. deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
  60. i=0;
  61. while (!done)
  62. {
  63. *NumberDevices *= 2;
  64. if (*HidDevices)
  65. {
  66. newHidDevices =
  67. realloc (*HidDevices, (*NumberDevices * sizeof (HID_DEVICE)));
  68. if (NULL == newHidDevices)
  69. {
  70. free(*HidDevices);
  71. }
  72. *HidDevices = newHidDevices;
  73. }
  74. else
  75. {
  76. *HidDevices = calloc (*NumberDevices, sizeof (HID_DEVICE));
  77. }
  78. if (NULL == *HidDevices)
  79. {
  80. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  81. return FALSE;
  82. }
  83. hidDeviceInst = *HidDevices + i;
  84. for (; i < *NumberDevices; i++, hidDeviceInst++)
  85. {
  86. if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
  87. 0, // No care about specific PDOs
  88. &hidGuid,
  89. i,
  90. &deviceInfoData))
  91. {
  92. //
  93. // allocate a function class device data structure to receive the
  94. // goods about this particular device.
  95. //
  96. SetupDiGetDeviceInterfaceDetail (
  97. hardwareDeviceInfo,
  98. &deviceInfoData,
  99. NULL, // probing so no output buffer yet
  100. 0, // probing so output buffer length of zero
  101. &requiredLength,
  102. NULL); // not interested in the specific dev-node
  103. predictedLength = requiredLength;
  104. functionClassDeviceData = malloc (predictedLength);
  105. if (functionClassDeviceData)
  106. {
  107. functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
  108. }
  109. else
  110. {
  111. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  112. return FALSE;
  113. }
  114. //
  115. // Retrieve the information from Plug and Play.
  116. //
  117. if (! SetupDiGetDeviceInterfaceDetail (
  118. hardwareDeviceInfo,
  119. &deviceInfoData,
  120. functionClassDeviceData,
  121. predictedLength,
  122. &requiredLength,
  123. NULL))
  124. {
  125. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  126. free(functionClassDeviceData);
  127. return FALSE;
  128. }
  129. //
  130. // Open device with just generic query abilities to begin with
  131. //
  132. if (! OpenHidDevice (functionClassDeviceData -> DevicePath,
  133. FALSE, // ReadAccess - none
  134. FALSE, // WriteAccess - none
  135. FALSE, // Overlapped - no
  136. FALSE, // Exclusive - no
  137. hidDeviceInst))
  138. {
  139. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  140. free(functionClassDeviceData);
  141. return FALSE;
  142. }
  143. }
  144. else
  145. {
  146. if (ERROR_NO_MORE_ITEMS == GetLastError())
  147. {
  148. done = TRUE;
  149. break;
  150. }
  151. }
  152. }
  153. }
  154. *NumberDevices = i;
  155. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  156. free(functionClassDeviceData);
  157. return TRUE;
  158. }
  159. BOOLEAN
  160. OpenHidDevice (
  161. IN PCHAR DevicePath,
  162. IN BOOL HasReadAccess,
  163. IN BOOL HasWriteAccess,
  164. IN BOOL IsOverlapped,
  165. IN BOOL IsExclusive,
  166. IN OUT PHID_DEVICE HidDevice
  167. )
  168. /*++
  169. RoutineDescription:
  170. Given the HardwareDeviceInfo, representing a handle to the plug and
  171. play information, and deviceInfoData, representing a specific hid device,
  172. open that device and fill in all the relivant information in the given
  173. HID_DEVICE structure.
  174. return if the open and initialization was successfull or not.
  175. --*/
  176. {
  177. DWORD accessFlags = 0;
  178. DWORD sharingFlags = 0;
  179. BOOLEAN bSuccess;
  180. INT iDevicePathSize;
  181. HRESULT stringReturn;
  182. iDevicePathSize = strlen(DevicePath) + 1;
  183. HidDevice -> DevicePath = malloc(iDevicePathSize);
  184. if (NULL == HidDevice -> DevicePath)
  185. {
  186. return (FALSE);
  187. }
  188. stringReturn = StringCbCopy(HidDevice -> DevicePath, iDevicePathSize, DevicePath);
  189. if (HasReadAccess)
  190. {
  191. accessFlags |= GENERIC_READ;
  192. }
  193. if (HasWriteAccess)
  194. {
  195. accessFlags |= GENERIC_WRITE;
  196. }
  197. if (!IsExclusive)
  198. {
  199. sharingFlags = FILE_SHARE_READ | FILE_SHARE_WRITE;
  200. }
  201. //
  202. // The hid.dll api's do not pass the overlapped structure into deviceiocontrol
  203. // so to use them we must have a non overlapped device. If the request is for
  204. // an overlapped device we will close the device below and get a handle to an
  205. // overlapped device
  206. //
  207. HidDevice->HidDevice = CreateFile (DevicePath,
  208. accessFlags,
  209. sharingFlags,
  210. NULL, // no SECURITY_ATTRIBUTES structure
  211. OPEN_EXISTING, // No special create flags
  212. 0, // Open device as non-overlapped so we can get data
  213. NULL); // No template file
  214. if (INVALID_HANDLE_VALUE == HidDevice->HidDevice)
  215. {
  216. free(HidDevice -> DevicePath);
  217. HidDevice -> DevicePath = INVALID_HANDLE_VALUE ;
  218. return FALSE;
  219. }
  220. HidDevice -> OpenedForRead = HasReadAccess;
  221. HidDevice -> OpenedForWrite = HasWriteAccess;
  222. HidDevice -> OpenedOverlapped = IsOverlapped;
  223. HidDevice -> OpenedExclusive = IsExclusive;
  224. //
  225. // If the device was not opened as overlapped, then fill in the rest of the
  226. // HidDevice structure. However, if opened as overlapped, this handle cannot
  227. // be used in the calls to the HidD_ exported functions since each of these
  228. // functions does synchronous I/O.
  229. //
  230. if (!HidD_GetPreparsedData (HidDevice->HidDevice, &HidDevice->Ppd))
  231. {
  232. free(HidDevice -> DevicePath);
  233. HidDevice -> DevicePath = NULL ;
  234. CloseHandle(HidDevice -> HidDevice);
  235. HidDevice -> HidDevice = INVALID_HANDLE_VALUE ;
  236. return FALSE;
  237. }
  238. if (!HidD_GetAttributes (HidDevice->HidDevice, &HidDevice->Attributes))
  239. {
  240. free(HidDevice -> DevicePath);
  241. HidDevice -> DevicePath = NULL;
  242. CloseHandle(HidDevice -> HidDevice);
  243. HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
  244. HidD_FreePreparsedData (HidDevice->Ppd);
  245. HidDevice->Ppd = NULL;
  246. return FALSE;
  247. }
  248. if (!HidP_GetCaps (HidDevice->Ppd, &HidDevice->Caps))
  249. {
  250. free(HidDevice -> DevicePath);
  251. HidDevice -> DevicePath = NULL;
  252. CloseHandle(HidDevice -> HidDevice);
  253. HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
  254. HidD_FreePreparsedData (HidDevice->Ppd);
  255. HidDevice->Ppd = NULL;
  256. return FALSE;
  257. }
  258. //
  259. // At this point the client has a choice. It may chose to look at the
  260. // Usage and Page of the top level collection found in the HIDP_CAPS
  261. // structure. In this way it could just use the usages it knows about.
  262. // If either HidP_GetUsages or HidP_GetUsageValue return an error then
  263. // that particular usage does not exist in the report.
  264. // This is most likely the preferred method as the application can only
  265. // use usages of which it already knows.
  266. // In this case the app need not even call GetButtonCaps or GetValueCaps.
  267. //
  268. // In this example, however, we will call FillDeviceInfo to look for all
  269. // of the usages in the device.
  270. //
  271. bSuccess = FillDeviceInfo(HidDevice);
  272. if (FALSE == bSuccess)
  273. {
  274. CloseHidDevice(HidDevice);
  275. return (FALSE);
  276. }
  277. if (IsOverlapped)
  278. {
  279. CloseHandle(HidDevice->HidDevice);
  280. HidDevice->HidDevice = CreateFile (DevicePath,
  281. accessFlags,
  282. sharingFlags,
  283. NULL, // no SECURITY_ATTRIBUTES structure
  284. OPEN_EXISTING, // No special create flags
  285. FILE_FLAG_OVERLAPPED, // Now we open the device as overlapped
  286. NULL); // No template file
  287. if (INVALID_HANDLE_VALUE == HidDevice->HidDevice)
  288. {
  289. CloseHidDevice(HidDevice);
  290. return FALSE;
  291. }
  292. }
  293. return (TRUE);
  294. }
  295. BOOLEAN
  296. FillDeviceInfo(
  297. IN PHID_DEVICE HidDevice
  298. )
  299. {
  300. USHORT numValues;
  301. USHORT numCaps;
  302. PHIDP_BUTTON_CAPS buttonCaps;
  303. PHIDP_VALUE_CAPS valueCaps;
  304. PHID_DATA data;
  305. ULONG i;
  306. USAGE usage;
  307. //
  308. // setup Input Data buffers.
  309. //
  310. //
  311. // Allocate memory to hold on input report
  312. //
  313. HidDevice->InputReportBuffer = (PCHAR)
  314. calloc (HidDevice->Caps.InputReportByteLength, sizeof (CHAR));
  315. //
  316. // Allocate memory to hold the button and value capabilities.
  317. // NumberXXCaps is in terms of array elements.
  318. //
  319. HidDevice->InputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
  320. calloc (HidDevice->Caps.NumberInputButtonCaps, sizeof (HIDP_BUTTON_CAPS));
  321. if (NULL == buttonCaps)
  322. {
  323. return (FALSE);
  324. }
  325. HidDevice->InputValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
  326. calloc (HidDevice->Caps.NumberInputValueCaps, sizeof (HIDP_VALUE_CAPS));
  327. if (NULL == valueCaps)
  328. {
  329. return(FALSE);
  330. }
  331. //
  332. // Have the HidP_X functions fill in the capability structure arrays.
  333. //
  334. numCaps = HidDevice->Caps.NumberInputButtonCaps;
  335. HidP_GetButtonCaps (HidP_Input,
  336. buttonCaps,
  337. &numCaps,
  338. HidDevice->Ppd);
  339. numCaps = HidDevice->Caps.NumberInputValueCaps;
  340. HidP_GetValueCaps (HidP_Input,
  341. valueCaps,
  342. &numCaps,
  343. HidDevice->Ppd);
  344. //
  345. // Depending on the device, some value caps structures may represent more
  346. // than one value. (A range). In the interest of being verbose, over
  347. // efficient, we will expand these so that we have one and only one
  348. // struct _HID_DATA for each value.
  349. //
  350. // To do this we need to count up the total number of values are listed
  351. // in the value caps structure. For each element in the array we test
  352. // for range if it is a range then UsageMax and UsageMin describe the
  353. // usages for this range INCLUSIVE.
  354. //
  355. numValues = 0;
  356. for (i = 0; i < HidDevice->Caps.NumberInputValueCaps; i++, valueCaps++)
  357. {
  358. if (valueCaps->IsRange)
  359. {
  360. numValues += valueCaps->Range.UsageMax - valueCaps->Range.UsageMin + 1;
  361. }
  362. else
  363. {
  364. numValues++;
  365. }
  366. }
  367. valueCaps = HidDevice->InputValueCaps;
  368. //
  369. // Allocate a buffer to hold the struct _HID_DATA structures.
  370. // One element for each set of buttons, and one element for each value
  371. // found.
  372. //
  373. HidDevice->InputDataLength = HidDevice->Caps.NumberInputButtonCaps
  374. + numValues;
  375. HidDevice->InputData = data = (PHID_DATA)
  376. calloc (HidDevice->InputDataLength, sizeof (HID_DATA));
  377. if (NULL == data)
  378. {
  379. return (FALSE);
  380. }
  381. //
  382. // Fill in the button data
  383. //
  384. for (i = 0;
  385. i < HidDevice->Caps.NumberInputButtonCaps;
  386. i++, data++, buttonCaps++)
  387. {
  388. data->IsButtonData = TRUE;
  389. data->Status = HIDP_STATUS_SUCCESS;
  390. data->UsagePage = buttonCaps->UsagePage;
  391. if (buttonCaps->IsRange)
  392. {
  393. data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
  394. data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
  395. }
  396. else
  397. {
  398. data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
  399. }
  400. data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
  401. HidP_Input,
  402. buttonCaps->UsagePage,
  403. HidDevice->Ppd);
  404. data->ButtonData.Usages = (PUSAGE)
  405. calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
  406. data->ReportID = buttonCaps -> ReportID;
  407. }
  408. //
  409. // Fill in the value data
  410. //
  411. for (i = 0; i < numValues; i++, valueCaps++)
  412. {
  413. if (valueCaps->IsRange)
  414. {
  415. for (usage = valueCaps->Range.UsageMin;
  416. usage <= valueCaps->Range.UsageMax;
  417. usage++)
  418. {
  419. data->IsButtonData = FALSE;
  420. data->Status = HIDP_STATUS_SUCCESS;
  421. data->UsagePage = valueCaps->UsagePage;
  422. data->ValueData.Usage = usage;
  423. data->ReportID = valueCaps -> ReportID;
  424. data++;
  425. }
  426. }
  427. else
  428. {
  429. data->IsButtonData = FALSE;
  430. data->Status = HIDP_STATUS_SUCCESS;
  431. data->UsagePage = valueCaps->UsagePage;
  432. data->ValueData.Usage = valueCaps->NotRange.Usage;
  433. data->ReportID = valueCaps -> ReportID;
  434. data++;
  435. }
  436. }
  437. //
  438. // setup Output Data buffers.
  439. //
  440. HidDevice->OutputReportBuffer = (PCHAR)
  441. calloc (HidDevice->Caps.OutputReportByteLength, sizeof (CHAR));
  442. HidDevice->OutputButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
  443. calloc (HidDevice->Caps.NumberOutputButtonCaps, sizeof (HIDP_BUTTON_CAPS));
  444. if (NULL == buttonCaps)
  445. {
  446. return (FALSE);
  447. }
  448. HidDevice->OutputValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
  449. calloc (HidDevice->Caps.NumberOutputValueCaps, sizeof (HIDP_VALUE_CAPS));
  450. if (NULL == valueCaps)
  451. {
  452. return (FALSE);
  453. }
  454. numCaps = HidDevice->Caps.NumberOutputButtonCaps;
  455. HidP_GetButtonCaps (HidP_Output,
  456. buttonCaps,
  457. &numCaps,
  458. HidDevice->Ppd);
  459. numCaps = HidDevice->Caps.NumberOutputValueCaps;
  460. HidP_GetValueCaps (HidP_Output,
  461. valueCaps,
  462. &numCaps,
  463. HidDevice->Ppd);
  464. numValues = 0;
  465. for (i = 0; i < HidDevice->Caps.NumberOutputValueCaps; i++, valueCaps++)
  466. {
  467. if (valueCaps->IsRange)
  468. {
  469. numValues += valueCaps->Range.UsageMax
  470. - valueCaps->Range.UsageMin + 1;
  471. }
  472. else
  473. {
  474. numValues++;
  475. }
  476. }
  477. valueCaps = HidDevice->OutputValueCaps;
  478. HidDevice->OutputDataLength = HidDevice->Caps.NumberOutputButtonCaps
  479. + numValues;
  480. HidDevice->OutputData = data = (PHID_DATA)
  481. calloc (HidDevice->OutputDataLength, sizeof (HID_DATA));
  482. if (NULL == data)
  483. {
  484. return (FALSE);
  485. }
  486. for (i = 0;
  487. i < HidDevice->Caps.NumberOutputButtonCaps;
  488. i++, data++, buttonCaps++)
  489. {
  490. data->IsButtonData = TRUE;
  491. data->Status = HIDP_STATUS_SUCCESS;
  492. data->UsagePage = buttonCaps->UsagePage;
  493. if (buttonCaps->IsRange)
  494. {
  495. data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
  496. data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
  497. }
  498. else
  499. {
  500. data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
  501. }
  502. data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
  503. HidP_Output,
  504. buttonCaps->UsagePage,
  505. HidDevice->Ppd);
  506. data->ButtonData.Usages = (PUSAGE)
  507. calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
  508. data->ReportID = buttonCaps -> ReportID;
  509. }
  510. for (i = 0; i < numValues; i++, valueCaps++)
  511. {
  512. if (valueCaps->IsRange)
  513. {
  514. for (usage = valueCaps->Range.UsageMin;
  515. usage <= valueCaps->Range.UsageMax;
  516. usage++)
  517. {
  518. data->IsButtonData = FALSE;
  519. data->Status = HIDP_STATUS_SUCCESS;
  520. data->UsagePage = valueCaps->UsagePage;
  521. data->ValueData.Usage = usage;
  522. data->ReportID = valueCaps -> ReportID;
  523. data++;
  524. }
  525. }
  526. else
  527. {
  528. data->IsButtonData = FALSE;
  529. data->Status = HIDP_STATUS_SUCCESS;
  530. data->UsagePage = valueCaps->UsagePage;
  531. data->ValueData.Usage = valueCaps->NotRange.Usage;
  532. data->ReportID = valueCaps -> ReportID;
  533. data++;
  534. }
  535. }
  536. //
  537. // setup Feature Data buffers.
  538. //
  539. HidDevice->FeatureReportBuffer = (PCHAR)
  540. calloc (HidDevice->Caps.FeatureReportByteLength, sizeof (CHAR));
  541. HidDevice->FeatureButtonCaps = buttonCaps = (PHIDP_BUTTON_CAPS)
  542. calloc (HidDevice->Caps.NumberFeatureButtonCaps, sizeof (HIDP_BUTTON_CAPS));
  543. if (NULL == buttonCaps)
  544. {
  545. return (FALSE);
  546. }
  547. HidDevice->FeatureValueCaps = valueCaps = (PHIDP_VALUE_CAPS)
  548. calloc (HidDevice->Caps.NumberFeatureValueCaps, sizeof (HIDP_VALUE_CAPS));
  549. if (NULL == valueCaps)
  550. {
  551. return (FALSE);
  552. }
  553. numCaps = HidDevice->Caps.NumberFeatureButtonCaps;
  554. HidP_GetButtonCaps (HidP_Feature,
  555. buttonCaps,
  556. &numCaps,
  557. HidDevice->Ppd);
  558. numCaps = HidDevice->Caps.NumberFeatureValueCaps;
  559. HidP_GetValueCaps (HidP_Feature,
  560. valueCaps,
  561. &numCaps,
  562. HidDevice->Ppd);
  563. numValues = 0;
  564. for (i = 0; i < HidDevice->Caps.NumberFeatureValueCaps; i++, valueCaps++)
  565. {
  566. if (valueCaps->IsRange)
  567. {
  568. numValues += valueCaps->Range.UsageMax
  569. - valueCaps->Range.UsageMin + 1;
  570. }
  571. else
  572. {
  573. numValues++;
  574. }
  575. }
  576. valueCaps = HidDevice->FeatureValueCaps;
  577. HidDevice->FeatureDataLength = HidDevice->Caps.NumberFeatureButtonCaps
  578. + numValues;
  579. HidDevice->FeatureData = data = (PHID_DATA)
  580. calloc (HidDevice->FeatureDataLength, sizeof (HID_DATA));
  581. if (NULL == data)
  582. {
  583. return (FALSE);
  584. }
  585. for (i = 0;
  586. i < HidDevice->Caps.NumberFeatureButtonCaps;
  587. i++, data++, buttonCaps++)
  588. {
  589. data->IsButtonData = TRUE;
  590. data->Status = HIDP_STATUS_SUCCESS;
  591. data->UsagePage = buttonCaps->UsagePage;
  592. if (buttonCaps->IsRange)
  593. {
  594. data->ButtonData.UsageMin = buttonCaps -> Range.UsageMin;
  595. data->ButtonData.UsageMax = buttonCaps -> Range.UsageMax;
  596. }
  597. else
  598. {
  599. data -> ButtonData.UsageMin = data -> ButtonData.UsageMax = buttonCaps -> NotRange.Usage;
  600. }
  601. data->ButtonData.MaxUsageLength = HidP_MaxUsageListLength (
  602. HidP_Feature,
  603. buttonCaps->UsagePage,
  604. HidDevice->Ppd);
  605. data->ButtonData.Usages = (PUSAGE)
  606. calloc (data->ButtonData.MaxUsageLength, sizeof (USAGE));
  607. data->ReportID = buttonCaps -> ReportID;
  608. }
  609. for (i = 0; i < numValues; i++, valueCaps++)
  610. {
  611. if (valueCaps->IsRange)
  612. {
  613. for (usage = valueCaps->Range.UsageMin;
  614. usage <= valueCaps->Range.UsageMax;
  615. usage++)
  616. {
  617. data->IsButtonData = FALSE;
  618. data->Status = HIDP_STATUS_SUCCESS;
  619. data->UsagePage = valueCaps->UsagePage;
  620. data->ValueData.Usage = usage;
  621. data->ReportID = valueCaps -> ReportID;
  622. data++;
  623. }
  624. }
  625. else
  626. {
  627. data->IsButtonData = FALSE;
  628. data->Status = HIDP_STATUS_SUCCESS;
  629. data->UsagePage = valueCaps->UsagePage;
  630. data->ValueData.Usage = valueCaps->NotRange.Usage;
  631. data->ReportID = valueCaps -> ReportID;
  632. data++;
  633. }
  634. }
  635. return (TRUE);
  636. }
  637. VOID
  638. CloseHidDevices(
  639. IN PHID_DEVICE HidDevices,
  640. IN ULONG NumberDevices
  641. )
  642. {
  643. ULONG Index;
  644. for (Index = 0; Index < NumberDevices; Index++)
  645. {
  646. CloseHidDevice(HidDevices+Index);
  647. }
  648. return;
  649. }
  650. VOID
  651. CloseHidDevice (
  652. IN PHID_DEVICE HidDevice
  653. )
  654. {
  655. free(HidDevice -> DevicePath);
  656. if (INVALID_HANDLE_VALUE != HidDevice -> HidDevice)
  657. {
  658. CloseHandle(HidDevice -> HidDevice);
  659. HidDevice -> HidDevice = INVALID_HANDLE_VALUE;
  660. }
  661. if (NULL != HidDevice -> Ppd)
  662. {
  663. HidD_FreePreparsedData(HidDevice -> Ppd);
  664. HidDevice -> Ppd = NULL;
  665. }
  666. if (NULL != HidDevice -> InputReportBuffer)
  667. {
  668. free(HidDevice -> InputReportBuffer);
  669. HidDevice -> InputReportBuffer = NULL;
  670. }
  671. if (NULL != HidDevice -> InputData)
  672. {
  673. free(HidDevice -> InputData);
  674. HidDevice -> InputData = NULL;
  675. }
  676. if (NULL != HidDevice -> InputButtonCaps)
  677. {
  678. free(HidDevice -> InputButtonCaps);
  679. HidDevice -> InputButtonCaps = NULL;
  680. }
  681. if (NULL != HidDevice -> InputValueCaps)
  682. {
  683. free(HidDevice -> InputValueCaps);
  684. HidDevice -> InputValueCaps = NULL;
  685. }
  686. if (NULL != HidDevice -> OutputReportBuffer)
  687. {
  688. free(HidDevice -> OutputReportBuffer);
  689. HidDevice -> OutputReportBuffer = NULL;
  690. }
  691. if (NULL != HidDevice -> OutputData)
  692. {
  693. free(HidDevice -> OutputData);
  694. HidDevice -> OutputData = NULL;
  695. }
  696. if (NULL != HidDevice -> OutputButtonCaps)
  697. {
  698. free(HidDevice -> OutputButtonCaps);
  699. HidDevice -> OutputButtonCaps = NULL;
  700. }
  701. if (NULL != HidDevice -> OutputValueCaps)
  702. {
  703. free(HidDevice -> OutputValueCaps);
  704. HidDevice -> OutputValueCaps = NULL;
  705. }
  706. if (NULL != HidDevice -> FeatureReportBuffer)
  707. {
  708. free(HidDevice -> FeatureReportBuffer);
  709. HidDevice -> FeatureReportBuffer = NULL;
  710. }
  711. if (NULL != HidDevice -> FeatureData)
  712. {
  713. free(HidDevice -> FeatureData);
  714. HidDevice -> FeatureData = NULL;
  715. }
  716. if (NULL != HidDevice -> FeatureButtonCaps)
  717. {
  718. free(HidDevice -> FeatureButtonCaps);
  719. HidDevice -> FeatureButtonCaps = NULL;
  720. }
  721. if (NULL != HidDevice -> FeatureValueCaps)
  722. {
  723. free(HidDevice -> FeatureValueCaps);
  724. HidDevice -> FeatureValueCaps = NULL;
  725. }
  726. return;
  727. }