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.

4814 lines
148 KiB

  1. #define __HIDTEST_C__
  2. /*
  3. // This file contains the code used for performing different tests on the Hid
  4. // Devices. A Hid Device can be either a physical or logical device where
  5. // a physical device is considered a tangible object like a mouse or keyboard.
  6. // A logical device is simply Preparsed Data that has been generated from a
  7. // report descriptor (either manually created or captured from a physical
  8. // device. Therefore, the test APIs that apply to logical devices are more
  9. // limited since you cannot open a file object up for them.
  10. //
  11. // Since I've had problems trying to decide what my test structure will be for
  12. // using the NT logging functions, I will enumerate it here to hopefully avoid
  13. // confusion and/or refresh my own memory and a later time.
  14. //
  15. // TEST -- test api function -- for it to pass there must be no failures during
  16. // the test, beginning of api should have START_TEST()
  17. //
  18. // TEST ITERATION -- one iteration of the full test, one of API
  19. // user parameters is the # of iterations to perform
  20. // Beginning of each iteration loop should have
  21. // START_TEST_ITERATION() call
  22. //
  23. // VARIATION -- test is made up of a series of variations, a
  24. // variation is considered to be one check
  25. // of the validity of a test. This usually
  26. // tweaking one major parameter to the tested
  27. // function (ie. a different file object, or
  28. // invalid Preparsed data) These are the
  29. // most common variations that will be used
  30. //
  31. // INT_VAR_RESULT -- Abbreviated for INTERMEDIATE_VARIATION_RESULT
  32. // This is some sort of information that gets
  33. // logged about the current state of the variation
  34. // being performed. It uses the NT logging
  35. // type of TL_INFO. It's mainly used to generate
  36. // a little more information for a debugging case
  37. //
  38. // VARIATION_RESULT -- Actual result of a variation -- This is where
  39. // the variation is logged as either pass or
  40. // fail. A variation may fail due to a reason
  41. // that is specified by INT_VAR_RESULT but
  42. // the actual error code is set here.
  43. //
  44. // END_VARIATION -- Macro called to indicate the end of a variation
  45. //
  46. // END_TEST_ITERATION -- Macro called to signify the end of one particular
  47. // iteration of the test -- Another iteration should
  48. // perform the exact same variations with the
  49. // exact same conditions.
  50. //
  51. // END_TEST -- Macro called to indicate the end of the test
  52. // API -- No other information should be logged
  53. // at this point
  54. //
  55. // There are two other macros that do some sort of logging and have some sort
  56. // of meaning to the test suite. However, they do not relate to the general
  57. // test structure above although they may effect the operation of a test.
  58. //
  59. // WARNING -- Warning is used to indicate that something was
  60. // found that may be incorrect but is not something
  61. // that is the focus of the test API and therefore
  62. // is not flagged as a variation failure. An example
  63. // of a warning is a HID API returning the wrong
  64. // error code. Since the HID API that returned the
  65. // code was not the one that was being directly tested
  66. // but being used to validate the APIs currently
  67. // under test.
  68. //
  69. // TEST_ERROR -- Test error is something beyond our control which
  70. // will not let the test continue but is not due
  71. // to a variation failure. An example of a test
  72. // error is the failure of a memory allocation
  73. //
  74. // Hopefully, that will provide a little more info and add a tad more understanding
  75. // to the implementation below. Hopefully, I'll be able to go back to it
  76. // and keep me from getting confused.
  77. */
  78. /*****************************************************************************
  79. /* HidTest include files
  80. /*****************************************************************************/
  81. #include <windows.h>
  82. #include <stdlib.h>
  83. #include <wtypes.h>
  84. #include <limits.h>
  85. #include "hidsdi.h"
  86. #define USE_MACROS
  87. #include "list.h"
  88. #include "hidtest.h"
  89. #include "log.h"
  90. #include "handle.h"
  91. #include "buffer.h"
  92. #include "debug.h"
  93. /*
  94. // Include hidclass.h so we can get the HID_CLASS GUID value
  95. */
  96. #define INITGUID
  97. #include "hidclass.h"
  98. /*****************************************************************************
  99. /* Local macro definitions
  100. /*****************************************************************************/
  101. #define HIDTest_CompareAttributes(pa1, pa2) (((pa1) -> Size == (pa2) -> Size) && \
  102. ((pa1) -> VendorID == (pa2) -> VendorID) && \
  103. ((pa1) -> ProductID == (pa2) -> ProductID) && \
  104. ((pa1) -> VersionNumber == (pa2) -> VersionNumber))
  105. #define HIDTest_CompareStrings(s1, s1len, s2, s2len) (((s1len) == (s2len)) && \
  106. (0 == memcmp((s1), (s2), (s1len))))
  107. /*****************************************************************************
  108. /* Miscellaneous other definitions
  109. /*****************************************************************************/
  110. #define STRINGS_TO_TEST 0x100
  111. #define INIT_STR_LIST_SIZE 4
  112. #define STRING_INDEX_MANUFACTURER 0xFFFFFFFC
  113. #define STRING_INDEX_PRODUCT 0xFFFFFFFD
  114. #define STRING_INDEX_SERIAL_NUMBER 0xFFFFFFFE
  115. #define COMPARE_GUIDS(guid1, guid2) ((0 == memcmp(&(guid1), &(guid2), sizeof(GUID))))
  116. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  117. #define CURRENT_BUFFER_MIN 2
  118. #define RANDOM_BUFFER_VALUE 10
  119. /*****************************************************************************
  120. /* Module specific typedefs
  121. /*****************************************************************************/
  122. typedef struct _DataIndexList {
  123. ULONG MaxDataIndex;
  124. BOOL *List;
  125. } DATA_INDEX_LIST, *PDATA_INDEX_LIST;
  126. /*****************************************************************************
  127. /* DLL exportable variables with exportable function address
  128. /*****************************************************************************/
  129. PHIDTEST_API HIDTest_VerifyHidGuid;
  130. PHIDTEST_API HIDTest_VerifyStrings;
  131. PHIDTEST_API HIDTest_VerifyPreparsedData;
  132. PHIDTEST_API HIDTest_VerifyAttributes;
  133. PHIDTEST_API HIDTest_VerifyCapabilities;
  134. PCREATE_PHYSICAL_DEVICE_INFO_PROC HIDTest_CreatePhysicalDeviceInfo;
  135. PCREATE_LOGICAL_DEVICE_INFO_PROC HIDTest_CreateLogicalDeviceInfo;
  136. PCREATE_FREE_DEVICE_INFO_PROC HIDTest_FreeDeviceInfo;
  137. PCREATE_TEST_LOG_PROC HIDTest_CreateTestLog;
  138. PSET_LOG_ON_PROC HIDTest_SetLogOn;
  139. PCLOSE_TEST_LOG_PROC HIDTest_CloseTestLog;
  140. /*****************************************************************************
  141. /* Local function declarations
  142. /*****************************************************************************/
  143. BOOL
  144. HIDTest_FillCommonDeviceInfo(
  145. OUT PHIDTEST_DEVICEINFO DeviceInfo
  146. );
  147. BOOL
  148. HIDTest_FillValueCaps(
  149. IN HIDP_REPORT_TYPE ReportType,
  150. IN PHIDP_VALUE_CAPS *CapsBuffer,
  151. IN ULONG NumCaps,
  152. IN PHIDP_PREPARSED_DATA Ppd
  153. );
  154. BOOL
  155. HIDTest_FillButtonCaps(
  156. IN HIDP_REPORT_TYPE ReportType,
  157. IN PHIDP_BUTTON_CAPS *CapsBuffer,
  158. IN ULONG NumCaps,
  159. IN PHIDP_PREPARSED_DATA Ppd
  160. );
  161. BOOL
  162. HIDTest_DoGetFreePpd(
  163. IN HANDLE HidDevice
  164. );
  165. BOOL
  166. HIDTest_ValidateAttributes(
  167. IN HANDLE HidDevice,
  168. IN PHIDD_ATTRIBUTES Attrib
  169. );
  170. BOOL
  171. HIDTest_ValidateCaps(
  172. IN PHIDP_PREPARSED_DATA HidPpd,
  173. IN PHIDP_CAPS HidCaps
  174. );
  175. BOOL
  176. HIDTest_ValidateBufferValues(
  177. IN HIDP_REPORT_TYPE ReportType,
  178. IN USHORT NumButtonCaps,
  179. IN USHORT NumValueCaps,
  180. IN USHORT NumDataIndices,
  181. IN PHIDP_PREPARSED_DATA Ppd
  182. );
  183. BOOL
  184. HIDTest_ValidateNumInputBuffers(
  185. IN HANDLE HandleToTest,
  186. IN HANDLE SecondHandle,
  187. IN BOOL IsFirstHandleLegal,
  188. IN PULONG TestBuffer
  189. );
  190. BOOL
  191. HIDTest_GetBufferCount(
  192. IN HANDLE DeviceHandle,
  193. IN PULONG TestBuffer
  194. );
  195. BOOL
  196. HIDTest_ValidateStrings(
  197. HANDLE DeviceHandle,
  198. PLIST MasterList,
  199. IN ULONG ManufacturerStringIndex,
  200. IN ULONG ProductStringIndex,
  201. IN ULONG SerialNumberStringIndex
  202. );
  203. BOOL
  204. HIDTest_ValidateStdStrings(
  205. IN HANDLE DeviceHandle,
  206. IN PLIST CurrentStringList,
  207. IN ULONG ManufacturerStringIndex,
  208. IN ULONG ProductStringIndex,
  209. IN ULONG SerialNumberStringIndex
  210. );
  211. BOOL
  212. HIDTest_ValidateStringParams(
  213. IN HANDLE HidDevice,
  214. IN PLIST StringList,
  215. IN ULONG ManufacturerStringIndex,
  216. IN ULONG ProductStringIndex,
  217. IN ULONG SerialNumberStringIndex
  218. );
  219. BOOL
  220. HIDTest_ValidateStringIndexParams(
  221. IN HANDLE HidDevice,
  222. IN ULONG StringIndex,
  223. IN ULONG StringLength,
  224. IN PCHAR StringTypeDesc
  225. );
  226. BOOL
  227. HIDTest_CompareCaps(
  228. IN PHIDP_CAPS Caps1,
  229. IN PHIDP_CAPS Caps2
  230. );
  231. BOOL
  232. HIDTest_InitDataIndexList(
  233. IN ULONG MaxDataIndex,
  234. OUT PDATA_INDEX_LIST IndexList
  235. );
  236. VOID
  237. HIDTest_FreeDataIndexList(
  238. IN PDATA_INDEX_LIST IndexList
  239. );
  240. BOOL
  241. HIDTest_MarkDataIndex(
  242. IN PDATA_INDEX_LIST IndexList,
  243. IN ULONG IndexValue
  244. );
  245. BOOL
  246. HIDTest_GetDataIndexStatus(
  247. IN PDATA_INDEX_LIST IndexList,
  248. IN ULONG IndexValue
  249. );
  250. BOOL
  251. HIDTest_AreAllIndicesUsed(
  252. IN PDATA_INDEX_LIST IndexList
  253. );
  254. BOOL
  255. HIDTest_DoesStringExist(
  256. HANDLE DeviceHandle,
  257. ULONG StringIndex,
  258. PWCHAR *String,
  259. PULONG StringLength,
  260. BOOL *StringExists
  261. );
  262. BOOL
  263. HIDTest_GetWideStringLength(
  264. PWCHAR String,
  265. ULONG StringSize,
  266. PULONG StringLength
  267. );
  268. BOOL
  269. HIDTest_GetString(
  270. HANDLE DeviceHandle,
  271. ULONG StringIndex,
  272. PWCHAR StringBuffer,
  273. ULONG BufferLength,
  274. PULONG ErrorCode
  275. );
  276. BOOL
  277. HIDTest_BuildStringList(
  278. HANDLE DeviceHandle,
  279. PLIST StringList
  280. );
  281. VOID
  282. HIDTest_FreeStringList(
  283. PLIST StringList
  284. );
  285. VOID
  286. HIDTest_FreeStringNodeCallback(
  287. PLIST_NODE_HDR ListNode
  288. );
  289. BOOL
  290. HIDTest_AddStringToStringList(
  291. PLIST StringList,
  292. ULONG StringIndex,
  293. PWCHAR String,
  294. ULONG StringLength
  295. );
  296. BOOL
  297. HIDTest_IsStrIndexInStrList(
  298. PLIST StringList,
  299. ULONG StringIndex,
  300. PSTRING_LIST_NODE StringNode
  301. );
  302. BOOL
  303. HIDTest_IsStringInStrList(
  304. PLIST StringList,
  305. PWCHAR String,
  306. ULONG StringLength,
  307. PSTRING_LIST_NODE StringNode
  308. );
  309. BOOL
  310. HIDTest_CompareStringLists(
  311. PLIST StringList1,
  312. PLIST StringList2
  313. );
  314. VOID
  315. HIDTest_CallGetFeature(
  316. IN HANDLE DeviceHandle,
  317. IN UCHAR ReportID,
  318. IN PUCHAR ReportBuffer,
  319. IN ULONG ReportBufferLength,
  320. OUT PBOOL ReturnStatus,
  321. OUT PULONG ErrorCode,
  322. OUT PBOOL BufferStatus
  323. );
  324. VOID
  325. HIDTest_CallSetFeature(
  326. IN HANDLE DeviceHandle,
  327. IN UCHAR ReportID,
  328. IN PUCHAR ReportBuffer,
  329. IN ULONG ReportBufferLength,
  330. OUT PBOOL ReturnStatus,
  331. OUT PULONG ErrorCode,
  332. OUT PBOOL BufferStatus
  333. );
  334. BOOL
  335. HIDTest_BuildReportIDList(
  336. IN PHIDP_VALUE_CAPS VCaps,
  337. IN ULONG NumVCaps,
  338. IN PHIDP_BUTTON_CAPS BCaps,
  339. IN ULONG NumBCaps,
  340. IN PUCHAR *ReportIDs,
  341. IN PULONG ReportIDCount
  342. );
  343. VOID
  344. HIDTest_InsertIDIntoList(
  345. IN PUCHAR ReportIDs,
  346. IN PULONG ReportIDCount,
  347. IN UCHAR NewID
  348. );
  349. BOOL
  350. HIDTest_IsIDInList(
  351. IN UCHAR ReportID,
  352. IN PUCHAR ReportIDList,
  353. IN ULONG ReportIDListCount
  354. );
  355. /*****************************************************************************
  356. /* Exportable function definitions
  357. /*****************************************************************************/
  358. BOOLEAN __stdcall
  359. DllMain(
  360. HINSTANCE hinst,
  361. DWORD dwReason,
  362. LPVOID lpReserved
  363. )
  364. {
  365. switch (dwReason) {
  366. default: return TRUE;
  367. }
  368. }
  369. VOID
  370. HIDTest_InitExportAddress(
  371. PHIDTEST_FUNCTIONS Exports
  372. )
  373. {
  374. Exports -> HIDTest_VerifyHidGuid = &HIDTest_VerifyHidGuidA;
  375. Exports -> HIDTest_VerifyStrings = &HIDTest_VerifyStringsA;
  376. Exports -> HIDTest_VerifyPreparsedData = &HIDTest_VerifyPreparsedDataA;
  377. Exports -> HIDTest_VerifyAttributes = &HIDTest_VerifyAttributesA;
  378. Exports -> HIDTest_VerifyNumBuffers = &HIDTest_VerifyNumBuffersA;
  379. Exports -> HIDTest_VerifyCapabilities = &HIDTest_VerifyCapabilitiesA;
  380. Exports -> HIDTest_VerifyGetFeature = &HIDTest_VerifyGetFeatureA;
  381. Exports -> HIDTest_VerifySetFeature = &HIDTest_VerifySetFeatureA;
  382. Exports -> HIDTest_CreatePhysicalDeviceInfo = &HIDTest_CreatePhysicalDeviceInfoA;
  383. Exports -> HIDTest_CreateLogicalDeviceInfo = &HIDTest_CreateLogicalDeviceInfoA;
  384. Exports -> HIDTest_FreeDeviceInfo = &HIDTest_FreeDeviceInfoA;
  385. Exports -> HIDTest_CreateTestLog = &HIDTest_CreateTestLogA;
  386. Exports -> HIDTest_SetLogOn = &HIDTest_SetLogOnA;
  387. Exports -> HIDTest_CloseTestLog = &HIDTest_CloseTestLogA;
  388. return;
  389. }
  390. VOID
  391. HIDTest_VerifyHidGuidA(
  392. IN PHIDTEST_DEVICEINFO HidDevice,
  393. IN ULONG nIterations,
  394. OUT PHIDTEST_STATUS Status
  395. )
  396. {
  397. ULONG OperationCount;
  398. ULONG IterationCount;
  399. ULONG FailedCount;
  400. GUID *CallGuid;
  401. /*
  402. // Testing the HidD_GetHidGuid function is relatively simple. It consists of
  403. // one variation which calls HidD_GetHidGuid nIterations times and compares
  404. // the received guid with the standard hidclass guid.
  405. */
  406. OperationCount = 0;
  407. FailedCount = 0;
  408. START_TEST("HIDTest_HidD_GetHidGuid");
  409. CallGuid = (GUID *) AllocateTestBuffer(sizeof(GUID));
  410. if (NULL == CallGuid) {
  411. LOG_TEST_ERROR("Couldn't allocate memory");
  412. return;
  413. }
  414. for (IterationCount = 1; IterationCount <= nIterations; IterationCount++) {
  415. START_TEST_ITERATION(IterationCount);
  416. START_VARIATION("Validating the HID Class GUID");
  417. HidD_GetHidGuid(CallGuid);
  418. if (!ValidateTestBuffer(CallGuid)) {
  419. LOG_VARIATION_RESULT(TLS_SEV3, "Buffer violation");
  420. FailedCount++;
  421. }
  422. else if (!COMPARE_GUIDS(GUID_CLASS_INPUT, *CallGuid)) {
  423. LOG_VARIATION_FAIL();
  424. FailedCount++;
  425. }
  426. else {
  427. LOG_VARIATION_PASS();
  428. }
  429. OperationCount++;
  430. END_VARIATION();
  431. END_TEST_ITERATION();
  432. }
  433. END_TEST();
  434. FreeTestBuffer(CallGuid);
  435. Status -> nOperationsPerformed = OperationCount;
  436. Status -> nOperationsFailed = FailedCount;
  437. Status -> nOperationsPassed = OperationCount - FailedCount;
  438. return;
  439. }
  440. VOID
  441. HIDTest_VerifyPreparsedDataA(
  442. IN PHIDTEST_DEVICEINFO HidDevice,
  443. IN ULONG nIterations,
  444. OUT PHIDTEST_STATUS Status
  445. )
  446. {
  447. ULONG OperationCount;
  448. ULONG IterationCount;
  449. ULONG FailedCount;
  450. BOOL CallStatus;
  451. HANDLE CurrDeviceHandle;
  452. BOOL IsLegalDeviceHandle;
  453. static HANDLE HandleList[MAX_NUM_HANDLES];
  454. /*
  455. // This test is made up of a number of different variations depending on
  456. // the number of handles that will be used but the basic concept is the
  457. // following.
  458. //
  459. // 1) For each handle that we get from the handle generator
  460. // attempt to get preparsed data for that handle and compare
  461. // the results of the Get/Free status with what we should expect
  462. // to receive depending on the validity of the handle. The results
  463. // we expect to see is what we have stored for PreparsedData in the
  464. // HidDevice struct.
  465. //
  466. // 2) Also, if during the above iterations we encounter a legal handle
  467. // value, we will try to GetPreparsed data with a NULL value
  468. // passed in as the second paramters. The call should simply
  469. // fail.
  470. //
  471. // 3) After all is said and done, we attempt to free bogus buffers,
  472. // both NULL and the HandleList buffer. See comments below for
  473. // the reason, HandleList is to be freed.
  474. //
  475. // The above steps are all variations of the test, and the variations
  476. // must pass for nIterations in order for the variation to pass.
  477. // Each separate handle is also a variation. Basically,
  478. // there will be 2N + 1 variations where N is the number
  479. // of handles being tested.
  480. */
  481. START_TEST("HIDTest_VerifyPreparsedData");
  482. /*
  483. // Initialize the test statistics variables
  484. */
  485. FailedCount = 0;
  486. OperationCount = 0;
  487. /*
  488. // This test is made up of three variations, each of which is performs
  489. // the same operation nIterations number of times. To pass a variation
  490. // all iterations must pass.
  491. */
  492. /*
  493. // Begin by initializing the device handles that will be used for the test
  494. // A device handle list is built and passed into InitDeviceHandles.
  495. // Subsequent calls to GetDeviceHandle will return either one of the
  496. // handles that is specified in this list or another handle that the
  497. // "Handle Manager" has decided should be tested as well.
  498. */
  499. if (IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) {
  500. HandleList[0] = HidDevice -> HidDeviceHandle;
  501. ASSERT (NULL != HidDevice -> HidDeviceString);
  502. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  503. 2,
  504. 1,
  505. HandleList
  506. );
  507. }
  508. else {
  509. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  510. goto VERIFY_PPD_END;
  511. }
  512. /*
  513. // The testing of the preparsed data function involves attempting to get
  514. // and set the free preparsed data nIterations number of times for a
  515. // given device handle. If the device handle is not a legal one,
  516. // then the CallStatus should be FALSE instead of TRUE
  517. //
  518. */
  519. /*
  520. // Start the iteration loop
  521. */
  522. for (IterationCount = 1; IterationCount <= nIterations; IterationCount++) {
  523. START_TEST_ITERATION( IterationCount );
  524. HIDTest_ResetDeviceHandles();
  525. while (HIDTest_GetDeviceHandle(&CurrDeviceHandle, &IsLegalDeviceHandle)) {
  526. START_VARIATION_ON_DEVICE_HANDLE(CurrDeviceHandle,
  527. IsLegalDeviceHandle
  528. );
  529. /*
  530. // If the handle that is being tested is a valid one, then the
  531. // below call should return TRUE and FALSE otherwise. Therefore
  532. // we need only compare the return value with the IsLegalDeviceHandle
  533. // variable to determine if the call really failed or not.
  534. */
  535. CallStatus = HIDTest_DoGetFreePpd(CurrDeviceHandle);
  536. if (CallStatus != IsLegalDeviceHandle) {
  537. LOG_VARIATION_FAIL();
  538. FailedCount++;
  539. }
  540. else {
  541. LOG_VARIATION_PASS();
  542. }
  543. OperationCount++;
  544. END_VARIATION();
  545. }
  546. /*
  547. // Start another variation, this time, we attempt to free a block of
  548. // PREPARSED_DATA which is not actually a block of preparsed data
  549. */
  550. START_VARIATION("Attempting to free non-preparsed data block\n");
  551. /*
  552. // We'll pass in the address of the HandleList for three reasons
  553. // 1) If the function touches any part of this memory, it had better
  554. // be a valid address so we don't page fault
  555. // 2) If the function touches the memory, it should be big enough
  556. // for the same reason -- there's a good chance this will be
  557. // big enough.
  558. // 3) If he garbles any of the data, it's not going to kill our app
  559. // The list is defined static so that the procedure doesn't try
  560. // to free stack space either. Basically, if it does try to free
  561. // this memory block, we at least should be able to determine
  562. // that he freed the block instead of possibly having the OS go off
  563. // into la-la land and not knowing what happened.
  564. */
  565. CallStatus = HidD_FreePreparsedData((PHIDP_PREPARSED_DATA) (&HandleList));
  566. if (CallStatus) {
  567. FailedCount++;
  568. LOG_VARIATION_FAIL();
  569. }
  570. else {
  571. LOG_VARIATION_PASS();
  572. }
  573. OperationCount++;
  574. END_VARIATION();
  575. END_TEST_ITERATION();
  576. }
  577. HIDTest_CloseDeviceHandles();
  578. VERIFY_PPD_END:
  579. END_TEST();
  580. Status -> nOperationsPerformed = OperationCount;
  581. Status -> nOperationsPassed = OperationCount - FailedCount;
  582. Status -> nOperationsFailed = FailedCount;
  583. return;
  584. }
  585. VOID
  586. HIDTest_VerifyAttributesA(
  587. IN PHIDTEST_DEVICEINFO HidDevice,
  588. IN ULONG nIterations,
  589. OUT PHIDTEST_STATUS Status
  590. )
  591. {
  592. ULONG OperationCount;
  593. ULONG IterationCount;
  594. ULONG FailedCount;
  595. BOOL CallStatus;
  596. HANDLE HandleList[MAX_NUM_HANDLES];
  597. HANDLE CurrDeviceHandle;
  598. BOOL IsLegalDeviceHandle;
  599. FailedCount = 0;
  600. OperationCount = 0;
  601. START_TEST("HIDTest_VerifyAttributes");
  602. /*
  603. // Setup our device handle list but only if our initial device
  604. // handle is legitimate and we have HidDeviceAttributes. This should
  605. // weed out those danged logical devices that I'm currently hallucinating
  606. // we'll be implemented.
  607. */
  608. if ((IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) &&
  609. (NULL != HidDevice -> HidDeviceAttributes)) {
  610. HandleList[0] = HidDevice -> HidDeviceHandle;
  611. ASSERT (NULL != HidDevice -> HidDeviceString);
  612. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  613. 2,
  614. 1,
  615. HandleList
  616. );
  617. }
  618. else {
  619. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  620. goto VERIFY_ATTRIB_END;
  621. }
  622. /*
  623. // This test involves a variation for each of the different device handles
  624. // that is generated by our device handle generator. We will not test
  625. // with a NULL pointer to the attributes structure since the expected
  626. // behavior with such a pointer is to terminate the app.
  627. */
  628. for (IterationCount = 1; IterationCount <= nIterations; IterationCount++) {
  629. START_TEST_ITERATION( IterationCount );
  630. HIDTest_ResetDeviceHandles();
  631. while ( HIDTest_GetDeviceHandle( &CurrDeviceHandle, &IsLegalDeviceHandle )) {
  632. START_VARIATION_ON_DEVICE_HANDLE( CurrDeviceHandle,
  633. IsLegalDeviceHandle
  634. );
  635. CallStatus = HIDTest_ValidateAttributes( CurrDeviceHandle,
  636. HidDevice -> HidDeviceAttributes
  637. );
  638. if (CallStatus != IsLegalDeviceHandle) {
  639. LOG_VARIATION_FAIL();
  640. FailedCount++;
  641. }
  642. else {
  643. LOG_VARIATION_PASS();
  644. }
  645. OperationCount++;
  646. END_VARIATION();
  647. }
  648. END_TEST_ITERATION();
  649. }
  650. HIDTest_CloseDeviceHandles();
  651. VERIFY_ATTRIB_END:
  652. END_TEST();
  653. Status -> nOperationsPerformed = OperationCount;
  654. Status -> nOperationsPassed = OperationCount - FailedCount;
  655. Status -> nOperationsFailed = FailedCount;
  656. return;
  657. }
  658. VOID
  659. HIDTest_VerifyCapabilitiesA(
  660. IN PHIDTEST_DEVICEINFO HidDevice,
  661. IN ULONG nIterations,
  662. OUT PHIDTEST_STATUS Status
  663. )
  664. {
  665. HIDP_CAPS HidCaps;
  666. NTSTATUS CapsStatus;
  667. ULONG IterationCount;
  668. ULONG OperationCount;
  669. ULONG FailedCount;
  670. BOOL CallStatus;
  671. ULONG BadPpd[16];
  672. /*
  673. // This is a more straight forward piece of code. We're not going to
  674. // build a device list because we're not going to use the device handles.
  675. // In fact, we're just going to use the Ppd data structure to verify
  676. // everything. However, we will pass at least one bad Ppd structure
  677. // to verify that the signature checking works.
  678. */
  679. /*
  680. // What we need to do is call the verify routine with the preparsed data
  681. // for nIterations to verify that this stuff works all the time. Therefore
  682. // there exist only two varitions for this test. One with good preparsed
  683. // data on nIterations and another with bogus Ppd for nIterations
  684. */
  685. START_TEST("HIDTest_VerifyCapabilities");
  686. OperationCount = 0;
  687. FailedCount = 0;
  688. for (IterationCount = 0; IterationCount < nIterations; IterationCount++) {
  689. START_TEST_ITERATION(IterationCount);
  690. START_VARIATION("Validating Capabilities -- Good Ppd");
  691. CallStatus = HIDTest_ValidateCaps(HidDevice -> HidDevicePpd,
  692. HidDevice -> HidDeviceCaps
  693. );
  694. if (!CallStatus) {
  695. LOG_VARIATION_FAIL();
  696. FailedCount++;
  697. }
  698. else {
  699. LOG_VARIATION_PASS();
  700. }
  701. OperationCount++;
  702. END_VARIATION();
  703. /*
  704. // Let's do the same thing, only this time with bogus Ppd. To insure
  705. // that the correct error code is returned, we won't call
  706. // ValidateCaps but instead just call Hidp_GetCaps from here
  707. // to insure INVALID_PREPARSED_DATA is returned.
  708. */
  709. START_VARIATION("Validating Capabilities -- Bad Ppd");
  710. CapsStatus = HidP_GetCaps((PHIDP_PREPARSED_DATA) &BadPpd[0],
  711. &HidCaps
  712. );
  713. if (HIDP_STATUS_INVALID_PREPARSED_DATA != CapsStatus) {
  714. LOG_INTERMEDIATE_VARIATION_RESULT("Unexpected error code returned");
  715. LOG_VARIATION_FAIL();
  716. FailedCount++;
  717. }
  718. else {
  719. LOG_VARIATION_PASS();
  720. }
  721. OperationCount++;
  722. END_VARIATION();
  723. END_TEST_ITERATION();
  724. }
  725. END_TEST();
  726. Status -> nOperationsPerformed = OperationCount;
  727. Status -> nOperationsPassed = OperationCount - FailedCount;
  728. Status -> nOperationsFailed = FailedCount;
  729. return;
  730. }
  731. VOID
  732. HIDTest_VerifyStringsA(
  733. IN PHIDTEST_DEVICEINFO HidDevice,
  734. IN ULONG nIterations,
  735. OUT PHIDTEST_STATUS Status
  736. )
  737. {
  738. ULONG IterationCount;
  739. ULONG OperationCount;
  740. ULONG FailedCount;
  741. HANDLE HandleList[MAX_NUM_HANDLES];
  742. HANDLE CurrDeviceHandle;
  743. BOOL IsLegalDeviceHandle;
  744. BOOL CallStatus;
  745. START_TEST("HIDTest_VerifyStrings");
  746. OperationCount = 0;
  747. FailedCount = 0;
  748. /*
  749. // Attempt to setup the device handle list, if the current
  750. // HidDeviceHandle is not valid than we cannot proceed any farther
  751. */
  752. if (IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) {
  753. HandleList[0] = HidDevice -> HidDeviceHandle;
  754. ASSERT (NULL != HidDevice -> HidDeviceString);
  755. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  756. 2,
  757. 1,
  758. HandleList
  759. );
  760. }
  761. else {
  762. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  763. goto VERIFY_STRINGS_END;
  764. }
  765. /*
  766. // Start the iterations of the string test
  767. */
  768. for (IterationCount = 1; IterationCount <= nIterations; IterationCount++) {
  769. START_TEST_ITERATION(IterationCount);
  770. HIDTest_ResetDeviceHandles();
  771. while ( HIDTest_GetDeviceHandle( &CurrDeviceHandle, &IsLegalDeviceHandle )) {
  772. START_VARIATION_ON_DEVICE_HANDLE( CurrDeviceHandle,
  773. IsLegalDeviceHandle
  774. );
  775. CallStatus = HIDTest_ValidateStrings( CurrDeviceHandle,
  776. &HidDevice -> StringList,
  777. HidDevice -> ManufacturerStringIndex,
  778. HidDevice -> ProductStringIndex,
  779. HidDevice -> SerialNumberStringIndex
  780. );
  781. if (CallStatus != IsLegalDeviceHandle) {
  782. LOG_VARIATION_FAIL();
  783. FailedCount++;
  784. }
  785. else {
  786. LOG_VARIATION_PASS();
  787. }
  788. OperationCount++;
  789. END_VARIATION();
  790. }
  791. START_VARIATION("Testing the HidD_ string parameter validation");
  792. CallStatus = HIDTest_ValidateStringParams( HidDevice -> HidDeviceHandle,
  793. &HidDevice -> StringList,
  794. HidDevice -> ManufacturerStringIndex,
  795. HidDevice -> ProductStringIndex,
  796. HidDevice -> SerialNumberStringIndex
  797. );
  798. if (!CallStatus) {
  799. LOG_VARIATION_FAIL();
  800. FailedCount++;
  801. }
  802. else {
  803. LOG_VARIATION_PASS();
  804. }
  805. OperationCount++;
  806. END_TEST_ITERATION();
  807. }
  808. HIDTest_CloseDeviceHandles();
  809. VERIFY_STRINGS_END:
  810. END_TEST();
  811. Status -> nOperationsPerformed = OperationCount;
  812. Status -> nOperationsPassed = OperationCount - FailedCount;
  813. Status -> nOperationsFailed = FailedCount;
  814. return;
  815. }
  816. VOID
  817. HIDTest_VerifyNumBuffersA(
  818. IN PHIDTEST_DEVICEINFO HidDevice,
  819. IN ULONG nIterations,
  820. OUT PHIDTEST_STATUS Status
  821. )
  822. {
  823. ULONG iterationCount;
  824. ULONG operationCount;
  825. ULONG failedCount;
  826. PULONG bufCount;
  827. HANDLE secondHandle;
  828. HANDLE handleList[MAX_NUM_HANDLES];
  829. HANDLE currDeviceHandle;
  830. BOOL isLegalDeviceHandle;
  831. BOOL callStatus;
  832. START_TEST("HIDTest_VerifyNumInputBuffers");
  833. operationCount = 0;
  834. failedCount = 0;
  835. bufCount = NULL;
  836. secondHandle = CreateFile( HidDevice -> HidDeviceString,
  837. GENERIC_READ | GENERIC_WRITE,
  838. FILE_SHARE_READ | FILE_SHARE_WRITE,
  839. NULL,
  840. OPEN_EXISTING,
  841. 0,
  842. NULL
  843. );
  844. if (INVALID_HANDLE_VALUE == secondHandle) {
  845. LOG_TEST_ERROR("Couldn't open second handle to HID device");
  846. goto VERIFY_NUMBUFFERS_END;
  847. }
  848. bufCount = (PULONG) AllocateTestBuffer(sizeof(ULONG));
  849. if (NULL == bufCount) {
  850. LOG_TEST_ERROR( "Couldn't allocate memory" );
  851. goto VERIFY_NUMBUFFERS_END;
  852. }
  853. /*
  854. // Attempt to setup the device handle list, if the current
  855. // HidDeviceHandle is not valid than we cannot proceed any farther
  856. */
  857. if (IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) {
  858. handleList[0] = HidDevice -> HidDeviceHandle;
  859. ASSERT (NULL != HidDevice -> HidDeviceString);
  860. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  861. 2,
  862. 1,
  863. handleList
  864. );
  865. }
  866. else {
  867. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  868. goto VERIFY_NUMBUFFERS_END;
  869. }
  870. for (iterationCount = 1; iterationCount <= nIterations; iterationCount++) {
  871. START_TEST_ITERATION(iterationCount);
  872. HIDTest_ResetDeviceHandles();
  873. while ( HIDTest_GetDeviceHandle( &currDeviceHandle, &isLegalDeviceHandle )) {
  874. START_VARIATION_ON_DEVICE_HANDLE( currDeviceHandle,
  875. isLegalDeviceHandle
  876. );
  877. callStatus = HIDTest_ValidateNumInputBuffers( currDeviceHandle,
  878. secondHandle,
  879. isLegalDeviceHandle,
  880. bufCount
  881. );
  882. if (!callStatus) {
  883. LOG_VARIATION_FAIL();
  884. failedCount++;
  885. }
  886. else {
  887. LOG_VARIATION_PASS();
  888. }
  889. operationCount++;
  890. END_VARIATION();
  891. }
  892. }
  893. VERIFY_NUMBUFFERS_END:
  894. END_TEST();
  895. if (NULL != bufCount) {
  896. FreeTestBuffer(bufCount);
  897. }
  898. if (INVALID_HANDLE_VALUE != secondHandle) {
  899. CloseHandle(secondHandle);
  900. }
  901. Status -> nOperationsPerformed = operationCount;
  902. Status -> nOperationsPassed = operationCount - failedCount;
  903. Status -> nOperationsFailed = failedCount;
  904. return;
  905. }
  906. VOID
  907. HIDTest_VerifyGetFeatureA(
  908. IN PHIDTEST_DEVICEINFO HidDevice,
  909. IN ULONG nIterations,
  910. OUT PHIDTEST_STATUS Status
  911. )
  912. {
  913. ULONG iterationCount;
  914. ULONG operationCount;
  915. ULONG failedCount;
  916. PCHAR featureBuffer;
  917. ULONG featureBufferLength;
  918. HANDLE handleList[MAX_NUM_HANDLES];
  919. HANDLE currDeviceHandle;
  920. BOOL isLegalDeviceHandle;
  921. BOOL returnStatus;
  922. BOOL bufferStatus;
  923. ULONG errorCode;
  924. PUCHAR reportIDList;
  925. ULONG reportIDListCount;
  926. ULONG idIndex;
  927. UCHAR reportID;
  928. BOOL variationStatus;
  929. ULONG reportBufferSize;
  930. static CHAR varString[128];
  931. START_TEST("HIDTest_VerifyGetFeature");
  932. operationCount = 0;
  933. failedCount = 0;
  934. /*
  935. // If we have no features on the device, we still want to allocate
  936. // a buffer of two bytes just to verify that FALSE and the correct
  937. // error code is returned when we call HidD_GetFeature;
  938. */
  939. if (0 == HidDevice -> HidDeviceCaps -> FeatureReportByteLength) {
  940. featureBufferLength = 2;
  941. }
  942. else {
  943. featureBufferLength = HidDevice -> HidDeviceCaps -> FeatureReportByteLength;
  944. }
  945. featureBuffer = (PCHAR) AllocateTestBuffer(featureBufferLength);
  946. if (NULL == featureBuffer) {
  947. LOG_TEST_ERROR( "Couldn't allocate memory" );
  948. goto VERIFY_GETFEATURE_END;
  949. }
  950. /*
  951. // Build the list or reportIDs that are supported
  952. */
  953. returnStatus = HIDTest_BuildReportIDList( HidDevice -> HidFeatureValueCaps,
  954. HidDevice -> HidDeviceCaps -> NumberFeatureValueCaps,
  955. HidDevice -> HidFeatureButtonCaps,
  956. HidDevice -> HidDeviceCaps -> NumberFeatureButtonCaps,
  957. &reportIDList,
  958. &reportIDListCount
  959. );
  960. if (!returnStatus) {
  961. LOG_TEST_ERROR("Error building report ID list");
  962. goto VERIFY_GETFEATURE_END;
  963. }
  964. /*
  965. // Attempt to setup the device handle list, if the current
  966. // HidDeviceHandle is not valid than we cannot proceed any farther
  967. */
  968. if (IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) {
  969. handleList[0] = HidDevice -> HidDeviceHandle;
  970. ASSERT (NULL != HidDevice -> HidDeviceString);
  971. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  972. 2,
  973. 1,
  974. handleList
  975. );
  976. }
  977. else {
  978. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  979. goto VERIFY_GETFEATURE_END;
  980. }
  981. for (iterationCount = 1; iterationCount <= nIterations; iterationCount++) {
  982. START_TEST_ITERATION(iterationCount);
  983. HIDTest_ResetDeviceHandles();
  984. while ( HIDTest_GetDeviceHandle( &currDeviceHandle, &isLegalDeviceHandle )) {
  985. /*
  986. // Begin by testing that we can retrieve feature reports for
  987. // all the IDs supported on the device. For this part to
  988. // pass:
  989. //
  990. // 1) returnStatus should be TRUE
  991. // 2) errorCode should be ERROR_SUCCESS
  992. // 3) bufferStatus should be TRUE (ie. no buffer overrun problems
  993. //
  994. //
  995. // Of course, that would only happen if currDeviceHandle were
  996. // actually a legal handle...If current device handle is not
  997. // a legal handle, we would need to look for the following:
  998. //
  999. // 1) returnStatus = FALSE
  1000. // 2) errorCode = ERROR_INVALID_HANDLE (?)
  1001. // 3) bufferStatus = TRUE
  1002. */
  1003. START_VARIATION_WITH_DEVICE_HANDLE( currDeviceHandle,
  1004. isLegalDeviceHandle,
  1005. "Getting all feature reports"
  1006. );
  1007. variationStatus = TRUE;
  1008. for (idIndex = 0; idIndex < reportIDListCount; idIndex++) {
  1009. HIDTest_CallGetFeature( currDeviceHandle,
  1010. *(reportIDList + idIndex),
  1011. featureBuffer,
  1012. featureBufferLength,
  1013. &returnStatus,
  1014. &errorCode,
  1015. &bufferStatus
  1016. );
  1017. if (!bufferStatus) {
  1018. LOG_BUFFER_VALIDATION_FAIL();
  1019. variationStatus = FALSE;
  1020. }
  1021. else if (isLegalDeviceHandle) {
  1022. if (!returnStatus) {
  1023. LOG_INVALID_RETURN_STATUS();
  1024. variationStatus = FALSE;
  1025. }
  1026. else {
  1027. if (ERROR_SUCCESS != errorCode) {
  1028. LOG_INVALID_ERROR_CODE();
  1029. variationStatus = FALSE;
  1030. }
  1031. }
  1032. }
  1033. else {
  1034. if (returnStatus) {
  1035. LOG_INVALID_RETURN_STATUS();
  1036. variationStatus = FALSE;
  1037. }
  1038. else {
  1039. if (ERROR_INVALID_HANDLE != errorCode) {
  1040. LOG_INVALID_ERROR_CODE();
  1041. variationStatus = FALSE;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. if (variationStatus) {
  1047. LOG_VARIATION_PASS();
  1048. }
  1049. else {
  1050. LOG_VARIATION_FAIL();
  1051. failedCount++;
  1052. }
  1053. operationCount++;
  1054. END_VARIATION();
  1055. /*
  1056. // Now let's choose some report IDs that aren't in the list
  1057. // and make sure the appropriate results come back to us from
  1058. // ValidateGetFeature. Appropriate results are:
  1059. //
  1060. // if IsLegalDeviceHandle
  1061. // 1) returnStatus = FALSE
  1062. // 2) errorCode = ERROR_CRC
  1063. // 3) bufferStatus = TRUE;
  1064. //
  1065. // otherwise,
  1066. // 1) returnStatus = FALSE
  1067. // 2) errorCode = ERROR_INVALID_HANDLE
  1068. // 3) bufferStatus = TRUE;
  1069. //
  1070. // We will use the following report IDs as possible ReportID values
  1071. // to try. If any one of these report IDs is already in the list
  1072. // we'll skip it and move on to the next one.
  1073. //
  1074. // 0, 1, 2, 127, 128, 129, 254, 255
  1075. //
  1076. */
  1077. #define BAD_REPORT_ID_LIST_COUNT 8
  1078. START_VARIATION_WITH_DEVICE_HANDLE( currDeviceHandle,
  1079. isLegalDeviceHandle,
  1080. "Attempting to retrieve non-existent report"
  1081. );
  1082. variationStatus = TRUE;
  1083. for (idIndex = 0; idIndex < BAD_REPORT_ID_LIST_COUNT; idIndex++) {
  1084. UCHAR BadReportIDList[BAD_REPORT_ID_LIST_COUNT] = { 0, 1, 127, 128, 129, 254, 255 };
  1085. if (!HIDTest_IsIDInList(BadReportIDList[idIndex],
  1086. reportIDList,
  1087. reportIDListCount
  1088. )) {
  1089. HIDTest_CallGetFeature( currDeviceHandle,
  1090. BadReportIDList[idIndex],
  1091. featureBuffer,
  1092. featureBufferLength,
  1093. &returnStatus,
  1094. &errorCode,
  1095. &bufferStatus
  1096. );
  1097. if (!bufferStatus) {
  1098. LOG_BUFFER_VALIDATION_FAIL();
  1099. variationStatus = FALSE;
  1100. }
  1101. else if (isLegalDeviceHandle) {
  1102. if (returnStatus) {
  1103. LOG_INVALID_RETURN_STATUS();
  1104. variationStatus = FALSE;
  1105. }
  1106. else {
  1107. if (ERROR_CRC != errorCode &&
  1108. ERROR_INVALID_FUNCTION != errorCode) {
  1109. LOG_INVALID_ERROR_CODE();
  1110. variationStatus = FALSE;
  1111. }
  1112. }
  1113. }
  1114. else {
  1115. if (returnStatus) {
  1116. LOG_INVALID_RETURN_STATUS();
  1117. variationStatus = FALSE;
  1118. }
  1119. else {
  1120. if (ERROR_INVALID_HANDLE != errorCode) {
  1121. LOG_INVALID_ERROR_CODE();
  1122. variationStatus = FALSE;
  1123. }
  1124. }
  1125. }
  1126. }
  1127. }
  1128. if (variationStatus) {
  1129. LOG_VARIATION_PASS();
  1130. }
  1131. else {
  1132. LOG_VARIATION_FAIL();
  1133. failedCount++;
  1134. }
  1135. operationCount++;
  1136. END_VARIATION();
  1137. /*
  1138. // The next step in the validation process is to pass in buffers
  1139. // that are too small to hold an entire feature report. The same
  1140. // feature buffer will be used but we'll pass in a different size
  1141. // to the ValidateFeature routine. The appropriate response to
  1142. // this call should be:
  1143. //
  1144. // 1) returnStatus = FALSE;
  1145. // 2) errorCode = ERROR_INVALID_PARAMETER (?)
  1146. // 3) bufferStatus = TRUE
  1147. //
  1148. // As above, we'll do this with two different report IDs, one
  1149. // valid one and one invalid one (if the invalid one exists) to
  1150. // make sure we hit as many possible code paths.
  1151. // Also three different lengths of buffers will be used, 1, 2,
  1152. // and featurelength-1
  1153. */
  1154. START_VARIATION("Passing in buffers that are too small");
  1155. variationStatus = TRUE;
  1156. reportID = 0;
  1157. do {
  1158. if (!HIDTest_IsIDInList(reportID,
  1159. reportIDList,
  1160. reportIDListCount
  1161. )) {
  1162. /*
  1163. // Perform the validation steps here for each of the report
  1164. // buffer sizes
  1165. */
  1166. reportBufferSize = 1;
  1167. while (1) {
  1168. wsprintf(varString, "ReportBufferSize = %d", reportBufferSize);
  1169. LOG_INTERMEDIATE_VARIATION_RESULT(varString);
  1170. HIDTest_CallGetFeature( currDeviceHandle,
  1171. reportID,
  1172. featureBuffer,
  1173. reportBufferSize,
  1174. &returnStatus,
  1175. &errorCode,
  1176. &bufferStatus
  1177. );
  1178. if (!bufferStatus) {
  1179. LOG_BUFFER_VALIDATION_FAIL();
  1180. variationStatus = FALSE;
  1181. }
  1182. else if (returnStatus) {
  1183. LOG_INVALID_RETURN_STATUS();
  1184. variationStatus = FALSE;
  1185. }
  1186. else if (isLegalDeviceHandle) {
  1187. if (ERROR_CRC != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1188. LOG_INVALID_ERROR_CODE();
  1189. variationStatus = FALSE;
  1190. }
  1191. }
  1192. else if (ERROR_INVALID_HANDLE != errorCode) {
  1193. LOG_INVALID_ERROR_CODE();
  1194. variationStatus = FALSE;
  1195. }
  1196. /*
  1197. // Determine the next buffer length...The buffer lengths
  1198. // that are to be used are 1,2, and featureBufferLength-1
  1199. // unless some of those happen to be the same size
  1200. */
  1201. reportBufferSize++;
  1202. if (reportBufferSize == featureBufferLength) {
  1203. break;
  1204. }
  1205. else if (reportBufferSize > 2) {
  1206. reportBufferSize = featureBufferLength-1;
  1207. }
  1208. }
  1209. if (0 != reportID) {
  1210. break;
  1211. }
  1212. }
  1213. } while (reportID++ != 255);
  1214. }
  1215. if (variationStatus) {
  1216. LOG_VARIATION_PASS();
  1217. }
  1218. else {
  1219. LOG_VARIATION_FAIL();
  1220. failedCount++;
  1221. }
  1222. operationCount++;
  1223. END_VARIATION();
  1224. }
  1225. /*
  1226. // Do parameter validation now...Pass in the following three cases and
  1227. // verify correct operation
  1228. //
  1229. // 1) NULL buffer -- Length of 0,
  1230. // 2) NULL buffer -- Length != 0
  1231. // 3) non-NULL buffer -- length of 0
  1232. //
  1233. // Since we're verifying parameters, the actual reportID we use shouldn't
  1234. // matter, so we'll just use 1. Since we're not actually using test buffers
  1235. // we may not do any checking there either.
  1236. */
  1237. START_VARIATION("Parameter validation of GetFeature");
  1238. variationStatus = TRUE;
  1239. LOG_INTERMEDIATE_VARIATION_RESULT("Using NULL buffer with 0 length");
  1240. HIDTest_CallGetFeature( HidDevice -> HidDeviceHandle,
  1241. 1,
  1242. NULL,
  1243. 0,
  1244. &returnStatus,
  1245. &errorCode,
  1246. NULL
  1247. );
  1248. if (returnStatus) {
  1249. LOG_INVALID_RETURN_STATUS();
  1250. variationStatus = FALSE;
  1251. failedCount++;
  1252. }
  1253. else if (ERROR_INVALID_USER_BUFFER != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1254. LOG_INVALID_ERROR_CODE();
  1255. variationStatus = FALSE;
  1256. }
  1257. LOG_INTERMEDIATE_VARIATION_RESULT("Using NULL buffer with non-zero length");
  1258. HIDTest_CallGetFeature (HidDevice -> HidDeviceHandle,
  1259. 1,
  1260. NULL,
  1261. 3,
  1262. &returnStatus,
  1263. &errorCode,
  1264. NULL
  1265. );
  1266. if (returnStatus) {
  1267. LOG_INVALID_RETURN_STATUS();
  1268. variationStatus = FALSE;
  1269. }
  1270. else if (ERROR_NOACCESS != errorCode) {
  1271. LOG_INVALID_RETURN_STATUS();
  1272. variationStatus = FALSE;
  1273. }
  1274. LOG_INTERMEDIATE_VARIATION_RESULT("Using non-NULL buffer with zero length");
  1275. HIDTest_CallGetFeature (HidDevice -> HidDeviceHandle,
  1276. 1,
  1277. featureBuffer,
  1278. 0,
  1279. &returnStatus,
  1280. &errorCode,
  1281. &bufferStatus
  1282. );
  1283. if (!bufferStatus) {
  1284. LOG_BUFFER_VALIDATION_FAIL();
  1285. variationStatus = FALSE;
  1286. }
  1287. else if (returnStatus) {
  1288. LOG_INVALID_RETURN_STATUS();
  1289. variationStatus = FALSE;
  1290. }
  1291. else if (ERROR_INVALID_USER_BUFFER != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1292. LOG_INVALID_ERROR_CODE();
  1293. variationStatus = FALSE;
  1294. }
  1295. if (variationStatus) {
  1296. LOG_VARIATION_PASS();
  1297. }
  1298. else {
  1299. LOG_VARIATION_FAIL();
  1300. failedCount++;
  1301. }
  1302. operationCount++;
  1303. END_VARIATION();
  1304. VERIFY_GETFEATURE_END:
  1305. END_TEST();
  1306. if (NULL != featureBuffer) {
  1307. FreeTestBuffer(featureBuffer);
  1308. }
  1309. Status -> nOperationsPerformed = operationCount;
  1310. Status -> nOperationsPassed = operationCount - failedCount;
  1311. Status -> nOperationsFailed = failedCount;
  1312. return;
  1313. }
  1314. VOID
  1315. HIDTest_CallGetFeature(
  1316. IN HANDLE DeviceHandle,
  1317. IN UCHAR ReportID,
  1318. IN PUCHAR ReportBuffer,
  1319. IN ULONG ReportBufferLength,
  1320. OUT PBOOL ReturnStatus,
  1321. OUT PULONG ErrorCode,
  1322. OUT PBOOL BufferStatus
  1323. )
  1324. {
  1325. /*
  1326. // If we have a non-null buffer of > 0 length, then allocate the
  1327. // zero the memory and add the reportID as the first byte.
  1328. */
  1329. if (NULL != ReportBuffer && ReportBufferLength > 0) {
  1330. ZeroMemory (ReportBuffer, ReportBufferLength);
  1331. *ReportBuffer = ReportID;
  1332. }
  1333. /*
  1334. // Call GetFeature
  1335. */
  1336. *ReturnStatus = HidD_GetFeature(DeviceHandle,
  1337. ReportBuffer,
  1338. ReportBufferLength
  1339. );
  1340. /*
  1341. // Get the error code returned
  1342. */
  1343. *ErrorCode = GetLastError();
  1344. /*
  1345. // Do a buffer validation check
  1346. */
  1347. if (NULL != BufferStatus) {
  1348. *BufferStatus = ValidateTestBuffer(ReportBuffer);
  1349. }
  1350. return;
  1351. }
  1352. VOID
  1353. HIDTest_VerifySetFeatureA(
  1354. IN PHIDTEST_DEVICEINFO HidDevice,
  1355. IN ULONG nIterations,
  1356. OUT PHIDTEST_STATUS Status
  1357. )
  1358. {
  1359. ULONG iterationCount;
  1360. ULONG operationCount;
  1361. ULONG failedCount;
  1362. PCHAR featureBuffer;
  1363. ULONG featureBufferLength;
  1364. HANDLE handleList[MAX_NUM_HANDLES];
  1365. HANDLE currDeviceHandle;
  1366. BOOL isLegalDeviceHandle;
  1367. BOOL returnStatus;
  1368. BOOL bufferStatus;
  1369. ULONG errorCode;
  1370. PUCHAR reportIDList;
  1371. ULONG reportIDListCount;
  1372. ULONG idIndex;
  1373. UCHAR reportID;
  1374. BOOL variationStatus;
  1375. ULONG reportBufferSize;
  1376. static CHAR varString[128];
  1377. START_TEST("HIDTest_VerifySetFeature");
  1378. operationCount = 0;
  1379. failedCount = 0;
  1380. /*
  1381. // If we have no features on the device, we still want to allocate
  1382. // a buffer of two bytes just to verify that FALSE and the correct
  1383. // error code is returned when we call HidD_GetFeature;
  1384. */
  1385. if (0 == HidDevice -> HidDeviceCaps -> FeatureReportByteLength) {
  1386. featureBufferLength = 2;
  1387. }
  1388. else {
  1389. featureBufferLength = HidDevice -> HidDeviceCaps -> FeatureReportByteLength;
  1390. }
  1391. featureBuffer = (PCHAR) AllocateTestBuffer(featureBufferLength);
  1392. if (NULL == featureBuffer) {
  1393. LOG_TEST_ERROR( "Couldn't allocate memory" );
  1394. goto VERIFY_SETFEATURE_END;
  1395. }
  1396. /*
  1397. // Build the list or reportIDs that are supported
  1398. */
  1399. returnStatus = HIDTest_BuildReportIDList( HidDevice -> HidFeatureValueCaps,
  1400. HidDevice -> HidDeviceCaps -> NumberFeatureValueCaps,
  1401. HidDevice -> HidFeatureButtonCaps,
  1402. HidDevice -> HidDeviceCaps -> NumberFeatureButtonCaps,
  1403. &reportIDList,
  1404. &reportIDListCount
  1405. );
  1406. if (!returnStatus) {
  1407. LOG_TEST_ERROR("Error building report ID list");
  1408. goto VERIFY_SETFEATURE_END;
  1409. }
  1410. /*
  1411. // Attempt to setup the device handle list, if the current
  1412. // HidDeviceHandle is not valid than we cannot proceed any farther
  1413. */
  1414. if (IS_VALID_DEVICE_HANDLE(HidDevice -> HidDeviceHandle)) {
  1415. handleList[0] = HidDevice -> HidDeviceHandle;
  1416. ASSERT (NULL != HidDevice -> HidDeviceString);
  1417. HIDTest_InitDeviceHandles(HidDevice -> HidDeviceString,
  1418. 2,
  1419. 1,
  1420. handleList
  1421. );
  1422. }
  1423. else {
  1424. LOG_TEST_ERROR("HidDevice Handle is invalid -- cannot perform test");
  1425. goto VERIFY_SETFEATURE_END;
  1426. }
  1427. for (iterationCount = 1; iterationCount <= nIterations; iterationCount++) {
  1428. START_TEST_ITERATION(iterationCount);
  1429. HIDTest_ResetDeviceHandles();
  1430. while ( HIDTest_GetDeviceHandle( &currDeviceHandle, &isLegalDeviceHandle )) {
  1431. /*
  1432. // Begin by testing that we can set feature reports for
  1433. // all the IDs supported on the device. For this part to
  1434. // pass:
  1435. //
  1436. // 1) returnStatus should be TRUE
  1437. // 2) errorCode should be ERROR_SUCCESS
  1438. // 3) bufferStatus should be TRUE (ie. no buffer overrun problems
  1439. //
  1440. //
  1441. // Of course, that would only happen if currDeviceHandle were
  1442. // actually a legal handle...If current device handle is not
  1443. // a legal handle, we would need to look for the following:
  1444. //
  1445. // 1) returnStatus = FALSE
  1446. // 2) errorCode = ERROR_INVALID_HANDLE (?)
  1447. // 3) bufferStatus = TRUE
  1448. */
  1449. START_VARIATION_WITH_DEVICE_HANDLE( currDeviceHandle,
  1450. isLegalDeviceHandle,
  1451. "Setting all feature reports"
  1452. );
  1453. variationStatus = TRUE;
  1454. for (idIndex = 0; idIndex < reportIDListCount; idIndex++) {
  1455. HIDTest_CallSetFeature( currDeviceHandle,
  1456. *(reportIDList + idIndex),
  1457. featureBuffer,
  1458. featureBufferLength,
  1459. &returnStatus,
  1460. &errorCode,
  1461. &bufferStatus
  1462. );
  1463. if (!bufferStatus) {
  1464. LOG_BUFFER_VALIDATION_FAIL();
  1465. variationStatus = FALSE;
  1466. }
  1467. else if (isLegalDeviceHandle) {
  1468. if (!returnStatus) {
  1469. LOG_INVALID_RETURN_STATUS();
  1470. variationStatus = FALSE;
  1471. }
  1472. else {
  1473. if (ERROR_SUCCESS != errorCode) {
  1474. LOG_INVALID_ERROR_CODE();
  1475. variationStatus = FALSE;
  1476. }
  1477. }
  1478. }
  1479. else {
  1480. if (returnStatus) {
  1481. LOG_INVALID_RETURN_STATUS();
  1482. variationStatus = FALSE;
  1483. }
  1484. else {
  1485. if (ERROR_INVALID_HANDLE != errorCode) {
  1486. LOG_INVALID_ERROR_CODE();
  1487. variationStatus = FALSE;
  1488. }
  1489. }
  1490. }
  1491. }
  1492. if (variationStatus) {
  1493. LOG_VARIATION_PASS();
  1494. }
  1495. else {
  1496. LOG_VARIATION_FAIL();
  1497. failedCount++;
  1498. }
  1499. operationCount++;
  1500. END_VARIATION();
  1501. /*
  1502. // Now let's choose some report IDs that aren't in the list
  1503. // and make sure the appropriate results come back to us from
  1504. // CallSetFeature. Appropriate results are:
  1505. //
  1506. // if IsLegalDeviceHandle
  1507. // 1) returnStatus = FALSE
  1508. // 2) errorCode = ERROR_CRC
  1509. // 3) bufferStatus = TRUE;
  1510. //
  1511. // otherwise,
  1512. // 1) returnStatus = FALSE
  1513. // 2) errorCode = ERROR_INVALID_HANDLE
  1514. // 3) bufferStatus = TRUE;
  1515. //
  1516. // We will use the following report IDs as possible ReportID values
  1517. // to try. If any one of these report IDs is already in the list
  1518. // we'll skip it and move on to the next one.
  1519. //
  1520. // 0, 1, 2, 127, 128, 129, 254, 255
  1521. //
  1522. */
  1523. #define BAD_REPORT_ID_LIST_COUNT 8
  1524. START_VARIATION_WITH_DEVICE_HANDLE( currDeviceHandle,
  1525. isLegalDeviceHandle,
  1526. "Attempting to set non-existent report"
  1527. );
  1528. variationStatus = TRUE;
  1529. for (idIndex = 0; idIndex < BAD_REPORT_ID_LIST_COUNT; idIndex++) {
  1530. UCHAR BadReportIDList[BAD_REPORT_ID_LIST_COUNT] = { 0, 1, 127, 128, 129, 254, 255 };
  1531. if (!HIDTest_IsIDInList(BadReportIDList[idIndex],
  1532. reportIDList,
  1533. reportIDListCount
  1534. )) {
  1535. HIDTest_CallSetFeature( currDeviceHandle,
  1536. BadReportIDList[idIndex],
  1537. featureBuffer,
  1538. featureBufferLength,
  1539. &returnStatus,
  1540. &errorCode,
  1541. &bufferStatus
  1542. );
  1543. if (!bufferStatus) {
  1544. LOG_BUFFER_VALIDATION_FAIL();
  1545. variationStatus = FALSE;
  1546. }
  1547. else if (isLegalDeviceHandle) {
  1548. if (returnStatus) {
  1549. LOG_INVALID_RETURN_STATUS();
  1550. variationStatus = FALSE;
  1551. }
  1552. else {
  1553. if (ERROR_CRC != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1554. LOG_INVALID_ERROR_CODE();
  1555. variationStatus = FALSE;
  1556. }
  1557. }
  1558. }
  1559. else {
  1560. if (returnStatus) {
  1561. LOG_INVALID_RETURN_STATUS();
  1562. variationStatus = FALSE;
  1563. }
  1564. else {
  1565. if (ERROR_INVALID_HANDLE != errorCode) {
  1566. LOG_INVALID_ERROR_CODE();
  1567. variationStatus = FALSE;
  1568. }
  1569. }
  1570. }
  1571. }
  1572. }
  1573. if (variationStatus) {
  1574. LOG_VARIATION_PASS();
  1575. }
  1576. else {
  1577. LOG_VARIATION_FAIL();
  1578. failedCount++;
  1579. }
  1580. operationCount++;
  1581. END_VARIATION();
  1582. /*
  1583. // The next step in the validation process is to pass in buffers
  1584. // that are too small to hold an entire feature report. The same
  1585. // feature buffer will be used but we'll pass in a different size
  1586. // to the CallSetFeature routine. The appropriate response to
  1587. // this call should be:
  1588. //
  1589. // 1) returnStatus = FALSE;
  1590. // 2) errorCode = ERROR_CRC
  1591. // 3) bufferStatus = TRUE
  1592. //
  1593. // As above, we'll do this with two different report IDs, one
  1594. // valid one and one invalid one (if the invalid one exists) to
  1595. // make sure we hit as many possible code paths.
  1596. // Also three different lengths of buffers will be used, 1, 2,
  1597. // and featurelength-1
  1598. */
  1599. START_VARIATION("Passing in buffers that are too small");
  1600. variationStatus = TRUE;
  1601. reportID = 0;
  1602. do {
  1603. if (!HIDTest_IsIDInList(reportID,
  1604. reportIDList,
  1605. reportIDListCount
  1606. )) {
  1607. /*
  1608. // Perform the validation steps here for each of the report
  1609. // buffer sizes
  1610. */
  1611. reportBufferSize = 1;
  1612. while (1) {
  1613. wsprintf(varString, "ReportBufferSize = %d", reportBufferSize);
  1614. LOG_INTERMEDIATE_VARIATION_RESULT(varString);
  1615. HIDTest_CallSetFeature( currDeviceHandle,
  1616. reportID,
  1617. featureBuffer,
  1618. reportBufferSize,
  1619. &returnStatus,
  1620. &errorCode,
  1621. &bufferStatus
  1622. );
  1623. if (!bufferStatus) {
  1624. LOG_BUFFER_VALIDATION_FAIL();
  1625. variationStatus = FALSE;
  1626. }
  1627. else if (returnStatus) {
  1628. LOG_INVALID_RETURN_STATUS();
  1629. variationStatus = FALSE;
  1630. }
  1631. else if (isLegalDeviceHandle) {
  1632. if (ERROR_CRC != errorCode) {
  1633. LOG_INVALID_ERROR_CODE();
  1634. variationStatus = FALSE;
  1635. }
  1636. }
  1637. else if (ERROR_INVALID_HANDLE != errorCode) {
  1638. LOG_INVALID_ERROR_CODE();
  1639. variationStatus = FALSE;
  1640. }
  1641. /*
  1642. // Determine the next buffer length...The buffer lengths
  1643. // that are to be used are 1,2, and featureBufferLength-1
  1644. // unless some of those happen to be the same size
  1645. */
  1646. reportBufferSize++;
  1647. if (reportBufferSize == featureBufferLength) {
  1648. break;
  1649. }
  1650. else if (reportBufferSize > 2) {
  1651. reportBufferSize = featureBufferLength-1;
  1652. }
  1653. }
  1654. if (0 != reportID) {
  1655. break;
  1656. }
  1657. }
  1658. } while (reportID++ != 255);
  1659. }
  1660. if (variationStatus) {
  1661. LOG_VARIATION_PASS();
  1662. }
  1663. else {
  1664. LOG_VARIATION_FAIL();
  1665. failedCount++;
  1666. }
  1667. operationCount++;
  1668. END_VARIATION();
  1669. }
  1670. /*
  1671. // Do parameter validation now...Pass in the following three cases and
  1672. // verify correct operation
  1673. //
  1674. // 1) NULL buffer -- Length of 0,
  1675. // 2) NULL buffer -- Length != 0
  1676. // 3) non-NULL buffer -- length of 0
  1677. //
  1678. // Since we're verifying parameters, the actual reportID we use shouldn't
  1679. // matter, so we'll just use 1. Since we're not actually using test buffers
  1680. // we may not do any checking there either.
  1681. */
  1682. START_VARIATION("Parameter validation of SetFeature");
  1683. variationStatus = TRUE;
  1684. LOG_INTERMEDIATE_VARIATION_RESULT("Using NULL buffer with 0 length");
  1685. HIDTest_CallSetFeature( HidDevice -> HidDeviceHandle,
  1686. 1,
  1687. NULL,
  1688. 0,
  1689. &returnStatus,
  1690. &errorCode,
  1691. NULL
  1692. );
  1693. if (returnStatus) {
  1694. LOG_INVALID_RETURN_STATUS();
  1695. variationStatus = FALSE;
  1696. failedCount++;
  1697. }
  1698. else if (ERROR_INVALID_USER_BUFFER != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1699. LOG_INVALID_ERROR_CODE();
  1700. variationStatus = FALSE;
  1701. }
  1702. LOG_INTERMEDIATE_VARIATION_RESULT("Using NULL buffer with non-zero length");
  1703. HIDTest_CallSetFeature (HidDevice -> HidDeviceHandle,
  1704. 1,
  1705. NULL,
  1706. 3,
  1707. &returnStatus,
  1708. &errorCode,
  1709. NULL
  1710. );
  1711. if (returnStatus) {
  1712. LOG_INVALID_RETURN_STATUS();
  1713. variationStatus = FALSE;
  1714. }
  1715. else if (ERROR_INVALID_USER_BUFFER != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1716. LOG_INVALID_RETURN_STATUS();
  1717. variationStatus = FALSE;
  1718. }
  1719. LOG_INTERMEDIATE_VARIATION_RESULT("Using non-NULL buffer with zero length");
  1720. HIDTest_CallSetFeature (HidDevice -> HidDeviceHandle,
  1721. 1,
  1722. featureBuffer,
  1723. 0,
  1724. &returnStatus,
  1725. &errorCode,
  1726. &bufferStatus
  1727. );
  1728. if (!bufferStatus) {
  1729. LOG_BUFFER_VALIDATION_FAIL();
  1730. variationStatus = FALSE;
  1731. }
  1732. else if (returnStatus) {
  1733. LOG_INVALID_RETURN_STATUS();
  1734. variationStatus = FALSE;
  1735. }
  1736. else if (ERROR_INVALID_USER_BUFFER != errorCode && ERROR_INVALID_FUNCTION != errorCode) {
  1737. LOG_INVALID_ERROR_CODE();
  1738. variationStatus = FALSE;
  1739. }
  1740. if (variationStatus) {
  1741. LOG_VARIATION_PASS();
  1742. }
  1743. else {
  1744. LOG_VARIATION_FAIL();
  1745. failedCount++;
  1746. }
  1747. operationCount++;
  1748. END_VARIATION();
  1749. VERIFY_SETFEATURE_END:
  1750. END_TEST();
  1751. if (NULL != featureBuffer) {
  1752. FreeTestBuffer(featureBuffer);
  1753. }
  1754. Status -> nOperationsPerformed = operationCount;
  1755. Status -> nOperationsPassed = operationCount - failedCount;
  1756. Status -> nOperationsFailed = failedCount;
  1757. return;
  1758. }
  1759. VOID
  1760. HIDTest_CallSetFeature(
  1761. IN HANDLE DeviceHandle,
  1762. IN UCHAR ReportID,
  1763. IN PUCHAR ReportBuffer,
  1764. IN ULONG ReportBufferLength,
  1765. OUT PBOOL ReturnStatus,
  1766. OUT PULONG ErrorCode,
  1767. OUT PBOOL BufferStatus
  1768. )
  1769. {
  1770. /*
  1771. // If we have a non-null buffer of > 0 length, then allocate the
  1772. // zero the memory and add the reportID as the first byte.
  1773. */
  1774. if (NULL != ReportBuffer && ReportBufferLength > 0) {
  1775. ZeroMemory (ReportBuffer, ReportBufferLength);
  1776. *ReportBuffer = ReportID;
  1777. }
  1778. /*
  1779. // Call SetFeature
  1780. */
  1781. *ReturnStatus = HidD_SetFeature(DeviceHandle,
  1782. ReportBuffer,
  1783. ReportBufferLength
  1784. );
  1785. /*
  1786. // Get the error code returned
  1787. */
  1788. *ErrorCode = GetLastError();
  1789. /*
  1790. // Do a buffer validation check
  1791. */
  1792. if (NULL != BufferStatus) {
  1793. *BufferStatus = ValidateTestBuffer(ReportBuffer);
  1794. }
  1795. return;
  1796. }
  1797. BOOL
  1798. HIDTest_ValidateNumInputBuffers(
  1799. IN HANDLE HandleToTest,
  1800. IN HANDLE SecondHandle,
  1801. IN BOOL IsFirstHandleLegal,
  1802. IN PULONG TestBuffer
  1803. )
  1804. {
  1805. BOOL testStatus;
  1806. BOOL callStatus;
  1807. BOOL prevStatus;
  1808. BOOL isLegalNewCount;
  1809. BOOL done;
  1810. ULONG firstHandleCount;
  1811. ULONG secondHandleCount;
  1812. ULONG newCount;
  1813. /*
  1814. // For each iteration of this test, we need to do the following steps
  1815. // 1) Open a second handle to the hid device
  1816. // 2) Call HidD_GetNumInputBuffers on both handles and verify > 0 if
  1817. // the first handle is legal
  1818. // 3) Verify that the buffer is not overrun
  1819. // 4) On first handle, call HidD_SetNumInputBuffers with 0, 1,
  1820. // CURRENT_BUFFER_MIN-1, CURRENT_BUFFER_MIN and a random value
  1821. // - If return value is FALSE and legal handle, insure the
  1822. // value was an expected illegal one...Verify that previous
  1823. // value hasn't changed
  1824. // - If return value is FALSE and illegal handle, good!
  1825. // - If return value is TRUE and illegal handle, bad news.
  1826. // - If return value is TRUE and a legal handle, make sure
  1827. // HidD_GetNumInputBuffers returns the value we just set
  1828. // - Verify that the second handle's original value has not changed
  1829. //
  1830. */
  1831. LOG_INTERMEDIATE_VARIATION_RESULT("Retrieving current number of buffers");
  1832. /*
  1833. // Get the current number of buffers as reported for each device
  1834. */
  1835. callStatus = HIDTest_GetBufferCount(HandleToTest,
  1836. TestBuffer
  1837. );
  1838. if (!callStatus && IsFirstHandleLegal) {
  1839. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_GetNumInputBuffers unexpectedly returned FALSE");
  1840. return (FALSE);
  1841. }
  1842. if (callStatus && !IsFirstHandleLegal) {
  1843. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_GetNumInputBuffers unexpectedly returned TRUE");
  1844. return (FALSE);
  1845. }
  1846. firstHandleCount = *TestBuffer;
  1847. callStatus = HIDTest_GetBufferCount(SecondHandle,
  1848. TestBuffer
  1849. );
  1850. if (!callStatus) {
  1851. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_GetNumInputBuffers unexpectedly returned FALSE on second handle");
  1852. return (FALSE);
  1853. }
  1854. secondHandleCount = *TestBuffer;
  1855. /*
  1856. // Verify that each of the counts is greater than or equal to the minimum
  1857. // number of buffers
  1858. */
  1859. LOG_INTERMEDIATE_VARIATION_RESULT("Verifying the buffer count for both handles");
  1860. if (firstHandleCount < CURRENT_BUFFER_MIN || secondHandleCount < CURRENT_BUFFER_MIN) {
  1861. LOG_INTERMEDIATE_VARIATION_RESULT("One of the buffer counts is less than the supposed minimum");
  1862. return (FALSE);
  1863. }
  1864. /*
  1865. // Begin looping and setting the buffer values for the first handle and
  1866. // verifying proper functionality. On each loop, also make sure that
  1867. // the second handle's value doesn't change.
  1868. */
  1869. newCount = 0;
  1870. testStatus = TRUE;
  1871. done = FALSE;
  1872. while (!done) {
  1873. isLegalNewCount = (newCount >= CURRENT_BUFFER_MIN);
  1874. callStatus = HidD_SetNumInputBuffers(HandleToTest, newCount);
  1875. if (!callStatus) {
  1876. if (IsFirstHandleLegal && isLegalNewCount) {
  1877. LOG_INTERMEDIATE_VARIATION_RESULT("Could not set legal buffer value");
  1878. testStatus = FALSE;
  1879. }
  1880. else {
  1881. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_SetNumInputBuffers properly returned FALSE");
  1882. }
  1883. }
  1884. else {
  1885. if (!IsFirstHandleLegal) {
  1886. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_SetNumInputBuffers improperly returned TRUE");
  1887. testStatus = FALSE;
  1888. }
  1889. else if (!isLegalNewCount) {
  1890. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_SetNumInputBuffers set invalid value");
  1891. testStatus = FALSE;
  1892. }
  1893. }
  1894. /*
  1895. // Now that we have attempted to set the first handle to a new value,
  1896. // we need to do some verification...There are four cases to look
  1897. // at:
  1898. // 1) callStatus = FALSE, isLegalNewCount = TRUE
  1899. // -- old value should be retained
  1900. //
  1901. // 2) callStatus = FALSE, isLegalNewCount = FALSE
  1902. // -- old value should be retained
  1903. //
  1904. // 3) callStatus = TRUE, isLegalNewCount = TRUE
  1905. // -- new value should be set
  1906. //
  1907. // 4) callStatus = TRUE, isLegalNewCount = FALSE
  1908. // -- new value should be set
  1909. //
  1910. // One other case occurred if the handle we tested wasn't even legal...
  1911. // in this case, just need to bolt.
  1912. */
  1913. if (IsFirstHandleLegal) {
  1914. prevStatus = callStatus;
  1915. callStatus = HIDTest_GetBufferCount(HandleToTest, TestBuffer);
  1916. if (!callStatus) {
  1917. LOG_INTERMEDIATE_VARIATION_RESULT("HidD_GetNumInputBuffers unexpectedly returned FALSE");
  1918. testStatus = FALSE;
  1919. }
  1920. if (prevStatus) {
  1921. if (*TestBuffer != newCount) {
  1922. LOG_INTERMEDIATE_VARIATION_RESULT("New buffer value not actually set");
  1923. testStatus = FALSE;
  1924. firstHandleCount = *TestBuffer;
  1925. }
  1926. else {
  1927. LOG_INTERMEDIATE_VARIATION_RESULT("New buffer value properly set");
  1928. firstHandleCount = newCount;
  1929. }
  1930. }
  1931. else {
  1932. if (*TestBuffer != firstHandleCount) {
  1933. LOG_INTERMEDIATE_VARIATION_RESULT("Old buffer value not preserved on test handle");
  1934. testStatus = FALSE;
  1935. firstHandleCount = *TestBuffer;
  1936. }
  1937. else {
  1938. LOG_INTERMEDIATE_VARIATION_RESULT("Old buffer value properly retained on test handle");
  1939. }
  1940. }
  1941. }
  1942. /*
  1943. // Verify that the second handle's buffer value didn't change
  1944. */
  1945. callStatus = HIDTest_GetBufferCount(SecondHandle, TestBuffer);
  1946. if (!callStatus) {
  1947. LOG_INTERMEDIATE_VARIATION_RESULT("Could not get second handle value");
  1948. testStatus = FALSE;
  1949. }
  1950. else {
  1951. if (secondHandleCount != *TestBuffer) {
  1952. LOG_INTERMEDIATE_VARIATION_RESULT("Second handle buffer count not properly retained");
  1953. testStatus = FALSE;
  1954. secondHandleCount = *TestBuffer;
  1955. }
  1956. else {
  1957. LOG_INTERMEDIATE_VARIATION_RESULT("Second handle buffer count properly retained");
  1958. }
  1959. }
  1960. /*
  1961. // Determine what the next test value is
  1962. */
  1963. newCount++;
  1964. switch (newCount) {
  1965. case 2:
  1966. if (2 < CURRENT_BUFFER_MIN-1) {
  1967. newCount = CURRENT_BUFFER_MIN-1;
  1968. }
  1969. break;
  1970. case CURRENT_BUFFER_MIN+1:
  1971. newCount = RANDOM_BUFFER_VALUE;
  1972. break;
  1973. case RANDOM_BUFFER_VALUE+1:
  1974. done = TRUE;
  1975. break;
  1976. }
  1977. } // while loop
  1978. return (testStatus);
  1979. }
  1980. BOOL
  1981. HIDTest_GetBufferCount(
  1982. IN HANDLE DeviceHandle,
  1983. IN PULONG TestBuffer
  1984. )
  1985. {
  1986. BOOL callStatus;
  1987. callStatus = HidD_GetNumInputBuffers(DeviceHandle, TestBuffer);
  1988. if (!ValidateTestBuffer(TestBuffer)) {
  1989. LOG_BUFFER_VALIDATION_FAIL();
  1990. callStatus = FALSE;
  1991. }
  1992. return (callStatus);
  1993. }
  1994. BOOL
  1995. HIDTest_ValidateStrings(
  1996. HANDLE DeviceHandle,
  1997. PLIST MasterList,
  1998. ULONG ManufacturerStringIndex,
  1999. ULONG ProductStringIndex,
  2000. ULONG SerialNumberStringIndex
  2001. )
  2002. {
  2003. BOOL CallStatus;
  2004. LIST StringList;
  2005. /*
  2006. // To validate the strings, we need to perform the following operations on
  2007. // the current device handle
  2008. //
  2009. // 1) Build a list of all the strings
  2010. // 2) Compare the passed in list with the
  2011. // 2) Retrieve the standard strings and if they exist, need to verify
  2012. // that they actually in the previously built list
  2013. // 3) If the the PreviousList list pointer is not NULL, compare the
  2014. // string list that was just built with the previous one. They
  2015. // should be the same.
  2016. */
  2017. CallStatus = HIDTest_BuildStringList( DeviceHandle,
  2018. &StringList
  2019. );
  2020. if (!CallStatus) {
  2021. LOG_INTERMEDIATE_VARIATION_RESULT("Could not build string list");
  2022. return (FALSE);
  2023. }
  2024. /*
  2025. // Compare the string list just built with the master list that was
  2026. // passed in as a parameter. They should be the same
  2027. */
  2028. if (!HIDTest_CompareStringLists(&StringList, MasterList)) {
  2029. LOG_INTERMEDIATE_VARIATION_RESULT("String lists not equal");
  2030. return (FALSE);
  2031. }
  2032. /*
  2033. // Validate the standard strings (manufacturer, product, and serial number).
  2034. // checking that if a string is returned for these values, it is the same
  2035. // string as marked in the master list
  2036. */
  2037. CallStatus = HIDTest_ValidateStdStrings(DeviceHandle,
  2038. MasterList,
  2039. ManufacturerStringIndex,
  2040. ProductStringIndex,
  2041. SerialNumberStringIndex
  2042. );
  2043. if (!CallStatus) {
  2044. LOG_INTERMEDIATE_VARIATION_RESULT("Could not validate the standard strings");
  2045. return (FALSE);
  2046. }
  2047. return (TRUE);
  2048. }
  2049. BOOL
  2050. HIDTest_ValidateStringParams(
  2051. IN HANDLE HidDevice,
  2052. IN PLIST StringList,
  2053. IN ULONG ManufacturerStringIndex,
  2054. IN ULONG ProductStringIndex,
  2055. IN ULONG SerialNumberStringIndex
  2056. )
  2057. {
  2058. /*
  2059. // This function will perform parameter validation for each of the following
  2060. // calls:
  2061. //
  2062. // HidD_GetIndexedString();
  2063. // HidD_GetManufacturerString();
  2064. // HidD_GetProductString();
  2065. // HidD_GetSerialNumberString();
  2066. //
  2067. // It performs the following steps if the string in question actually exists
  2068. // for the passed in device:
  2069. //
  2070. // 1) Allocates a buffer of size 1 and verifies that FALSE is returned for
  2071. // the call, ERROR_INVALID_USER_BUFFER has been set and there is
  2072. // no trashing of the buffer
  2073. // 2) Allocats a buffer of size 2 and does the above check
  2074. // 3) Allocates a buffer of stringLength * sizeof(WCHAR) - 1 to verify
  2075. // the same check
  2076. // 4) Passes in a NULL buffer with a defined length of 0
  2077. // 5) Passes in a NULL buffer with a defined length != 0
  2078. */
  2079. ULONG stringIndex;
  2080. ULONG indexValue;
  2081. PCHAR stringTypeDesc;
  2082. BOOL testStatus;
  2083. BOOL callStatus;
  2084. STRING_LIST_NODE stringNode;
  2085. PSTRING_LIST_NODE ptrStringNode;
  2086. static CHAR ErrorString[128];
  2087. ASSERT(STRING_INDEX_MANUFACTURER+1 == STRING_INDEX_PRODUCT);
  2088. ASSERT(STRING_INDEX_PRODUCT+1 == STRING_INDEX_SERIAL_NUMBER);
  2089. testStatus = TRUE;
  2090. for (stringIndex = STRING_INDEX_MANUFACTURER; stringIndex <= STRING_INDEX_SERIAL_NUMBER; stringIndex++) {
  2091. switch (stringIndex) {
  2092. case STRING_INDEX_MANUFACTURER:
  2093. indexValue = ManufacturerStringIndex;
  2094. stringTypeDesc = "Manufacturer";
  2095. break;
  2096. case STRING_INDEX_PRODUCT:
  2097. indexValue = ProductStringIndex;
  2098. stringTypeDesc = "Product";
  2099. break;
  2100. case STRING_INDEX_SERIAL_NUMBER:
  2101. indexValue = SerialNumberStringIndex;
  2102. stringTypeDesc = "Serial number";
  2103. break;
  2104. }
  2105. if (NO_STRING_INDEX == indexValue) {
  2106. wsprintf(ErrorString,
  2107. "%s string does not exist -- no parameter checks",
  2108. stringTypeDesc
  2109. );
  2110. LOG_INTERMEDIATE_VARIATION_RESULT( ErrorString );
  2111. }
  2112. else {
  2113. if (!HIDTest_IsStrIndexInStrList(StringList,
  2114. indexValue,
  2115. &stringNode)) {
  2116. wsprintf(ErrorString,
  2117. "%s string not in string list",
  2118. stringTypeDesc
  2119. );
  2120. LOG_INTERMEDIATE_VARIATION_RESULT( ErrorString );
  2121. continue;
  2122. }
  2123. callStatus = HIDTest_ValidateStringIndexParams(HidDevice,
  2124. indexValue,
  2125. stringNode.StringLength,
  2126. stringTypeDesc
  2127. );
  2128. testStatus = testStatus && callStatus;
  2129. }
  2130. }
  2131. /*
  2132. // Perform the above tests now but this time using HidD_GetIndexedString using
  2133. // the first index in the string list
  2134. */
  2135. #ifdef O
  2136. if (IsListEmpty(StringList)) {
  2137. LOG_INTERMEDIATE_VARIATION_RESULT( "No strings in string list" );
  2138. }
  2139. else {
  2140. ptrStringNode = (PSTRING_LIST_NODE) GetListHead(StringList);
  2141. wsprintf(ErrorString,
  2142. "String index: %d",
  2143. ptrStringNode -> StringIndex
  2144. );
  2145. callStatus = HIDTest_ValidateStringIndexParams(HidDevice,
  2146. ptrStringNode -> StringIndex,
  2147. ptrStringNode -> StringLength,
  2148. ErrorString
  2149. );
  2150. testStatus = testStatus && callStatus;
  2151. }
  2152. #endif
  2153. return (testStatus);
  2154. }
  2155. BOOL
  2156. HIDTest_ValidateStringIndexParams(
  2157. IN HANDLE HidDevice,
  2158. IN ULONG StringIndex,
  2159. IN ULONG StringLength,
  2160. IN PCHAR StringTypeDesc
  2161. )
  2162. {
  2163. ULONG bufferLength;
  2164. BOOL done;
  2165. BOOL callStatus;
  2166. BOOL testStatus;
  2167. PWCHAR deviceString;
  2168. ULONG errorCode;
  2169. static CHAR ErrorString[128];
  2170. bufferLength = 1;
  2171. done = FALSE;
  2172. testStatus = FALSE;
  2173. while (!done) {
  2174. deviceString = (PWCHAR) AllocateTestBuffer(bufferLength*sizeof(WCHAR));
  2175. if (NULL == deviceString) {
  2176. wsprintf( ErrorString,
  2177. "Could not allocate space for %s string",
  2178. StringTypeDesc
  2179. );
  2180. LOG_TEST_ERROR ( ErrorString );
  2181. continue;
  2182. }
  2183. callStatus = HIDTest_GetString( HidDevice,
  2184. StringIndex,
  2185. deviceString,
  2186. bufferLength,
  2187. &errorCode
  2188. );
  2189. if (!ValidateTestBuffer(deviceString)) {
  2190. LOG_BUFFER_VALIDATION_FAIL();
  2191. testStatus = FALSE;
  2192. }
  2193. if (!callStatus) {
  2194. if (bufferLength == StringLength*sizeof(WCHAR)) {
  2195. wsprintf( ErrorString,
  2196. "Couldn't retrieve %s string with proper buffer",
  2197. StringTypeDesc
  2198. );
  2199. LOG_INTERMEDIATE_VARIATION_RESULT( ErrorString );
  2200. testStatus = FALSE;
  2201. }
  2202. else if (ERROR_INVALID_USER_BUFFER != GetLastError()) {
  2203. wsprintf( ErrorString,
  2204. "Invalid error value returned for %s string",
  2205. StringTypeDesc
  2206. );
  2207. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  2208. testStatus = FALSE;
  2209. }
  2210. }
  2211. else {
  2212. if (bufferLength != StringLength*sizeof(WCHAR)) {
  2213. wsprintf( ErrorString,
  2214. "Retrieved %s string with buffer too small",
  2215. StringTypeDesc
  2216. );
  2217. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  2218. testStatus = FALSE;
  2219. }
  2220. }
  2221. FreeTestBuffer( deviceString );
  2222. /*
  2223. // Increment the buffer length and try again
  2224. */
  2225. switch (bufferLength) {
  2226. case 1:
  2227. bufferLength = 2;
  2228. break;
  2229. case 2:
  2230. bufferLength = StringLength*sizeof(WCHAR)-1;
  2231. break;
  2232. default:
  2233. if (bufferLength >= StringLength*sizeof(WCHAR)) {
  2234. done = TRUE;
  2235. }
  2236. else {
  2237. bufferLength = StringLength*sizeof(WCHAR);
  2238. }
  2239. }
  2240. }
  2241. for (bufferLength = 0;
  2242. bufferLength <= StringLength*sizeof(WCHAR);
  2243. bufferLength += StringLength*sizeof(WCHAR)) {
  2244. /*
  2245. // Pass in a NULL buffer with length 0 and NULL buffer
  2246. // with the appropriate size. Verify that
  2247. // FALSE/ERROR_INVALID_USER_BUFFER is returned
  2248. */
  2249. callStatus = HIDTest_GetString(HidDevice,
  2250. StringIndex,
  2251. NULL,
  2252. bufferLength,
  2253. &errorCode
  2254. );
  2255. if (callStatus) {
  2256. wsprintf( ErrorString,
  2257. "%s string retrieved into NULL buffer with size: %d",
  2258. StringTypeDesc,
  2259. bufferLength
  2260. );
  2261. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  2262. testStatus = FALSE;
  2263. }
  2264. else {
  2265. if (ERROR_INVALID_USER_BUFFER != GetLastError()) {
  2266. wsprintf( ErrorString,
  2267. "%s string expected ERROR_INVALID_USER_BUFFER error",
  2268. StringTypeDesc
  2269. );
  2270. LOG_INTERMEDIATE_VARIATION_RESULT( ErrorString );
  2271. testStatus = FALSE;
  2272. }
  2273. else {
  2274. wsprintf( ErrorString,
  2275. "%s string returned correctly with invalid buffer and size: %d",
  2276. StringTypeDesc,
  2277. bufferLength
  2278. );
  2279. LOG_INTERMEDIATE_VARIATION_RESULT( ErrorString );
  2280. }
  2281. }
  2282. }
  2283. return (testStatus);
  2284. }
  2285. BOOL
  2286. HIDTest_CreatePhysicalDeviceInfoA(
  2287. IN DEVICE_STRING DeviceName,
  2288. IN BOOL OpenOverlapped,
  2289. OUT PHIDTEST_DEVICEINFO DeviceInfo
  2290. )
  2291. {
  2292. PWCHAR tempString;
  2293. ULONG tempStringLength;
  2294. BOOL stringExists;
  2295. STRING_LIST_NODE stringNode;
  2296. /*
  2297. // First, fill our device info block so that we can easily determine
  2298. // what needs to be freed and what doesn't when we call
  2299. // HIDTest_FreeDeviceStructures
  2300. */
  2301. ZeroMemory(DeviceInfo, sizeof(HIDTEST_DEVICEINFO));
  2302. /*
  2303. // If no device name exists, simply return false but at least we've
  2304. // fill our memory buffer so if the caller later tries to destroy this
  2305. // block we won't attempt to free nonexistant memory
  2306. */
  2307. if (NULL == DeviceName) {
  2308. return (FALSE);
  2309. }
  2310. DeviceInfo -> IsPhysicalDevice = TRUE;
  2311. /*
  2312. // First thing to do is initialize the string list, so we can properly
  2313. // free it if need be.
  2314. */
  2315. InitializeList(&DeviceInfo -> StringList);
  2316. /*
  2317. // Begin by creating space for the DEVICE_STRING
  2318. */
  2319. DeviceInfo -> HidDeviceString = (DEVICE_STRING) HIDTest_AllocateDeviceString(lstrlen(DeviceName));
  2320. if (NULL == DeviceInfo -> HidDeviceString) {
  2321. return (FALSE);
  2322. }
  2323. CopyMemory(DeviceInfo -> HidDeviceString,
  2324. DeviceName,
  2325. (1+lstrlen(DeviceName)) * sizeof(TCHAR));
  2326. /*
  2327. // Next, we need to try to open the device handle
  2328. */
  2329. DeviceInfo -> HidDeviceHandle = CreateFile(DeviceInfo -> HidDeviceString,
  2330. GENERIC_READ | GENERIC_WRITE,
  2331. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2332. NULL,
  2333. OPEN_EXISTING,
  2334. OpenOverlapped ? FILE_FLAG_OVERLAPPED : 0,
  2335. NULL);
  2336. if (!(IS_VALID_DEVICE_HANDLE(DeviceInfo -> HidDeviceHandle))) {
  2337. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2338. return (FALSE);
  2339. }
  2340. /*
  2341. // Next, we need to try to obtain the preparsed data for the device
  2342. */
  2343. if (!HidD_GetPreparsedData(DeviceInfo -> HidDeviceHandle, &DeviceInfo -> HidDevicePpd)) {
  2344. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2345. return (FALSE);
  2346. }
  2347. DeviceInfo -> HidDeviceAttributes = (PHIDD_ATTRIBUTES) ALLOC(sizeof(HIDD_ATTRIBUTES));
  2348. if (NULL == DeviceInfo -> HidDeviceAttributes) {
  2349. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2350. return (FALSE);
  2351. }
  2352. if (!HidD_GetAttributes(DeviceInfo -> HidDeviceHandle, DeviceInfo -> HidDeviceAttributes)) {
  2353. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2354. return (FALSE);
  2355. }
  2356. if (!HIDTest_FillCommonDeviceInfo(DeviceInfo)) {
  2357. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2358. return (FALSE);
  2359. }
  2360. /*
  2361. // Create the string list for the physical device
  2362. */
  2363. if (!HIDTest_BuildStringList( DeviceInfo -> HidDeviceHandle,
  2364. &DeviceInfo -> StringList
  2365. )) {
  2366. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2367. return (FALSE);
  2368. }
  2369. /*
  2370. // String list has been built, let's determine what the
  2371. // the different other strings are.
  2372. */
  2373. /*
  2374. // Begin by turning off logging for this function...Odds
  2375. // are its not on yet, but will do so just to make sure
  2376. */
  2377. LOG_OFF();
  2378. /*
  2379. // Initialize the indices
  2380. */
  2381. DeviceInfo -> ManufacturerStringIndex = NO_STRING_INDEX;
  2382. DeviceInfo -> ProductStringIndex = NO_STRING_INDEX;
  2383. DeviceInfo -> SerialNumberStringIndex = NO_STRING_INDEX;
  2384. /*
  2385. // Get the manufacturer string
  2386. */
  2387. /*
  2388. // The retrieval of the strings is broken in NT5 so this part is commented out for
  2389. // now
  2390. */
  2391. #ifdef O
  2392. if (!HIDTest_DoesStringExist(DeviceInfo -> HidDeviceHandle,
  2393. STRING_INDEX_MANUFACTURER,
  2394. &tempString,
  2395. &tempStringLength,
  2396. &stringExists)) {
  2397. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2398. LOG_ON();
  2399. return (FALSE);
  2400. }
  2401. if (stringExists) {
  2402. if (!HIDTest_IsStringInStrList(&DeviceInfo -> StringList,
  2403. tempString,
  2404. tempStringLength,
  2405. &stringNode
  2406. )) {
  2407. FreeTestBuffer(tempString);
  2408. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2409. LOG_ON();
  2410. return (FALSE);
  2411. }
  2412. DeviceInfo -> ManufacturerStringIndex = stringNode.StringIndex;
  2413. FreeTestBuffer(tempString);
  2414. }
  2415. /*
  2416. // Get the product string
  2417. */
  2418. if (!HIDTest_DoesStringExist(DeviceInfo -> HidDeviceHandle,
  2419. STRING_INDEX_PRODUCT,
  2420. &tempString,
  2421. &tempStringLength,
  2422. &stringExists)) {
  2423. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2424. LOG_ON();
  2425. return (FALSE);
  2426. }
  2427. if (stringExists) {
  2428. if (!HIDTest_IsStringInStrList(&DeviceInfo -> StringList,
  2429. tempString,
  2430. tempStringLength,
  2431. &stringNode
  2432. )) {
  2433. FreeTestBuffer(tempString);
  2434. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2435. LOG_ON();
  2436. return (FALSE);
  2437. }
  2438. DeviceInfo -> ProductStringIndex = stringNode.StringIndex;
  2439. FreeTestBuffer(tempString);
  2440. }
  2441. /*
  2442. // Get the serial number string
  2443. */
  2444. if (!HIDTest_DoesStringExist(DeviceInfo -> HidDeviceHandle,
  2445. STRING_INDEX_SERIAL_NUMBER,
  2446. &tempString,
  2447. &tempStringLength,
  2448. &stringExists)) {
  2449. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2450. LOG_ON();
  2451. return (FALSE);
  2452. }
  2453. if (stringExists) {
  2454. if (!HIDTest_IsStringInStrList(&DeviceInfo -> StringList,
  2455. tempString,
  2456. tempStringLength,
  2457. &stringNode
  2458. )) {
  2459. FreeTestBuffer(tempString);
  2460. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2461. LOG_ON();
  2462. return (FALSE);
  2463. }
  2464. DeviceInfo -> SerialNumberStringIndex = stringNode.StringIndex;
  2465. FreeTestBuffer(tempString);
  2466. }
  2467. #endif
  2468. return (TRUE);
  2469. }
  2470. BOOL
  2471. HIDTest_CreateLogicalDeviceInfoA(
  2472. IN PCHAR DevicePpd,
  2473. IN ULONG DevicePpdLength,
  2474. OUT PHIDTEST_DEVICEINFO DeviceInfo
  2475. )
  2476. {
  2477. /*
  2478. // Declare the HidD_Hello function to satisfy the compiler needing
  2479. // the declaration
  2480. */
  2481. PULONG HidD_Hello;
  2482. /*
  2483. // First, fill our device info block so that we can easily determine
  2484. // what needs to be freed and what doesn't when we call
  2485. // HIDTest_FreeDeviceStructures
  2486. */
  2487. ZeroMemory(DeviceInfo, sizeof(HIDTEST_DEVICEINFO));
  2488. DeviceInfo -> IsPhysicalDevice = FALSE;
  2489. /*
  2490. // A logical device has no string associated with it.
  2491. */
  2492. DeviceInfo -> HidDeviceString = NULL;
  2493. /*
  2494. // A logical device also has no object handle, so we invalidate that
  2495. // as well.
  2496. */
  2497. DeviceInfo -> HidDeviceHandle = INVALID_HANDLE_VALUE;
  2498. /*
  2499. // Allocate memory for our preparsed data structure. Since the input
  2500. // pointer points to a structure that is obtained at the driver level
  2501. // we need to allocate a little more space for the signature that
  2502. // is attached to driver supplied info by HID.DLL.
  2503. //
  2504. // WARNING: This is buggy as the signature prepended to the structure
  2505. // may someday changed and blow this routine to pieces. The
  2506. // following prepended header is derived from the current
  2507. // HID.DLL implementation and header files (which could change).
  2508. */
  2509. /*
  2510. // First, let's attempt to get the address to HidD_Hello
  2511. */
  2512. HidD_Hello = (PULONG) GetProcAddress(GetModuleHandle("HID.DLL"),
  2513. "HidD_Hello"
  2514. );
  2515. if (NULL == HidD_Hello) {
  2516. return (FALSE);
  2517. }
  2518. DeviceInfo -> HidDevicePpd = (PHIDP_PREPARSED_DATA) ALLOC((4*sizeof(ULONG)) + DevicePpdLength);
  2519. if (NULL == DeviceInfo -> HidDevicePpd) {
  2520. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2521. return (FALSE);
  2522. }
  2523. /*
  2524. // Setup the signature on the Ppd, copy over the real Ppd struct and set
  2525. // the address of the Ppd to past the signature. Now, it's just like
  2526. // we got the data directly from the device.
  2527. */
  2528. *((PULONG) DeviceInfo -> HidDevicePpd) = (ULONG) &HidD_Hello;
  2529. (PULONG) DeviceInfo -> HidDevicePpd = ((PULONG) DeviceInfo -> HidDevicePpd) + 4;
  2530. CopyMemory(DeviceInfo -> HidDevicePpd, DevicePpd, DevicePpdLength);
  2531. /*
  2532. // Also, a logical device has no attributes so we NULL that field as well.
  2533. */
  2534. DeviceInfo -> HidDeviceAttributes = NULL;
  2535. if (!HIDTest_FillCommonDeviceInfo(DeviceInfo)) {
  2536. HIDTest_FreeDeviceInfoA(DeviceInfo);
  2537. return (FALSE);
  2538. }
  2539. return (TRUE);
  2540. }
  2541. VOID
  2542. HIDTest_FreeDeviceInfoA(
  2543. IN PHIDTEST_DEVICEINFO DeviceInfo
  2544. )
  2545. {
  2546. if (IS_VALID_DEVICE_HANDLE(DeviceInfo -> HidDeviceHandle)) {
  2547. CloseHandle(DeviceInfo -> HidDeviceHandle);
  2548. }
  2549. if (NULL != DeviceInfo -> HidDeviceString) {
  2550. HIDTest_FreeDeviceString(DeviceInfo -> HidDeviceString);
  2551. }
  2552. if (NULL != DeviceInfo -> HidDevicePpd) {
  2553. if (DeviceInfo -> IsPhysicalDevice) {
  2554. HidD_FreePreparsedData(DeviceInfo -> HidDevicePpd);
  2555. }
  2556. else {
  2557. (PULONG) DeviceInfo -> HidDevicePpd = ((PULONG) DeviceInfo -> HidDevicePpd) - 4;
  2558. FREE(DeviceInfo -> HidDevicePpd);
  2559. }
  2560. }
  2561. if (NULL != DeviceInfo -> HidDeviceAttributes) {
  2562. FREE(DeviceInfo -> HidDeviceAttributes);
  2563. }
  2564. if (NULL != DeviceInfo -> HidDeviceCaps) {
  2565. FREE(DeviceInfo -> HidDeviceCaps);
  2566. }
  2567. return;
  2568. }
  2569. /*****************************************************************************
  2570. /* Local function definitions
  2571. /*****************************************************************************/
  2572. BOOL
  2573. HIDTest_FillCommonDeviceInfo(
  2574. OUT PHIDTEST_DEVICEINFO DeviceInfo
  2575. )
  2576. {
  2577. BOOL isError;
  2578. isError = FALSE;
  2579. DeviceInfo -> HidDeviceCaps = (PHIDP_CAPS) ALLOC(sizeof(HIDP_CAPS));
  2580. if (NULL == DeviceInfo -> HidDeviceCaps) {
  2581. isError = TRUE;
  2582. goto FILL_INFO_END;
  2583. }
  2584. if (!HidP_GetCaps(DeviceInfo -> HidDevicePpd,
  2585. DeviceInfo -> HidDeviceCaps)) {
  2586. isError = TRUE;
  2587. goto FILL_INFO_END;
  2588. }
  2589. isError = !HIDTest_FillValueCaps( HidP_Input,
  2590. &DeviceInfo -> HidInputValueCaps,
  2591. DeviceInfo -> HidDeviceCaps -> NumberInputValueCaps,
  2592. DeviceInfo -> HidDevicePpd
  2593. );
  2594. isError = !HIDTest_FillValueCaps( HidP_Output,
  2595. &DeviceInfo -> HidOutputValueCaps,
  2596. DeviceInfo -> HidDeviceCaps -> NumberOutputValueCaps,
  2597. DeviceInfo -> HidDevicePpd) || isError;
  2598. isError = !HIDTest_FillValueCaps( HidP_Feature,
  2599. &DeviceInfo -> HidFeatureValueCaps,
  2600. DeviceInfo -> HidDeviceCaps -> NumberFeatureValueCaps,
  2601. DeviceInfo -> HidDevicePpd) || isError;
  2602. isError = !HIDTest_FillButtonCaps(HidP_Input,
  2603. &DeviceInfo -> HidInputButtonCaps,
  2604. DeviceInfo -> HidDeviceCaps -> NumberInputButtonCaps,
  2605. DeviceInfo -> HidDevicePpd
  2606. ) || isError;
  2607. isError = !HIDTest_FillButtonCaps(HidP_Output,
  2608. &DeviceInfo -> HidOutputButtonCaps,
  2609. DeviceInfo -> HidDeviceCaps -> NumberOutputButtonCaps,
  2610. DeviceInfo -> HidDevicePpd) || isError;
  2611. isError = !HIDTest_FillButtonCaps(HidP_Feature,
  2612. &DeviceInfo -> HidFeatureButtonCaps,
  2613. DeviceInfo -> HidDeviceCaps -> NumberFeatureButtonCaps,
  2614. DeviceInfo -> HidDevicePpd) || isError;
  2615. FILL_INFO_END:
  2616. return (!isError);
  2617. }
  2618. BOOL
  2619. HIDTest_FillValueCaps(
  2620. IN HIDP_REPORT_TYPE ReportType,
  2621. IN PHIDP_VALUE_CAPS *CapsBuffer,
  2622. IN ULONG NumCaps,
  2623. IN PHIDP_PREPARSED_DATA Ppd
  2624. )
  2625. {
  2626. BOOL callStatus;
  2627. BOOL isError;
  2628. USHORT numCaps;
  2629. isError = FALSE;
  2630. if (0 != NumCaps) {
  2631. *CapsBuffer = (PHIDP_VALUE_CAPS) ALLOC(NumCaps * sizeof(HIDP_VALUE_CAPS));
  2632. if (NULL != *CapsBuffer) {
  2633. numCaps = (USHORT) NumCaps;
  2634. callStatus = HidP_GetValueCaps( ReportType,
  2635. *CapsBuffer,
  2636. &numCaps,
  2637. Ppd
  2638. );
  2639. if (HIDP_STATUS_SUCCESS != callStatus || numCaps != NumCaps) {
  2640. isError = TRUE;
  2641. }
  2642. }
  2643. else {
  2644. isError = TRUE;
  2645. }
  2646. }
  2647. else {
  2648. *CapsBuffer = NULL;
  2649. }
  2650. return (!isError);
  2651. }
  2652. BOOL
  2653. HIDTest_FillButtonCaps(
  2654. IN HIDP_REPORT_TYPE ReportType,
  2655. IN PHIDP_BUTTON_CAPS *CapsBuffer,
  2656. IN ULONG NumCaps,
  2657. IN PHIDP_PREPARSED_DATA Ppd
  2658. )
  2659. {
  2660. BOOL callStatus;
  2661. BOOL isError;
  2662. USHORT numCaps;
  2663. isError = FALSE;
  2664. if (0 != NumCaps) {
  2665. *CapsBuffer = (PHIDP_BUTTON_CAPS) ALLOC(NumCaps * sizeof(HIDP_BUTTON_CAPS));
  2666. if (NULL != *CapsBuffer) {
  2667. numCaps = (USHORT) NumCaps;
  2668. callStatus = HidP_GetButtonCaps( ReportType,
  2669. *CapsBuffer,
  2670. &numCaps,
  2671. Ppd
  2672. );
  2673. if (HIDP_STATUS_SUCCESS != callStatus || numCaps != NumCaps) {
  2674. isError = TRUE;
  2675. }
  2676. }
  2677. else {
  2678. isError = TRUE;
  2679. }
  2680. }
  2681. else {
  2682. *CapsBuffer = NULL;
  2683. }
  2684. return (!isError);
  2685. }
  2686. BOOL
  2687. HIDTest_DoGetFreePpd(
  2688. IN HANDLE HidDevice
  2689. )
  2690. {
  2691. PHIDP_PREPARSED_DATA HidDevicePpd;
  2692. BOOL CallStatus;
  2693. CallStatus = HidD_GetPreparsedData(HidDevice, &HidDevicePpd);
  2694. if (CallStatus) {
  2695. CallStatus = HidD_FreePreparsedData(HidDevicePpd);
  2696. }
  2697. return (CallStatus);
  2698. }
  2699. BOOL
  2700. HIDTest_ValidateAttributes(
  2701. IN HANDLE HidDevice,
  2702. IN PHIDD_ATTRIBUTES Attrib
  2703. )
  2704. {
  2705. PHIDD_ATTRIBUTES HidDeviceAttrib;
  2706. BOOL CallStatus;
  2707. /*
  2708. // Allocate a test buffer to ensure that there are no problems with the
  2709. // memory filling done by HidD_GetAttributes
  2710. */
  2711. HidDeviceAttrib = (PHIDD_ATTRIBUTES) AllocateTestBuffer(sizeof(HIDD_ATTRIBUTES));
  2712. if (NULL == HidDeviceAttrib) {
  2713. LOG_TEST_ERROR("Couldn't allocate memory");
  2714. return (FALSE);
  2715. }
  2716. /*
  2717. // Attempt to get the attributes
  2718. */
  2719. CallStatus = HidD_GetAttributes(HidDevice, HidDeviceAttrib);
  2720. /*
  2721. // Check the buffer to make sure it wasn't improperly touched
  2722. */
  2723. if (!ValidateTestBuffer(HidDeviceAttrib)) {
  2724. LOG_BUFFER_VALIDATION_FAIL();
  2725. CallStatus = FALSE;
  2726. }
  2727. /*
  2728. // Make sure the attribute fields are correct as expected.
  2729. */
  2730. if (CallStatus) {
  2731. CallStatus = (HidDeviceAttrib -> Size == sizeof(HIDD_ATTRIBUTES)) &&
  2732. HIDTest_CompareAttributes(HidDeviceAttrib, Attrib);
  2733. }
  2734. FreeTestBuffer(HidDeviceAttrib);
  2735. return (CallStatus);
  2736. }
  2737. BOOL
  2738. HIDTest_ValidateCaps(
  2739. IN PHIDP_PREPARSED_DATA HidPpd,
  2740. IN PHIDP_CAPS HidCaps
  2741. )
  2742. {
  2743. HIDP_CAPS Caps;
  2744. NTSTATUS CallStatus;
  2745. BOOL BoolStatus;
  2746. BOOL TestStatus;
  2747. ULONG NumberLinkCollectionNodes;
  2748. PHIDP_LINK_COLLECTION_NODE LinkCollectionNodeList;
  2749. CallStatus = HidP_GetCaps(HidPpd, &Caps);
  2750. TestStatus = (HIDP_STATUS_SUCCESS == CallStatus) && (HIDTest_CompareCaps(HidCaps, &Caps));
  2751. /*
  2752. // We won't even bother proceeding any farther. This will catch the case where
  2753. // we pass in invalid ppd.
  2754. */
  2755. if (!TestStatus)
  2756. return (TestStatus);
  2757. /*
  2758. // Now come the real complicated part, we need to retrieve the following
  2759. // pieces of information concerning the current device
  2760. // 1) LinkCollectionNodes
  2761. // 2) ValueCaps for each report type
  2762. // 3) Button caps for each report type
  2763. // 4) Number of data indices for each report type
  2764. //
  2765. // From this information, we will verify each of the fields for its
  2766. // correctness. A comment on how each is performed will be included
  2767. // each test. These "tests" are actually variations.
  2768. */
  2769. /*
  2770. // Check that the number of link collection nodes from
  2771. // HidP_GetLinkCollectionNodes is the same as the number
  2772. // reported in the caps structure.
  2773. */
  2774. NumberLinkCollectionNodes = 0;
  2775. CallStatus = HidP_GetLinkCollectionNodes(NULL,
  2776. &NumberLinkCollectionNodes,
  2777. HidPpd
  2778. );
  2779. if (HIDP_STATUS_BUFFER_TOO_SMALL != CallStatus) {
  2780. LOG_UNEXPECTED_STATUS_WARNING("HidP_GetLinkCollectionNodes", CallStatus);
  2781. }
  2782. if (NumberLinkCollectionNodes != HidCaps -> NumberLinkCollectionNodes) {
  2783. LOG_INTERMEDIATE_VARIATION_RESULT("LinkCollectionNode counts don't match");
  2784. TestStatus = FALSE;
  2785. }
  2786. LinkCollectionNodeList = (PHIDP_LINK_COLLECTION_NODE) ALLOC(NumberLinkCollectionNodes * sizeof(HIDP_LINK_COLLECTION_NODE));
  2787. if (NULL == LinkCollectionNodeList) {
  2788. LOG_TEST_ERROR("Couldn't allocate memory");
  2789. return (FALSE);
  2790. }
  2791. CallStatus = HidP_GetLinkCollectionNodes(LinkCollectionNodeList,
  2792. &NumberLinkCollectionNodes,
  2793. HidPpd
  2794. );
  2795. if (HIDP_STATUS_SUCCESS != CallStatus) {
  2796. LOG_TEST_ERROR("Couldn't retrieve LinkCollectionNode info");
  2797. FREE(LinkCollectionNodeList);
  2798. return (FALSE);
  2799. }
  2800. /*
  2801. // Find the representative top-level collection in our
  2802. // LinkCollectionNodeList and verify that the UsagePage and
  2803. // Usage for the top-level collection match the same fields
  2804. // of the Caps structure. The top-level collection should
  2805. // be at index 0. We'll test this fact in the test that verifies
  2806. // the link collection node call
  2807. */
  2808. if ((LinkCollectionNodeList -> LinkUsagePage != HidCaps -> UsagePage) &&
  2809. (LinkCollectionNodeList -> LinkUsage != HidCaps -> Usage)) {
  2810. LOG_INTERMEDIATE_VARIATION_RESULT("Top level UsagePage/Usage don't match");
  2811. TestStatus = FALSE;
  2812. }
  2813. FREE(LinkCollectionNodeList);
  2814. /*
  2815. // Add code here to validate the buffer sizes. I'm not sure actual
  2816. // validation is possible. Why? Because the size of the buffer is
  2817. // dependent on how the report descriptor defines the buffer and
  2818. // unfortunately, two four bit wide fields can either be in separate
  2819. // bytes with padding in between or squeezed into one byte with no
  2820. // padding. At Ring3 and the calls available, the app cannot differentiate
  2821. // these cases.
  2822. */
  2823. /*
  2824. // Need to validate the number of button caps, value caps, and data indices
  2825. // for Input, Output and Feature Reports.
  2826. */
  2827. LOG_INTERMEDIATE_VARIATION_RESULT("Validating input buffer caps");
  2828. BoolStatus = HIDTest_ValidateBufferValues(HidP_Input,
  2829. HidCaps -> NumberInputButtonCaps,
  2830. HidCaps -> NumberInputValueCaps,
  2831. HidCaps -> NumberInputDataIndices,
  2832. HidPpd
  2833. );
  2834. if (!BoolStatus) {
  2835. LOG_INTERMEDIATE_VARIATION_RESULT("Failed Input Buffer Validation");
  2836. TestStatus = FALSE;
  2837. }
  2838. LOG_INTERMEDIATE_VARIATION_RESULT("Validating output buffer caps");
  2839. BoolStatus = HIDTest_ValidateBufferValues(HidP_Output,
  2840. HidCaps -> NumberOutputButtonCaps,
  2841. HidCaps -> NumberOutputValueCaps,
  2842. HidCaps -> NumberOutputDataIndices,
  2843. HidPpd
  2844. );
  2845. if (!BoolStatus) {
  2846. LOG_INTERMEDIATE_VARIATION_RESULT("Failed Output Buffer Validation");
  2847. TestStatus = FALSE;
  2848. }
  2849. LOG_INTERMEDIATE_VARIATION_RESULT("Validating feature buffer caps");
  2850. BoolStatus = HIDTest_ValidateBufferValues(HidP_Feature,
  2851. HidCaps -> NumberFeatureButtonCaps,
  2852. HidCaps -> NumberFeatureValueCaps,
  2853. HidCaps -> NumberFeatureDataIndices,
  2854. HidPpd
  2855. );
  2856. if (!BoolStatus) {
  2857. LOG_INTERMEDIATE_VARIATION_RESULT("Failed Feature Buffer Validation");
  2858. TestStatus = FALSE;
  2859. }
  2860. return (TestStatus);
  2861. }
  2862. BOOL
  2863. HIDTest_ValidateBufferValues(
  2864. IN HIDP_REPORT_TYPE ReportType,
  2865. IN USHORT NumButtonCaps,
  2866. IN USHORT NumValueCaps,
  2867. IN USHORT NumDataIndices,
  2868. IN PHIDP_PREPARSED_DATA Ppd
  2869. )
  2870. {
  2871. USHORT ReportedButtonCaps;
  2872. USHORT ReportedValueCaps;
  2873. ULONG MaxDataIndex;
  2874. ULONG Index;
  2875. ULONG RangeIndex;
  2876. NTSTATUS CallStatus;
  2877. BOOL BoolStatus;
  2878. BOOL TestStatus;
  2879. PHIDP_BUTTON_CAPS ButtonCapsList;
  2880. PHIDP_BUTTON_CAPS ButtonCapsWalk;
  2881. PHIDP_VALUE_CAPS ValueCapsList;
  2882. PHIDP_VALUE_CAPS ValueCapsWalk;
  2883. DATA_INDEX_LIST DataIndexList;
  2884. /*
  2885. // In order to verify the buffer values, we need to perform the following
  2886. // things
  2887. //
  2888. // 1) Call GetButtonCaps to see how many button caps structures are reported
  2889. // 2) Call GetValueCaps to see how many value caps structures are reported
  2890. // 3) Retrieve the list of both the value caps and the button caps for
  2891. // the report type
  2892. // 4) Loop through the list and verifying that there are 0..NumDataIndices-1
  2893. // indices and no more and no less and that the data index values are
  2894. // also in that range.
  2895. */
  2896. TestStatus = TRUE;
  2897. ReportedButtonCaps = 0;
  2898. CallStatus = HidP_GetButtonCaps(ReportType,
  2899. NULL,
  2900. &ReportedButtonCaps,
  2901. Ppd
  2902. );
  2903. /*
  2904. // There are two error conditions that we should expect here...
  2905. // 1) HIDP_STATUS_BUFFER_TOO_SMALL -- If button caps do exist
  2906. // 2) HIDP_STATUS_SUCCESS -- If no button caps exist for the report
  2907. //
  2908. // If one of these two cases doesn't arise, we need to log the warning msg.
  2909. */
  2910. if ((ReportedButtonCaps > 0 && HIDP_STATUS_BUFFER_TOO_SMALL != CallStatus) ||
  2911. (0 == ReportedButtonCaps && HIDP_STATUS_SUCCESS != CallStatus)) {
  2912. LOG_UNEXPECTED_STATUS_WARNING("HidP_GetButtonCaps", CallStatus);
  2913. }
  2914. if (ReportedButtonCaps != NumButtonCaps) {
  2915. LOG_INTERMEDIATE_VARIATION_RESULT("ButtonCaps values don't match");
  2916. TestStatus = FALSE;
  2917. }
  2918. /*
  2919. // There are two error conditions that we should expect here...
  2920. // 1) HIDP_STATUS_BUFFER_TOO_SMALL -- If value caps do exist
  2921. // 2) HIDP_STATUS_SUCCESS -- If no value exist for the report
  2922. //
  2923. // If one of these two cases doesn't arise, we need to log the warning msg.
  2924. */
  2925. ReportedValueCaps = 0;
  2926. CallStatus = HidP_GetValueCaps(ReportType,
  2927. NULL,
  2928. &ReportedValueCaps,
  2929. Ppd
  2930. );
  2931. if ((ReportedButtonCaps > 0 && HIDP_STATUS_BUFFER_TOO_SMALL != CallStatus) ||
  2932. (0 == ReportedButtonCaps && HIDP_STATUS_SUCCESS != CallStatus)) {
  2933. LOG_UNEXPECTED_STATUS_WARNING("HidP_GetValueCaps", CallStatus);
  2934. }
  2935. if (ReportedValueCaps != NumValueCaps) {
  2936. LOG_INTERMEDIATE_VARIATION_RESULT("ValueCaps values don't match");
  2937. TestStatus = FALSE;
  2938. }
  2939. /*
  2940. // Now we've got some debug only checks...This arises do to the fact that
  2941. // we will still allocate memory even if buffer size is 0, but only in
  2942. // the debug version...If there is an error due to a retail version of
  2943. // the build we don't want to scare out the user...However, we would
  2944. // like to verify in debug that HIDPARSE ain't trashing memory
  2945. */
  2946. ButtonCapsList = NULL;
  2947. ValueCapsList = NULL;
  2948. if (0 != ReportedButtonCaps) {
  2949. /*
  2950. // Allocate space for a button caps list
  2951. */
  2952. ButtonCapsList = (PHIDP_BUTTON_CAPS) malloc(ReportedButtonCaps * sizeof(HIDP_BUTTON_CAPS));
  2953. if (NULL == ButtonCapsList) {
  2954. LOG_TEST_ERROR("Couldn't allocate memory");
  2955. return (FALSE);
  2956. }
  2957. /*
  2958. // Now that the lists have been allocated, let's try to retrieve those puppies
  2959. // once again. We should only get a return value of HIDP_STATUS_SUCCESS,
  2960. // any thing else would be an error.
  2961. */
  2962. CallStatus = HidP_GetButtonCaps(ReportType,
  2963. ButtonCapsList,
  2964. &ReportedButtonCaps,
  2965. Ppd
  2966. );
  2967. if (HIDP_STATUS_SUCCESS != CallStatus) {
  2968. LOG_UNEXPECTED_STATUS_WARNING("HidP_GetButtonCaps", CallStatus);
  2969. TestStatus = FALSE;
  2970. }
  2971. }
  2972. /*
  2973. // Build the value caps list if one exists
  2974. */
  2975. if (0 != ReportedValueCaps) {
  2976. /*
  2977. // Allocate space for a value caps list
  2978. */
  2979. ValueCapsList = (PHIDP_VALUE_CAPS) malloc(ReportedValueCaps * sizeof(HIDP_VALUE_CAPS));
  2980. if (NULL == ValueCapsList) {
  2981. LOG_TEST_ERROR("Couldn't allocate memory");
  2982. FREE(ButtonCapsList);
  2983. return (FALSE);
  2984. }
  2985. /*
  2986. // Ditto the above comment for ValueCaps
  2987. */
  2988. CallStatus = HidP_GetValueCaps(ReportType,
  2989. ValueCapsList,
  2990. &ReportedValueCaps,
  2991. Ppd
  2992. );
  2993. if (HIDP_STATUS_SUCCESS != CallStatus) {
  2994. LOG_UNEXPECTED_STATUS_WARNING("HidP_GetValueCaps", CallStatus);
  2995. TestStatus = FALSE;
  2996. }
  2997. }
  2998. /*
  2999. // Time to verify the number of data indices for the buffer. To do so,
  3000. // we pass through both the button caps list and the value caps list and
  3001. // mark each one of the data indices report in that list. If all the
  3002. // all the data indices that are report is equivalent to the number of data
  3003. // indices reported in the caps structure and the appropriate data indices
  3004. // we marked, then we consider this to have passed.
  3005. */
  3006. if (0 == NumDataIndices) {
  3007. if (ReportedButtonCaps + ReportedValueCaps > 0) {
  3008. LOG_INTERMEDIATE_VARIATION_RESULT("No data indices although Button/Value Caps exist");
  3009. TestStatus = FALSE;
  3010. }
  3011. else {
  3012. LOG_INTERMEDIATE_VARIATION_RESULT("No data indices to verify");
  3013. }
  3014. }
  3015. else {
  3016. /*
  3017. // The maximum data index value should be one less than the number
  3018. // of report data indices since the data index range is 0 --> Number-1
  3019. */
  3020. MaxDataIndex = NumDataIndices - 1;
  3021. BoolStatus = HIDTest_InitDataIndexList(MaxDataIndex,
  3022. &DataIndexList
  3023. );
  3024. if (!BoolStatus) {
  3025. LOG_TEST_ERROR("Couldn't initialize data index list");
  3026. if (NULL != ButtonCapsList) {
  3027. free(ButtonCapsList);
  3028. }
  3029. if (NULL != ValueCapsList) {
  3030. free(ValueCapsList);
  3031. }
  3032. return (FALSE);
  3033. }
  3034. /*
  3035. // Begin by walking the button caps list and marking all the data indices
  3036. // reported in that list.
  3037. */
  3038. ButtonCapsWalk = ButtonCapsList;
  3039. for (Index = 0; Index < ReportedButtonCaps; Index++, ButtonCapsWalk++) {
  3040. if (ButtonCapsWalk -> IsRange) {
  3041. for (RangeIndex = ButtonCapsWalk -> Range.DataIndexMin;
  3042. RangeIndex <= ButtonCapsWalk -> Range.DataIndexMax;
  3043. RangeIndex++) {
  3044. BoolStatus = HIDTest_MarkDataIndex(&DataIndexList,
  3045. RangeIndex
  3046. );
  3047. if (!BoolStatus) {
  3048. LOG_INTERMEDIATE_VARIATION_RESULT("Bad button data index");
  3049. TestStatus = FALSE;
  3050. }
  3051. }
  3052. }
  3053. else {
  3054. BoolStatus = HIDTest_MarkDataIndex(&DataIndexList,
  3055. ButtonCapsWalk -> NotRange.DataIndex
  3056. );
  3057. if (!BoolStatus) {
  3058. LOG_INTERMEDIATE_VARIATION_RESULT("Bad button data index");
  3059. TestStatus = FALSE;
  3060. }
  3061. }
  3062. }
  3063. /*
  3064. // Walk the value caps list and mark all the data indices report there
  3065. // as well.
  3066. */
  3067. ValueCapsWalk = ValueCapsList;
  3068. for (Index = 0; Index < ReportedValueCaps; Index++, ValueCapsWalk++) {
  3069. if (ValueCapsWalk -> IsRange) {
  3070. for (RangeIndex = ValueCapsWalk -> Range.DataIndexMin;
  3071. RangeIndex <= ValueCapsWalk -> Range.DataIndexMax;
  3072. RangeIndex++) {
  3073. BoolStatus = HIDTest_MarkDataIndex(&DataIndexList,
  3074. RangeIndex
  3075. );
  3076. if (!BoolStatus) {
  3077. LOG_INTERMEDIATE_VARIATION_RESULT("Bad value data index");
  3078. TestStatus = FALSE;
  3079. }
  3080. }
  3081. }
  3082. else {
  3083. BoolStatus = HIDTest_MarkDataIndex(&DataIndexList,
  3084. ValueCapsWalk -> NotRange.DataIndex
  3085. );
  3086. if (!BoolStatus) {
  3087. LOG_INTERMEDIATE_VARIATION_RESULT("Bad value data index");
  3088. TestStatus = FALSE;
  3089. }
  3090. }
  3091. }
  3092. /*
  3093. // Check that all the data indices have been properly used.
  3094. */
  3095. if (!HIDTest_AreAllIndicesUsed(&DataIndexList)) {
  3096. LOG_INTERMEDIATE_VARIATION_RESULT("Unused data indices in data index list");
  3097. TestStatus = FALSE;
  3098. }
  3099. HIDTest_FreeDataIndexList(&DataIndexList);
  3100. }
  3101. if (NULL != ButtonCapsList) {
  3102. free(ButtonCapsList);
  3103. }
  3104. if (NULL != ValueCapsList) {
  3105. free(ValueCapsList);
  3106. }
  3107. return (TestStatus);
  3108. }
  3109. BOOL
  3110. HIDTest_CompareCaps(
  3111. IN PHIDP_CAPS Caps1,
  3112. IN PHIDP_CAPS Caps2
  3113. )
  3114. {
  3115. /*
  3116. // This could very well be implemented as a macro like CompareAttributes
  3117. // was, however, there are a lot of fields to compare so easier to define
  3118. // as function
  3119. */
  3120. return ((Caps1 -> UsagePage == Caps2 -> UsagePage) &&
  3121. (Caps1 -> Usage == Caps2 -> Usage) &&
  3122. (Caps1 -> InputReportByteLength == Caps2 -> InputReportByteLength) &&
  3123. (Caps1 -> OutputReportByteLength == Caps2 -> OutputReportByteLength) &&
  3124. (Caps1 -> FeatureReportByteLength == Caps2 -> FeatureReportByteLength) &&
  3125. (Caps1 -> NumberLinkCollectionNodes == Caps2 -> NumberLinkCollectionNodes) &&
  3126. (Caps1 -> NumberInputButtonCaps == Caps2 -> NumberInputButtonCaps) &&
  3127. (Caps1 -> NumberInputValueCaps == Caps2 -> NumberInputValueCaps) &&
  3128. (Caps1 -> NumberInputDataIndices == Caps2 -> NumberInputDataIndices) &&
  3129. (Caps1 -> NumberOutputButtonCaps == Caps2 -> NumberOutputButtonCaps) &&
  3130. (Caps1 -> NumberOutputValueCaps == Caps2 -> NumberOutputValueCaps) &&
  3131. (Caps1 -> NumberOutputDataIndices == Caps2 -> NumberOutputDataIndices) &&
  3132. (Caps1 -> NumberFeatureButtonCaps == Caps2 -> NumberFeatureButtonCaps) &&
  3133. (Caps1 -> NumberFeatureValueCaps == Caps2 -> NumberFeatureValueCaps) &&
  3134. (Caps1 -> NumberFeatureDataIndices == Caps2 -> NumberFeatureDataIndices)
  3135. );
  3136. }
  3137. /*****************************************************************************
  3138. /* Functions related to tracking data indices
  3139. /*****************************************************************************/
  3140. BOOL
  3141. HIDTest_InitDataIndexList(
  3142. IN ULONG MaxDataIndex,
  3143. OUT PDATA_INDEX_LIST IndexList
  3144. )
  3145. {
  3146. ULONG Index;
  3147. IndexList -> List = (BOOL *) ALLOC((MaxDataIndex+1) * sizeof(BOOL));
  3148. IndexList -> MaxDataIndex = MaxDataIndex;
  3149. if (NULL != IndexList -> List) {
  3150. for (Index = 0; Index <= MaxDataIndex; Index++) {
  3151. IndexList -> List[Index] = FALSE;
  3152. }
  3153. }
  3154. return (NULL != IndexList -> List);
  3155. }
  3156. VOID
  3157. HIDTest_FreeDataIndexList(
  3158. IN PDATA_INDEX_LIST IndexList
  3159. )
  3160. {
  3161. ASSERT (NULL != IndexList -> List);
  3162. FREE(IndexList -> List);
  3163. IndexList -> List = NULL;
  3164. return;
  3165. }
  3166. BOOL
  3167. HIDTest_MarkDataIndex(
  3168. IN PDATA_INDEX_LIST IndexList,
  3169. IN ULONG IndexValue
  3170. )
  3171. {
  3172. BOOL OldValue;
  3173. if (IndexValue > IndexList -> MaxDataIndex) {
  3174. return (FALSE);
  3175. }
  3176. OldValue = IndexList -> List[IndexValue];
  3177. IndexList -> List[IndexValue] = TRUE;
  3178. return (!OldValue);
  3179. }
  3180. BOOL
  3181. HIDTest_GetDataIndexStatus(
  3182. IN PDATA_INDEX_LIST IndexList,
  3183. IN ULONG IndexValue
  3184. )
  3185. {
  3186. ASSERT (NULL != IndexList -> List);
  3187. ASSERT (IndexValue <= IndexList -> MaxDataIndex);
  3188. return (IndexList -> List[IndexValue]);
  3189. }
  3190. BOOL
  3191. HIDTest_AreAllIndicesUsed(
  3192. IN PDATA_INDEX_LIST IndexList
  3193. )
  3194. {
  3195. ULONG Index;
  3196. ASSERT (NULL != IndexList -> List);
  3197. for (Index = 0; Index <= IndexList -> MaxDataIndex; Index++) {
  3198. if (!(IndexList -> List[Index])) {
  3199. return (FALSE);
  3200. }
  3201. }
  3202. return (TRUE);
  3203. }
  3204. /*****************************************************************************
  3205. /* Functions to track the availibility of strings for a device
  3206. /****************************************************************************/
  3207. BOOL
  3208. HIDTest_DoesStringExist(
  3209. HANDLE DeviceHandle,
  3210. ULONG StringIndex,
  3211. PWCHAR *String,
  3212. PULONG StringLength,
  3213. BOOL *StringExists
  3214. )
  3215. {
  3216. WCHAR TempChar;
  3217. ULONG StringSize;
  3218. BOOL CallStatus;
  3219. BOOL TestStatus;
  3220. ULONG ErrorCode;
  3221. /*
  3222. // We will use the TempChar variable first, just to determine if the
  3223. // string exists. If it HidD_GetIndexedString returns TRUE, then
  3224. // the string exists and we'll try to figure out it's actual length
  3225. // and create a buffer for it
  3226. */
  3227. *String = NULL;
  3228. *StringLength = 0;
  3229. TestStatus = TRUE;
  3230. CallStatus = HIDTest_GetString(DeviceHandle,
  3231. StringIndex,
  3232. &TempChar,
  3233. sizeof(TempChar),
  3234. &ErrorCode
  3235. );
  3236. /*
  3237. // If the GetString call returned FALSE, we need to examine the error code
  3238. // that was returned using GetLastError(). A return of FALSE can mean
  3239. // one of the following two things.
  3240. // 1) String index not supported by the device (ERROR_GEN_FAILURE)
  3241. // 2) String index is supported by the device but a big
  3242. // enough buffer wasn't passed down (ERROR_INVALID_USER_BUFFER)
  3243. */
  3244. if (!CallStatus) {
  3245. switch (ErrorCode) {
  3246. case ERROR_GEN_FAILURE:
  3247. /*
  3248. // This case is added here since NT5 string getting is currently
  3249. // busted
  3250. */
  3251. case ERROR_NOACCESS:
  3252. *StringExists = FALSE;
  3253. break;
  3254. case ERROR_INVALID_USER_BUFFER:
  3255. *StringExists = TRUE;
  3256. break;
  3257. default:
  3258. LOG_INTERMEDIATE_VARIATION_RESULT("Unknown HidD_GetIndexedString error code returned");
  3259. TestStatus = FALSE;
  3260. *StringExists = FALSE;
  3261. }
  3262. }
  3263. if (!*StringExists) {
  3264. return (TestStatus);
  3265. }
  3266. /*
  3267. // OK, so the string actually exists. Now, let's try to create a buffer
  3268. // to get the string length. Will start with 8 chararcters and double that
  3269. // size until we find a buffer which can hold the whole string
  3270. */
  3271. StringSize = 8;
  3272. while (NULL != (*String = (PWCHAR) AllocateTestBuffer(StringSize*sizeof(WCHAR)))) {
  3273. CallStatus = HIDTest_GetString(DeviceHandle,
  3274. StringIndex,
  3275. *String,
  3276. StringSize*sizeof(WCHAR),
  3277. &ErrorCode
  3278. );
  3279. if (!ValidateTestBuffer(*String)) {
  3280. LOG_BUFFER_VALIDATION_FAIL();
  3281. FreeTestBuffer(*String);
  3282. return (FALSE);
  3283. }
  3284. if (!CallStatus) {
  3285. switch (ErrorCode) {
  3286. /*
  3287. // We simply do nothing, since the loop will end up being
  3288. // repeated and a new buffer will be allocated
  3289. */
  3290. case ERROR_INVALID_USER_BUFFER:
  3291. break;
  3292. /*
  3293. // This error message is bad because it means a call to
  3294. // GetString passed before but now fails for some
  3295. // reason.
  3296. */
  3297. case ERROR_GEN_FAILURE:
  3298. /*
  3299. // Ditto the above about NT5 not properly handling error status
  3300. */
  3301. case ERROR_NOACCESS:
  3302. LOG_INTERMEDIATE_VARIATION_RESULT("Unexpected failure of string call");
  3303. TestStatus = FALSE;
  3304. break;
  3305. default:
  3306. LOG_INTERMEDIATE_VARIATION_RESULT("Unknown String error code returned");
  3307. TestStatus = FALSE;
  3308. }
  3309. }
  3310. /*
  3311. // We got the correct string now, however, it's still possible
  3312. // that we don't have the terminating zero. We'll call GetWideStringLength
  3313. // to determine that for us.
  3314. */
  3315. else {
  3316. CallStatus = HIDTest_GetWideStringLength(*String, StringSize, StringLength);
  3317. /*
  3318. // If CallStatus is TRUE, then the correct string length was found
  3319. // and we can break from this loop
  3320. */
  3321. if (CallStatus) {
  3322. break;
  3323. }
  3324. }
  3325. /*
  3326. // Otherwise, we need to free the previous buffer and allocate another
  3327. // larger buffer
  3328. */
  3329. FreeTestBuffer(*String);
  3330. StringSize *= 2;
  3331. }
  3332. if (NULL == *String) {
  3333. LOG_TEST_ERROR("Test Error - Memory allocation failed");
  3334. TestStatus = FALSE;
  3335. }
  3336. return (TestStatus);
  3337. }
  3338. BOOL
  3339. HIDTest_GetWideStringLength(
  3340. PWCHAR String,
  3341. ULONG StringSize,
  3342. PULONG StringLength
  3343. )
  3344. {
  3345. ULONG StringIndex;
  3346. for (StringIndex = 0; StringIndex < StringSize; StringIndex++) {
  3347. if ((WCHAR) '\0' == *(String+StringIndex)) {
  3348. *StringLength = StringIndex;
  3349. return (TRUE);
  3350. }
  3351. }
  3352. return (FALSE);
  3353. }
  3354. BOOL
  3355. HIDTest_BuildStringList(
  3356. HANDLE DeviceHandle,
  3357. PLIST StringList
  3358. )
  3359. {
  3360. ULONG StringIndex;
  3361. BOOL CallStatus;
  3362. PWCHAR DeviceString;
  3363. ULONG StringLength;
  3364. BOOL StringExist;
  3365. static CHAR ErrorString[128];
  3366. InitializeList(StringList);
  3367. for (StringIndex = 0; StringIndex < STRINGS_TO_TEST; StringIndex++) {
  3368. CallStatus = HIDTest_DoesStringExist(DeviceHandle,
  3369. StringIndex,
  3370. &DeviceString,
  3371. &StringLength,
  3372. &StringExist
  3373. );
  3374. if (!CallStatus) {
  3375. wsprintf(ErrorString,
  3376. "Test Error: Error determining if string %u exists",
  3377. StringIndex
  3378. );
  3379. LOG_TEST_ERROR(ErrorString);
  3380. HIDTest_FreeStringList(StringList);
  3381. return (FALSE);
  3382. }
  3383. else if (StringExist) {
  3384. CallStatus = HIDTest_AddStringToStringList(StringList,
  3385. StringIndex,
  3386. DeviceString,
  3387. StringLength
  3388. );
  3389. if (!CallStatus) {
  3390. wsprintf(ErrorString,
  3391. "Test Error: Error adding string %u to list",
  3392. StringIndex
  3393. );
  3394. LOG_TEST_ERROR(ErrorString);
  3395. FreeTestBuffer(DeviceString);
  3396. HIDTest_FreeStringList(StringList);
  3397. return (FALSE);
  3398. }
  3399. }
  3400. }
  3401. return (TRUE);
  3402. }
  3403. VOID
  3404. HIDTest_FreeStringList(
  3405. PLIST StringList
  3406. )
  3407. {
  3408. DestroyListWithCallback(StringList,
  3409. HIDTest_FreeStringNodeCallback
  3410. );
  3411. return;
  3412. }
  3413. VOID
  3414. HIDTest_FreeStringNodeCallback(
  3415. PLIST_NODE_HDR ListNode
  3416. )
  3417. {
  3418. PSTRING_LIST_NODE currNode;
  3419. currNode = (PSTRING_LIST_NODE) ListNode;
  3420. FreeTestBuffer(currNode -> String);
  3421. FREE(currNode);
  3422. return;
  3423. }
  3424. BOOL
  3425. HIDTest_AddStringToStringList(
  3426. PLIST StringList,
  3427. ULONG StringIndex,
  3428. PWCHAR String,
  3429. ULONG StringLength
  3430. )
  3431. {
  3432. PSTRING_LIST_NODE listNode;
  3433. /*
  3434. // To add a string to the string list, we need to do the following steps
  3435. // 1) If the string list is at it's maximum size or is NULL, need to
  3436. // alloc a new block
  3437. // 2) Find the end of the list and add the appropriate information there
  3438. // 3) Increment the number of strings in the list
  3439. //
  3440. // This function will assume that string indices will be added in increasing
  3441. // numerical order so that no sorting routine will have to be implemented
  3442. // This is a legitimate assumption since the BuildStringList begins with
  3443. // string zero and searchs through it's maximum for strings. Since this
  3444. // is the only caller of the AddStringToStringList, it will only add
  3445. // string indices in increasing order. If this assumption needs to change,
  3446. // it will require a little more computation to keep the list sorted
  3447. */
  3448. listNode = (PSTRING_LIST_NODE) ALLOC(sizeof(STRING_LIST_NODE));
  3449. if (NULL == listNode) {
  3450. return (FALSE);
  3451. }
  3452. listNode -> StringIndex = StringIndex;
  3453. listNode -> String = String;
  3454. listNode -> StringLength = StringLength;
  3455. InsertTail(StringList, listNode);
  3456. return (TRUE);
  3457. }
  3458. BOOL
  3459. HIDTest_IsStringInStrList(
  3460. PLIST StringList,
  3461. PWCHAR String,
  3462. ULONG StringLength,
  3463. PSTRING_LIST_NODE StringNode
  3464. )
  3465. {
  3466. /*
  3467. // Searching the string list for a given string is not as easy as searching
  3468. // the string list for a given string index since the strings are stored in
  3469. // in index order not alphabetical order. Therefore, we cannot perform
  3470. // any sort of binary search to deal with this case and must linearly
  3471. // search the list before we can determine that a given string does
  3472. // not exist in the list
  3473. */
  3474. PSTRING_LIST_NODE currNode;
  3475. currNode = (PSTRING_LIST_NODE) GetListHead(StringList);
  3476. while (currNode != (PSTRING_LIST_NODE) StringList) {
  3477. if (HIDTest_CompareStrings(currNode -> String,
  3478. currNode -> StringLength,
  3479. String,
  3480. StringLength
  3481. )) {
  3482. *StringNode = *currNode;
  3483. return (TRUE);
  3484. }
  3485. currNode = (PSTRING_LIST_NODE) GetNextEntry(currNode);
  3486. }
  3487. return (FALSE);
  3488. }
  3489. BOOL
  3490. HIDTest_IsStrIndexInStrList(
  3491. PLIST StringList,
  3492. ULONG StringIndex,
  3493. PSTRING_LIST_NODE StringNode
  3494. )
  3495. {
  3496. PSTRING_LIST_NODE currNode;
  3497. currNode = (PSTRING_LIST_NODE) GetListHead(StringList);
  3498. while (currNode != (PSTRING_LIST_NODE) StringList) {
  3499. if (currNode -> StringIndex == StringIndex) {
  3500. *StringNode = *currNode;
  3501. return (TRUE);
  3502. }
  3503. else if (currNode -> StringIndex > StringIndex) {
  3504. return (FALSE);
  3505. }
  3506. currNode = (PSTRING_LIST_NODE) GetNextEntry(currNode);
  3507. }
  3508. return (FALSE);
  3509. }
  3510. BOOL
  3511. HIDTest_CompareStringLists(
  3512. PLIST StringList1,
  3513. PLIST StringList2
  3514. )
  3515. {
  3516. PSTRING_LIST_NODE node1;
  3517. PSTRING_LIST_NODE node2;
  3518. /*
  3519. // Comparing two string lists is a relatively simple process since we
  3520. // are only looking for whether they are equal and not where they differ.
  3521. // Plus, our string lists should both be in index string order.
  3522. //
  3523. // To do the comparison, all that needs to be done is traverse both
  3524. // lists from the beginning. If at any point, either the indices
  3525. // or the string values don't match, we can return FALSE
  3526. */
  3527. node1 = (PSTRING_LIST_NODE) GetListHead(StringList1);
  3528. node2 = (PSTRING_LIST_NODE) GetListHead(StringList2);
  3529. while (node1 != (PSTRING_LIST_NODE) StringList1 && node2 != (PSTRING_LIST_NODE) StringList2) {
  3530. if ((node1 -> StringIndex != node2 -> StringIndex) ||
  3531. (!HIDTest_CompareStrings(node1 -> String,
  3532. node1 -> StringLength,
  3533. node2 -> String,
  3534. node2 -> StringLength
  3535. ))) {
  3536. return (FALSE);
  3537. }
  3538. node1 = (PSTRING_LIST_NODE) GetNextEntry(node1);
  3539. node2 = (PSTRING_LIST_NODE) GetNextEntry(node2);
  3540. }
  3541. return (TRUE);
  3542. }
  3543. BOOL
  3544. HIDTest_ValidateStdStrings(
  3545. HANDLE DeviceHandle,
  3546. PLIST CurrentStringList,
  3547. ULONG ManufacturerStringIndex,
  3548. ULONG ProductStringIndex,
  3549. ULONG SerialNumberStringIndex
  3550. )
  3551. {
  3552. PWCHAR DeviceString;
  3553. ULONG StringLength;
  3554. BOOL TestStatus;
  3555. BOOL CallStatus;
  3556. PCHAR StringTypeDesc;
  3557. ULONG StringIndex;
  3558. BOOL StringExist;
  3559. ULONG indexValue;
  3560. static CHAR ErrorString[128];
  3561. STRING_LIST_NODE stringNode;
  3562. /*
  3563. // To verify the standard strings, we need to the following steps
  3564. // for each of the strings (manufacturer, product, serial number)
  3565. //
  3566. // 1) Attempt to retrieve the string...
  3567. // 2) If the string doesn't exist, need to verify that the passed
  3568. // in StringIndex is == NO_STRING_INDEX
  3569. // 3) If the string exists, need to search the current string list
  3570. // to get the index and then compare that index value with the
  3571. // index value for the given string
  3572. */
  3573. /*
  3574. // Begin with the manufacturer string and work our way up from there
  3575. // The following asserts verify that the macros that have been defined
  3576. // above are still in numerical order
  3577. */
  3578. ASSERT(STRING_INDEX_MANUFACTURER+1 == STRING_INDEX_PRODUCT);
  3579. ASSERT(STRING_INDEX_PRODUCT+1 == STRING_INDEX_SERIAL_NUMBER);
  3580. TestStatus = TRUE;
  3581. for (StringIndex = STRING_INDEX_MANUFACTURER; StringIndex <= STRING_INDEX_SERIAL_NUMBER; StringIndex++) {
  3582. CallStatus = HIDTest_DoesStringExist(DeviceHandle,
  3583. StringIndex,
  3584. &DeviceString,
  3585. &StringLength,
  3586. &StringExist
  3587. );
  3588. switch (StringIndex) {
  3589. case STRING_INDEX_MANUFACTURER:
  3590. indexValue = ManufacturerStringIndex;
  3591. StringTypeDesc = "Manufacturer";
  3592. break;
  3593. case STRING_INDEX_PRODUCT:
  3594. indexValue = ProductStringIndex;
  3595. StringTypeDesc = "Product";
  3596. break;
  3597. case STRING_INDEX_SERIAL_NUMBER:
  3598. indexValue = SerialNumberStringIndex;
  3599. StringTypeDesc = "Serial number";
  3600. break;
  3601. }
  3602. if (!CallStatus) {
  3603. wsprintf(ErrorString,
  3604. "Test Error: Error determining if string %u exists",
  3605. StringIndex
  3606. );
  3607. LOG_TEST_ERROR(ErrorString);
  3608. return (FALSE);
  3609. }
  3610. else if (!StringExist) {
  3611. if (indexValue != NO_STRING_INDEX) {
  3612. wsprintf(ErrorString, "Mismatch: %s string not returned", StringTypeDesc);
  3613. TestStatus = FALSE;
  3614. }
  3615. else {
  3616. wsprintf(ErrorString, "%s string not found", StringTypeDesc);
  3617. }
  3618. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  3619. }
  3620. else {
  3621. CallStatus = HIDTest_IsStringInStrList(CurrentStringList,
  3622. DeviceString,
  3623. StringLength,
  3624. &stringNode
  3625. );
  3626. if (!CallStatus) {
  3627. wsprintf(ErrorString, "%s string could not be found in string list", StringTypeDesc);
  3628. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  3629. TestStatus = FALSE;
  3630. }
  3631. else {
  3632. if (indexValue != stringNode.StringIndex) {
  3633. wsprintf(ErrorString, "Mismatched index: %s string", StringTypeDesc);
  3634. TestStatus = FALSE;
  3635. }
  3636. else {
  3637. wsprintf(ErrorString, "%s string found in the string list", StringTypeDesc);
  3638. }
  3639. LOG_INTERMEDIATE_VARIATION_RESULT(ErrorString);
  3640. }
  3641. FreeTestBuffer(DeviceString);
  3642. }
  3643. }
  3644. return (TestStatus);
  3645. }
  3646. BOOL
  3647. HIDTest_GetString(
  3648. HANDLE DeviceHandle,
  3649. ULONG StringIndex,
  3650. PWCHAR StringBuffer,
  3651. ULONG BufferLength,
  3652. PULONG ErrorCode
  3653. )
  3654. {
  3655. BOOL CallStatus;
  3656. switch (StringIndex) {
  3657. case STRING_INDEX_MANUFACTURER:
  3658. CallStatus = HidD_GetManufacturerString(DeviceHandle,
  3659. StringBuffer,
  3660. BufferLength
  3661. );
  3662. break;
  3663. case STRING_INDEX_PRODUCT:
  3664. CallStatus = HidD_GetProductString(DeviceHandle,
  3665. StringBuffer,
  3666. BufferLength
  3667. );
  3668. break;
  3669. case STRING_INDEX_SERIAL_NUMBER:
  3670. CallStatus = HidD_GetSerialNumberString(DeviceHandle,
  3671. StringBuffer,
  3672. BufferLength
  3673. );
  3674. break;
  3675. default:
  3676. CallStatus = HidD_GetIndexedString(DeviceHandle,
  3677. StringIndex,
  3678. StringBuffer,
  3679. BufferLength
  3680. );
  3681. }
  3682. *ErrorCode = GetLastError();
  3683. return (CallStatus);
  3684. }
  3685. BOOL
  3686. HIDTest_BuildReportIDList(
  3687. IN PHIDP_VALUE_CAPS VCaps,
  3688. IN ULONG NumVCaps,
  3689. IN PHIDP_BUTTON_CAPS BCaps,
  3690. IN ULONG NumBCaps,
  3691. IN PUCHAR *ReportIDs,
  3692. IN PULONG ReportIDCount
  3693. )
  3694. {
  3695. BOOL usingReportIDs;
  3696. ULONG maxReportIDs;
  3697. usingReportIDs = FALSE;
  3698. *ReportIDCount = 0;
  3699. if (0 != NumVCaps) {
  3700. usingReportIDs = VCaps -> ReportID != 0;
  3701. }
  3702. else if (0 != NumBCaps) {
  3703. usingReportIDs = BCaps -> ReportID != 0;
  3704. }
  3705. else {
  3706. /*
  3707. // We're not actually using report IDs in the is case, but it will
  3708. // get set to TRUE anyway because both lists are empty. Doing so,
  3709. // will cause us to dump out of the routine early.
  3710. */
  3711. usingReportIDs = TRUE;
  3712. }
  3713. /*
  3714. // We'll allocate a buffer that can hold the maximum number of report
  3715. // IDs that can possible exist for these values. Most likely, we'll
  3716. // allocate a buffer that is too big. This can be optimized later if
  3717. // necessary.
  3718. */
  3719. if (usingReportIDs) {
  3720. maxReportIDs = NumVCaps + NumBCaps;
  3721. }
  3722. else {
  3723. maxReportIDs = 1;
  3724. }
  3725. if (0 == maxReportIDs) {
  3726. *ReportIDs = NULL;
  3727. return (TRUE);
  3728. }
  3729. *ReportIDs = (PUCHAR) malloc (maxReportIDs * sizeof(UCHAR));
  3730. if (NULL == *ReportIDs) {
  3731. return (FALSE);
  3732. }
  3733. /*
  3734. // We've allocated the buffer, now let's fill it.
  3735. // To do so, we need to trace through each of the lists, get the
  3736. // report ID, search the current list. If found in the current list of
  3737. // IDs, we ignore and proceed to the next. Otherwise, we need to bump
  3738. // all the other IDs that are greater than this one down one spot in the
  3739. // buffer and add this new ID. Doing so will guarantee that the buffer
  3740. // we are creating will be in sorted order.
  3741. */
  3742. while (NumVCaps--) {
  3743. HIDTest_InsertIDIntoList(*ReportIDs, ReportIDCount, VCaps -> ReportID);
  3744. VCaps++;
  3745. }
  3746. while (NumBCaps--) {
  3747. HIDTest_InsertIDIntoList(*ReportIDs, ReportIDCount, BCaps -> ReportID);
  3748. BCaps++;
  3749. }
  3750. return (TRUE);
  3751. }
  3752. VOID
  3753. HIDTest_InsertIDIntoList(
  3754. IN PUCHAR ReportIDs,
  3755. IN PULONG ReportIDCount,
  3756. IN UCHAR NewID
  3757. )
  3758. {
  3759. UCHAR listReportID;
  3760. ULONG listIndex;
  3761. BOOL insertIntoList;
  3762. for (listIndex = 0, insertIntoList = TRUE; listIndex < *ReportIDCount; listIndex++) {
  3763. listReportID = *(ReportIDs + listIndex);
  3764. if (listReportID == NewID) {
  3765. insertIntoList = FALSE;
  3766. break;
  3767. }
  3768. else if (listReportID > NewID) {
  3769. memmove(ReportIDs + listIndex + 1,
  3770. ReportIDs + listIndex,
  3771. (*ReportIDCount) - listIndex * sizeof(UCHAR)
  3772. );
  3773. break;
  3774. }
  3775. }
  3776. if (insertIntoList) {
  3777. *(ReportIDs + listIndex) = NewID;
  3778. (*ReportIDCount)++;
  3779. }
  3780. return;
  3781. }
  3782. BOOL
  3783. HIDTest_IsIDInList(
  3784. IN UCHAR ReportID,
  3785. IN PUCHAR ReportIDList,
  3786. IN ULONG ReportIDListCount
  3787. )
  3788. {
  3789. ULONG idIndex;
  3790. BOOL found;
  3791. found = FALSE;
  3792. for (idIndex = 0; idIndex < ReportIDListCount; idIndex++) {
  3793. if (ReportID == *(ReportIDList+idIndex)) {
  3794. found = TRUE;
  3795. break;
  3796. }
  3797. else if (ReportID < *(ReportIDList+idIndex)) {
  3798. break;
  3799. }
  3800. }
  3801. return (found);
  3802. }