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.

644 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract
  6. Debug/performance routines
  7. Author:
  8. Ervin P.
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #if DBG
  15. // can poke this in the debugger to trap for warnings
  16. BOOLEAN dbgTrapOnWarn = FALSE;
  17. BOOLEAN dbgTrapOnSS = FALSE;
  18. BOOLEAN dbgVerbose = FALSE;
  19. BOOLEAN dbgInfo = TRUE;
  20. BOOLEAN dbgSkipSecurity = FALSE;
  21. BOOLEAN dbgTrapOnHiccup = FALSE;
  22. ULONG dbgLastEntry = 0;
  23. ULONG dbgInHidclass = 0;
  24. VOID DbgCommonEntryExit(BOOLEAN isEntering)
  25. {
  26. if (isEntering){
  27. dbgInHidclass++;
  28. #ifdef _X86_
  29. _asm nop
  30. _asm mov eax, [ebp+4] /* <- set breakpt here */
  31. _asm mov dbgLastEntry, eax
  32. #endif
  33. }
  34. else {
  35. dbgInHidclass--;
  36. }
  37. }
  38. VOID InitFdoExtDebugInfo(PHIDCLASS_DEVICE_EXTENSION hidclassExt)
  39. {
  40. FDO_EXTENSION *fdoExt = &hidclassExt->fdoExt;
  41. NTSTATUS status;
  42. ULONG actualLen;
  43. status = IoGetDeviceProperty( hidclassExt->hidExt.PhysicalDeviceObject,
  44. DevicePropertyDriverKeyName,
  45. sizeof(fdoExt->dbgDriverKeyName),
  46. fdoExt->dbgDriverKeyName,
  47. &actualLen);
  48. if (!NT_SUCCESS(status)) {
  49. //
  50. // We couldn't get the driver key name. This will happen during
  51. // textmode setup on NT, for example, when we're loaded as part of
  52. // bootstrapping the system (long before the device installer/class
  53. // installer have run).
  54. //
  55. // Simply initialize the driver key name field to an empty string.
  56. //
  57. *(fdoExt->dbgDriverKeyName) = L'\0';
  58. }
  59. }
  60. ULONG dbgMinInterruptDelta = 0x0fffffff;
  61. ULONG dbgMaxInterruptsPerSecond = 0;
  62. ULONG dbgShortestInt = 0x0fffffff;
  63. ULONG dbgLongestInt = 0;
  64. LARGE_INTEGER dbgLastIntStart = {0};
  65. ULONG dbgAveIntTime = 0;
  66. VOID DbgLogIntStart()
  67. {
  68. static ULONG dbgInterruptsThisSecond = 0;
  69. static ULONG dbgThisSecondStartTime = 0;
  70. LARGE_INTEGER timeNow;
  71. ULONG lastTimeMilliSec, timeNowMilliSec;
  72. KeQuerySystemTime(&timeNow);
  73. // convert from usec to millisec
  74. timeNowMilliSec = timeNow.LowPart/10000;
  75. lastTimeMilliSec = dbgLastIntStart.LowPart/10000;
  76. if (timeNow.HighPart == dbgLastIntStart.HighPart){
  77. ULONG delta = timeNowMilliSec - lastTimeMilliSec;
  78. if (delta < dbgMinInterruptDelta){
  79. dbgMinInterruptDelta = delta;
  80. }
  81. if (timeNowMilliSec - dbgThisSecondStartTime < 1000){
  82. dbgInterruptsThisSecond++;
  83. if (dbgInterruptsThisSecond > dbgMaxInterruptsPerSecond){
  84. dbgMaxInterruptsPerSecond = dbgInterruptsThisSecond;
  85. }
  86. }
  87. else {
  88. dbgThisSecondStartTime = timeNowMilliSec;
  89. dbgInterruptsThisSecond = 0;
  90. }
  91. }
  92. else {
  93. // this case is harder so skip it
  94. dbgThisSecondStartTime = timeNowMilliSec;
  95. dbgInterruptsThisSecond = 0;
  96. }
  97. dbgLastIntStart = timeNow;
  98. }
  99. VOID DbgLogIntEnd()
  100. {
  101. LARGE_INTEGER timeNow;
  102. KeQuerySystemTime(&timeNow);
  103. if (timeNow.HighPart == dbgLastIntStart.HighPart){
  104. ULONG timeNowMilliSec = timeNow.LowPart/10000;
  105. ULONG intStartTimeMilliSec = dbgLastIntStart.LowPart/10000;
  106. ULONG delta = timeNowMilliSec - intStartTimeMilliSec;
  107. if (delta < dbgShortestInt){
  108. dbgShortestInt = delta;
  109. }
  110. else if (delta > dbgLongestInt){
  111. dbgLongestInt = delta;
  112. }
  113. {
  114. static ULONG dbgIntCount = 0;
  115. static ULONG dbgTimeLast1000Ints = 0;
  116. if (dbgIntCount < 1000){
  117. dbgIntCount++;
  118. dbgTimeLast1000Ints += delta;
  119. }
  120. else {
  121. dbgAveIntTime = dbgTimeLast1000Ints/1000;
  122. dbgTimeLast1000Ints = 0;
  123. dbgIntCount = 0;
  124. }
  125. }
  126. }
  127. else {
  128. // This is harder so we just skip it
  129. }
  130. }
  131. NTSTATUS DbgTestGetDeviceStringCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
  132. {
  133. ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
  134. ExFreePool(Irp->UserBuffer);
  135. IoFreeIrp(Irp);
  136. return STATUS_MORE_PROCESSING_REQUIRED;
  137. }
  138. VOID DbgTestGetDeviceString(PFDO_EXTENSION fdoExt)
  139. {
  140. PIRP Irp;
  141. const ULONG inputLen = 200;
  142. Irp = IoAllocateIrp(fdoExt->fdo->StackSize, FALSE);
  143. if (Irp){
  144. Irp->UserBuffer = ALLOCATEPOOL(NonPagedPool, inputLen);
  145. if (Irp->UserBuffer){
  146. ULONG stringId = HID_STRING_ID_IMANUFACTURER;
  147. ULONG languageId = 0x0409; // English
  148. PIO_STACK_LOCATION currentIrpSp = IoGetCurrentIrpStackLocation(Irp);
  149. Irp->MdlAddress->MappedSystemVa = Irp->UserBuffer;
  150. Irp->MdlAddress->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
  151. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  152. currentIrpSp->Parameters.DeviceIoControl.OutputBufferLength = inputLen;
  153. IoSetCompletionRoutine( Irp,
  154. DbgTestGetDeviceStringCompletion,
  155. (PVOID)NULL,
  156. TRUE,
  157. TRUE,
  158. TRUE);
  159. HidpGetDeviceString(fdoExt, Irp, stringId, languageId);
  160. }
  161. }
  162. }
  163. VOID DbgTestGetIndexedString(PFDO_EXTENSION fdoExt)
  164. {
  165. PIRP Irp;
  166. const ULONG inputLen = 200;
  167. Irp = IoAllocateIrp(fdoExt->fdo->StackSize, FALSE);
  168. if (Irp){
  169. Irp->UserBuffer = ALLOCATEPOOL(NonPagedPool, inputLen);
  170. if (Irp->UserBuffer){
  171. ULONG stringIndex = 1; // ???
  172. ULONG languageId = 0x0409; // English
  173. PIO_STACK_LOCATION currentIrpSp = IoGetCurrentIrpStackLocation(Irp);
  174. Irp->MdlAddress->MappedSystemVa = Irp->UserBuffer;
  175. Irp->MdlAddress->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
  176. currentIrpSp->Parameters.DeviceIoControl.InputBufferLength = inputLen;
  177. IoSetCompletionRoutine( Irp,
  178. DbgTestGetDeviceStringCompletion,
  179. (PVOID)NULL,
  180. TRUE,
  181. TRUE,
  182. TRUE);
  183. HidpGetIndexedString(fdoExt, Irp, stringIndex, languageId);
  184. }
  185. }
  186. }
  187. #define DBG_MAX_DEVOBJ_RECORDS 100
  188. dbgDevObjRecord dbgDevObjs[DBG_MAX_DEVOBJ_RECORDS] = {0};
  189. VOID DbgRecordDevObj(PDEVICE_OBJECT devObj, PCHAR str)
  190. {
  191. ULONG i;
  192. for (i = 0; i < DBG_MAX_DEVOBJ_RECORDS; i++){
  193. if (!ISPTR(dbgDevObjs[i].devObj)){
  194. break;
  195. }
  196. else if (dbgDevObjs[i].devObj == devObj){
  197. // already there
  198. break;
  199. }
  200. }
  201. if ((i < DBG_MAX_DEVOBJ_RECORDS) && !dbgDevObjs[i].devObj){
  202. ULONG j;
  203. dbgDevObjs[i].devObj = devObj;
  204. for (j = 0; str[j] && (j < dbgDevObjRecord_STRINGSIZE); j++){
  205. dbgDevObjs[i].str[j] = str[j];
  206. }
  207. }
  208. }
  209. #define DBG_MAX_FEATURE_RECORDS 0x1000
  210. dbgFeatureRecord dbgFeatures[DBG_MAX_FEATURE_RECORDS] = {0};
  211. ULONG dbgFeatureFirstFreeIndex = 0;
  212. VOID DbgRecordReport(ULONG reportId, ULONG controlCode, BOOLEAN isComplete)
  213. {
  214. ULONG typeId;
  215. switch (controlCode){
  216. case IOCTL_HID_GET_FEATURE: typeId = (ULONG)'fteG'; break;
  217. case IOCTL_HID_SET_FEATURE: typeId = (ULONG)'fteS'; break;
  218. case IOCTL_HID_GET_INPUT_REPORT: typeId = (ULONG)'iteG'; break;
  219. case IOCTL_HID_SET_OUTPUT_REPORT: typeId = (ULONG)'oteS'; break;
  220. default: typeId = (ULONG)'xxxx'; TRAP; break;
  221. }
  222. if (isComplete){
  223. LONG i;
  224. // step back to find the report that got completed
  225. // assumes no overlapped calls to same feature
  226. ASSERT(dbgFeatureFirstFreeIndex > 0);
  227. i = dbgFeatureFirstFreeIndex-1;
  228. while ((i >= 0) &&
  229. ((dbgFeatures[i].reportId != reportId) ||
  230. (dbgFeatures[i].type != typeId) ||
  231. dbgFeatures[i].completed)){
  232. i--;
  233. }
  234. ASSERT(i >= 0);
  235. if (i >= 0){
  236. dbgFeatures[i].completed = 1;
  237. }
  238. }
  239. else {
  240. if (dbgFeatureFirstFreeIndex >= DBG_MAX_FEATURE_RECORDS){
  241. RtlZeroMemory(dbgFeatures, sizeof(dbgFeatures));
  242. dbgFeatureFirstFreeIndex = 0;
  243. }
  244. dbgFeatures[dbgFeatureFirstFreeIndex].marker = (ULONG)'taeF';
  245. dbgFeatures[dbgFeatureFirstFreeIndex].reportId = reportId;
  246. dbgFeatures[dbgFeatureFirstFreeIndex].type = typeId;
  247. dbgFeatures[dbgFeatureFirstFreeIndex].completed = 0;
  248. dbgFeatureFirstFreeIndex++;
  249. }
  250. }
  251. #define DBG_MAX_READ_RECORDS 0x1000
  252. dbgReadRecord dbgReads[DBG_MAX_READ_RECORDS] = {0};
  253. VOID DbgRecordRead(PIRP irp, ULONG length, ULONG reportId, ULONG completed)
  254. {
  255. LONG i;
  256. for (i = 0;
  257. (i < DBG_MAX_READ_RECORDS) &&
  258. dbgReads[i].irpPtr &&
  259. ((dbgReads[i].irpPtr != (ULONG_PTR)irp) || dbgReads[i].completed);
  260. i++){
  261. }
  262. if (i < DBG_MAX_READ_RECORDS){
  263. if (dbgReads[i].irpPtr){
  264. ASSERT(dbgReads[i].irpPtr == (ULONG_PTR)irp);
  265. ASSERT(!dbgReads[i].completed);
  266. ASSERT(completed);
  267. dbgReads[i].length = length;
  268. dbgReads[i].reportId = reportId;
  269. dbgReads[i].completed = completed;
  270. }
  271. else {
  272. dbgReads[i].irpPtr = (ULONG_PTR)irp;
  273. dbgReads[i].length = length;
  274. dbgReads[i].reportId = reportId;
  275. dbgReads[i].completed = completed;
  276. }
  277. }
  278. }
  279. VOID DbgLogIrpMajor(ULONG_PTR irpPtr, ULONG majorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
  280. {
  281. if (dbgVerbose){
  282. char *funcName;
  283. switch (majorFunc){
  284. #undef MAKE_CASE
  285. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
  286. MAKE_CASE(IRP_MJ_CREATE)
  287. MAKE_CASE(IRP_MJ_CREATE_NAMED_PIPE)
  288. MAKE_CASE(IRP_MJ_CLOSE)
  289. MAKE_CASE(IRP_MJ_READ)
  290. MAKE_CASE(IRP_MJ_WRITE)
  291. MAKE_CASE(IRP_MJ_QUERY_INFORMATION)
  292. MAKE_CASE(IRP_MJ_SET_INFORMATION)
  293. MAKE_CASE(IRP_MJ_QUERY_EA)
  294. MAKE_CASE(IRP_MJ_SET_EA)
  295. MAKE_CASE(IRP_MJ_FLUSH_BUFFERS)
  296. MAKE_CASE(IRP_MJ_QUERY_VOLUME_INFORMATION)
  297. MAKE_CASE(IRP_MJ_SET_VOLUME_INFORMATION)
  298. MAKE_CASE(IRP_MJ_DIRECTORY_CONTROL)
  299. MAKE_CASE(IRP_MJ_FILE_SYSTEM_CONTROL)
  300. MAKE_CASE(IRP_MJ_DEVICE_CONTROL)
  301. MAKE_CASE(IRP_MJ_INTERNAL_DEVICE_CONTROL)
  302. MAKE_CASE(IRP_MJ_SHUTDOWN)
  303. MAKE_CASE(IRP_MJ_LOCK_CONTROL)
  304. MAKE_CASE(IRP_MJ_CLEANUP)
  305. MAKE_CASE(IRP_MJ_CREATE_MAILSLOT)
  306. MAKE_CASE(IRP_MJ_QUERY_SECURITY)
  307. MAKE_CASE(IRP_MJ_SET_SECURITY)
  308. MAKE_CASE(IRP_MJ_POWER)
  309. MAKE_CASE(IRP_MJ_SYSTEM_CONTROL)
  310. MAKE_CASE(IRP_MJ_DEVICE_CHANGE)
  311. MAKE_CASE(IRP_MJ_QUERY_QUOTA)
  312. MAKE_CASE(IRP_MJ_SET_QUOTA)
  313. MAKE_CASE(IRP_MJ_PNP)
  314. default: funcName = NULL; break;
  315. }
  316. if (isComplete){
  317. if (funcName){
  318. DBGOUT(("< %s for %s status=%xh (irp=%ph)",
  319. funcName,
  320. isForCollectionPdo ? "collection" : "device",
  321. status,
  322. irpPtr));
  323. }
  324. else {
  325. DBGOUT(("< ????<majorFunc=%xh> for %s status=%xh (irp=%ph)",
  326. majorFunc,
  327. isForCollectionPdo ? "collection" : "device",
  328. status,
  329. irpPtr));
  330. }
  331. }
  332. else {
  333. if (funcName){
  334. DBGOUT(("> %s (irp=%xh)", funcName, irpPtr));
  335. }
  336. else {
  337. DBGOUT(("> ????<majorFunc=%xh> (irp=%xh)", majorFunc, irpPtr));
  338. }
  339. }
  340. }
  341. }
  342. #define DBG_MAX_PNP_IRP_RECORDS 0x1000
  343. dbgPnPIrpRecord dbgPnPIrps[DBG_MAX_PNP_IRP_RECORDS] = {0};
  344. VOID DbgLogPnpIrp(ULONG_PTR irpPtr, ULONG minorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
  345. {
  346. char *funcName;
  347. ULONG funcShortName;
  348. int i;
  349. switch (minorFunc){
  350. #undef MAKE_CASE
  351. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; funcShortName = *(ULONG *)(funcName+7); break;
  352. MAKE_CASE(IRP_MN_START_DEVICE)
  353. MAKE_CASE(IRP_MN_QUERY_REMOVE_DEVICE)
  354. MAKE_CASE(IRP_MN_REMOVE_DEVICE)
  355. MAKE_CASE(IRP_MN_CANCEL_REMOVE_DEVICE)
  356. MAKE_CASE(IRP_MN_STOP_DEVICE)
  357. MAKE_CASE(IRP_MN_QUERY_STOP_DEVICE)
  358. MAKE_CASE(IRP_MN_CANCEL_STOP_DEVICE)
  359. MAKE_CASE(IRP_MN_QUERY_DEVICE_RELATIONS)
  360. MAKE_CASE(IRP_MN_QUERY_INTERFACE)
  361. MAKE_CASE(IRP_MN_QUERY_CAPABILITIES)
  362. MAKE_CASE(IRP_MN_QUERY_RESOURCES)
  363. MAKE_CASE(IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
  364. MAKE_CASE(IRP_MN_QUERY_DEVICE_TEXT)
  365. MAKE_CASE(IRP_MN_READ_CONFIG)
  366. MAKE_CASE(IRP_MN_WRITE_CONFIG)
  367. MAKE_CASE(IRP_MN_EJECT)
  368. MAKE_CASE(IRP_MN_SET_LOCK)
  369. MAKE_CASE(IRP_MN_QUERY_ID)
  370. MAKE_CASE(IRP_MN_QUERY_PNP_DEVICE_STATE)
  371. MAKE_CASE(IRP_MN_QUERY_BUS_INFORMATION)
  372. MAKE_CASE(IRP_MN_DEVICE_USAGE_NOTIFICATION)
  373. MAKE_CASE(IRP_MN_SURPRISE_REMOVAL)
  374. #ifndef IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  375. #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
  376. #endif // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  377. MAKE_CASE(IRP_MN_QUERY_LEGACY_BUS_INFORMATION)
  378. default: funcName = NULL; funcShortName = (ULONG)'\?\?\?\?'; break;
  379. }
  380. if (dbgVerbose){
  381. if (isComplete){
  382. if (funcName){
  383. DBGOUT((" < %s for %s status=%xh (irp=%ph)",
  384. funcName,
  385. isForCollectionPdo ? "collection" : "device",
  386. status,
  387. irpPtr));
  388. }
  389. else {
  390. DBGOUT((" < ?? <minorFunc=%xh> for %s status=%xh (irp=%ph)",
  391. minorFunc,
  392. isForCollectionPdo ? "collection" : "device",
  393. status,
  394. irpPtr));
  395. }
  396. }
  397. else {
  398. if (funcName){
  399. DBGOUT((" > %s for %s (irp=%xh)",
  400. funcName,
  401. isForCollectionPdo ? "collection" : "device",
  402. irpPtr));
  403. }
  404. else {
  405. DBGOUT((" > ?? <minorFunc=%xh> for %s (irp=%xh)",
  406. minorFunc,
  407. isForCollectionPdo ? "collection" : "device",
  408. irpPtr));
  409. }
  410. }
  411. }
  412. if (isComplete){
  413. for (i = 0; (i < DBG_MAX_PNP_IRP_RECORDS) && dbgPnPIrps[i].irpPtr; i++){
  414. if ((dbgPnPIrps[i].irpPtr == irpPtr) &&
  415. ((dbgPnPIrps[i].status == 0xFFFFFFFF) || (dbgPnPIrps[i].status == STATUS_PENDING))){
  416. dbgPnPIrps[i].status = status;
  417. break;
  418. }
  419. }
  420. }
  421. else {
  422. for (i = 0; i < DBG_MAX_PNP_IRP_RECORDS; i++){
  423. if (!dbgPnPIrps[i].irpPtr){
  424. dbgPnPIrps[i].irpPtr = irpPtr;
  425. dbgPnPIrps[i].func = funcShortName;
  426. dbgPnPIrps[i].isForCollectionPdo = isForCollectionPdo;
  427. dbgPnPIrps[i].status = 0xFFFFFFFF;
  428. break;
  429. }
  430. }
  431. }
  432. }
  433. VOID DbgLogPowerIrp(PVOID devExt, UCHAR minorFunc, ULONG isClientPdo, ULONG isComplete, PCHAR type, ULONG powerState, ULONG status)
  434. {
  435. char *funcName;
  436. switch (minorFunc){
  437. #undef MAKE_CASE
  438. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
  439. MAKE_CASE(IRP_MN_WAIT_WAKE)
  440. MAKE_CASE(IRP_MN_POWER_SEQUENCE)
  441. MAKE_CASE(IRP_MN_SET_POWER)
  442. MAKE_CASE(IRP_MN_QUERY_POWER)
  443. default: funcName = "????"; break;
  444. }
  445. if (dbgVerbose){
  446. if (isComplete){
  447. DBGOUT((" < %s for %s(ext=%ph) status=%xh ",
  448. funcName,
  449. isClientPdo ? "collection" : "device",
  450. devExt,
  451. status));
  452. }
  453. else if (minorFunc == IRP_MN_SET_POWER){
  454. DBGOUT((" > %s for %s(ext=%ph) type=%s, powerState=%ph",
  455. funcName,
  456. isClientPdo ? "collection" : "device",
  457. devExt,
  458. type,
  459. powerState));
  460. }
  461. else {
  462. DBGOUT((" > %s for %s(ext=%ph) ",
  463. funcName,
  464. isClientPdo ? "collection" : "device",
  465. devExt));
  466. }
  467. }
  468. }
  469. #define DBG_MAX_REPORT_RECORDS 0x100
  470. dbgReportRecord dbgReportRecords[DBG_MAX_REPORT_RECORDS] = { 0 };
  471. ULONG dbgCurrentReportRecord = 0;
  472. VOID DbgLogReport(ULONG collectionNumber, ULONG numRecipients, ULONG numPending, ULONG numFailed, PUCHAR report, ULONG reportLength)
  473. {
  474. ASSERT(dbgCurrentReportRecord <= DBG_MAX_REPORT_RECORDS);
  475. if (dbgCurrentReportRecord == DBG_MAX_REPORT_RECORDS){
  476. RtlZeroMemory(dbgReportRecords, DBG_MAX_REPORT_RECORDS*sizeof(dbgReportRecord));
  477. dbgCurrentReportRecord = 0;
  478. }
  479. dbgReportRecords[dbgCurrentReportRecord].collectionNumber = (UCHAR)collectionNumber;
  480. dbgReportRecords[dbgCurrentReportRecord].numRecipients = (UCHAR)numRecipients;
  481. if (reportLength > sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes)){
  482. reportLength = sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes);
  483. }
  484. RtlCopyMemory((PUCHAR)dbgReportRecords[dbgCurrentReportRecord].reportBytes, report, reportLength);
  485. dbgCurrentReportRecord++;
  486. if (dbgVerbose){
  487. ULONG i;
  488. DBGOUT(("Report (cltn #%d, %d recipients; %d pending, %d failed):", collectionNumber, numRecipients, numPending, numFailed));
  489. DbgPrint("'\t report bytes: \t");
  490. for (i = 0; i < reportLength; i++){
  491. DbgPrint("%02x ", report[i]);
  492. }
  493. DbgPrint("\n");
  494. }
  495. }
  496. VOID DbgLogIoctl(ULONG_PTR fdo, ULONG ioControlCode, ULONG status)
  497. {
  498. if (dbgVerbose){
  499. PCHAR ioctlStr;
  500. switch (ioControlCode){
  501. #undef MAKE_CASE
  502. #define MAKE_CASE(ioctl) case ioctl: ioctlStr = #ioctl; break;
  503. MAKE_CASE(IOCTL_HID_GET_DRIVER_CONFIG)
  504. MAKE_CASE(IOCTL_HID_SET_DRIVER_CONFIG)
  505. MAKE_CASE(IOCTL_HID_GET_POLL_FREQUENCY_MSEC)
  506. MAKE_CASE(IOCTL_HID_SET_POLL_FREQUENCY_MSEC)
  507. MAKE_CASE(IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS)
  508. MAKE_CASE(IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS)
  509. MAKE_CASE(IOCTL_HID_GET_COLLECTION_INFORMATION)
  510. MAKE_CASE(IOCTL_HID_GET_COLLECTION_DESCRIPTOR)
  511. MAKE_CASE(IOCTL_HID_FLUSH_QUEUE)
  512. MAKE_CASE(IOCTL_HID_SET_FEATURE)
  513. MAKE_CASE(IOCTL_HID_GET_FEATURE)
  514. MAKE_CASE(IOCTL_GET_PHYSICAL_DESCRIPTOR)
  515. MAKE_CASE(IOCTL_HID_GET_HARDWARE_ID)
  516. MAKE_CASE(IOCTL_HID_GET_MANUFACTURER_STRING)
  517. MAKE_CASE(IOCTL_HID_GET_PRODUCT_STRING)
  518. MAKE_CASE(IOCTL_HID_GET_SERIALNUMBER_STRING)
  519. MAKE_CASE(IOCTL_HID_GET_INDEXED_STRING)
  520. MAKE_CASE(IOCTL_INTERNAL_HID_SET_BLUESCREEN)
  521. default: ioctlStr = "???"; break;
  522. }
  523. DBGOUT(("IOCTL %s (%xh) status=%xh (fdo=%ph)",
  524. ioctlStr, ioControlCode, status, fdo));
  525. }
  526. }
  527. #endif