Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

572 lines
20 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. #define DBG_MAX_DEVOBJ_RECORDS 100
  132. dbgDevObjRecord dbgDevObjs[DBG_MAX_DEVOBJ_RECORDS] = {0};
  133. VOID DbgRecordDevObj(PDEVICE_OBJECT devObj, PCHAR str)
  134. {
  135. ULONG i;
  136. for (i = 0; i < DBG_MAX_DEVOBJ_RECORDS; i++){
  137. if (!ISPTR(dbgDevObjs[i].devObj)){
  138. break;
  139. }
  140. else if (dbgDevObjs[i].devObj == devObj){
  141. // already there
  142. break;
  143. }
  144. }
  145. if ((i < DBG_MAX_DEVOBJ_RECORDS) && !dbgDevObjs[i].devObj){
  146. ULONG j;
  147. dbgDevObjs[i].devObj = devObj;
  148. for (j = 0; str[j] && (j < dbgDevObjRecord_STRINGSIZE); j++){
  149. dbgDevObjs[i].str[j] = str[j];
  150. }
  151. }
  152. }
  153. #define DBG_MAX_FEATURE_RECORDS 0x1000
  154. dbgFeatureRecord dbgFeatures[DBG_MAX_FEATURE_RECORDS] = {0};
  155. ULONG dbgFeatureFirstFreeIndex = 0;
  156. VOID DbgRecordReport(ULONG reportId, ULONG controlCode, BOOLEAN isComplete)
  157. {
  158. ULONG typeId;
  159. switch (controlCode){
  160. case IOCTL_HID_GET_FEATURE: typeId = (ULONG)'fteG'; break;
  161. case IOCTL_HID_SET_FEATURE: typeId = (ULONG)'fteS'; break;
  162. case IOCTL_HID_GET_INPUT_REPORT: typeId = (ULONG)'iteG'; break;
  163. case IOCTL_HID_SET_OUTPUT_REPORT: typeId = (ULONG)'oteS'; break;
  164. default: typeId = (ULONG)'xxxx'; TRAP; break;
  165. }
  166. if (isComplete){
  167. LONG i;
  168. // step back to find the report that got completed
  169. // assumes no overlapped calls to same feature
  170. ASSERT(dbgFeatureFirstFreeIndex > 0);
  171. i = dbgFeatureFirstFreeIndex-1;
  172. while ((i >= 0) &&
  173. ((dbgFeatures[i].reportId != reportId) ||
  174. (dbgFeatures[i].type != typeId) ||
  175. dbgFeatures[i].completed)){
  176. i--;
  177. }
  178. ASSERT(i >= 0);
  179. if (i >= 0){
  180. dbgFeatures[i].completed = 1;
  181. }
  182. }
  183. else {
  184. if (dbgFeatureFirstFreeIndex >= DBG_MAX_FEATURE_RECORDS){
  185. RtlZeroMemory(dbgFeatures, sizeof(dbgFeatures));
  186. dbgFeatureFirstFreeIndex = 0;
  187. }
  188. dbgFeatures[dbgFeatureFirstFreeIndex].marker = (ULONG)'taeF';
  189. dbgFeatures[dbgFeatureFirstFreeIndex].reportId = reportId;
  190. dbgFeatures[dbgFeatureFirstFreeIndex].type = typeId;
  191. dbgFeatures[dbgFeatureFirstFreeIndex].completed = 0;
  192. dbgFeatureFirstFreeIndex++;
  193. }
  194. }
  195. #define DBG_MAX_READ_RECORDS 0x1000
  196. dbgReadRecord dbgReads[DBG_MAX_READ_RECORDS] = {0};
  197. VOID DbgRecordRead(PIRP irp, ULONG length, ULONG reportId, ULONG completed)
  198. {
  199. LONG i;
  200. for (i = 0;
  201. (i < DBG_MAX_READ_RECORDS) &&
  202. dbgReads[i].irpPtr &&
  203. ((dbgReads[i].irpPtr != (ULONG_PTR)irp) || dbgReads[i].completed);
  204. i++){
  205. }
  206. if (i < DBG_MAX_READ_RECORDS){
  207. if (dbgReads[i].irpPtr){
  208. ASSERT(dbgReads[i].irpPtr == (ULONG_PTR)irp);
  209. ASSERT(!dbgReads[i].completed);
  210. ASSERT(completed);
  211. dbgReads[i].length = length;
  212. dbgReads[i].reportId = reportId;
  213. dbgReads[i].completed = completed;
  214. }
  215. else {
  216. dbgReads[i].irpPtr = (ULONG_PTR)irp;
  217. dbgReads[i].length = length;
  218. dbgReads[i].reportId = reportId;
  219. dbgReads[i].completed = completed;
  220. }
  221. }
  222. }
  223. VOID DbgLogIrpMajor(ULONG_PTR irpPtr, ULONG majorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
  224. {
  225. if (dbgVerbose){
  226. char *funcName;
  227. switch (majorFunc){
  228. #undef MAKE_CASE
  229. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
  230. MAKE_CASE(IRP_MJ_CREATE)
  231. MAKE_CASE(IRP_MJ_CREATE_NAMED_PIPE)
  232. MAKE_CASE(IRP_MJ_CLOSE)
  233. MAKE_CASE(IRP_MJ_READ)
  234. MAKE_CASE(IRP_MJ_WRITE)
  235. MAKE_CASE(IRP_MJ_QUERY_INFORMATION)
  236. MAKE_CASE(IRP_MJ_SET_INFORMATION)
  237. MAKE_CASE(IRP_MJ_QUERY_EA)
  238. MAKE_CASE(IRP_MJ_SET_EA)
  239. MAKE_CASE(IRP_MJ_FLUSH_BUFFERS)
  240. MAKE_CASE(IRP_MJ_QUERY_VOLUME_INFORMATION)
  241. MAKE_CASE(IRP_MJ_SET_VOLUME_INFORMATION)
  242. MAKE_CASE(IRP_MJ_DIRECTORY_CONTROL)
  243. MAKE_CASE(IRP_MJ_FILE_SYSTEM_CONTROL)
  244. MAKE_CASE(IRP_MJ_DEVICE_CONTROL)
  245. MAKE_CASE(IRP_MJ_INTERNAL_DEVICE_CONTROL)
  246. MAKE_CASE(IRP_MJ_SHUTDOWN)
  247. MAKE_CASE(IRP_MJ_LOCK_CONTROL)
  248. MAKE_CASE(IRP_MJ_CLEANUP)
  249. MAKE_CASE(IRP_MJ_CREATE_MAILSLOT)
  250. MAKE_CASE(IRP_MJ_QUERY_SECURITY)
  251. MAKE_CASE(IRP_MJ_SET_SECURITY)
  252. MAKE_CASE(IRP_MJ_POWER)
  253. MAKE_CASE(IRP_MJ_SYSTEM_CONTROL)
  254. MAKE_CASE(IRP_MJ_DEVICE_CHANGE)
  255. MAKE_CASE(IRP_MJ_QUERY_QUOTA)
  256. MAKE_CASE(IRP_MJ_SET_QUOTA)
  257. MAKE_CASE(IRP_MJ_PNP)
  258. default: funcName = NULL; break;
  259. }
  260. if (isComplete){
  261. if (funcName){
  262. DBGOUT(("< %s for %s status=%xh (irp=%ph)",
  263. funcName,
  264. isForCollectionPdo ? "collection" : "device",
  265. status,
  266. irpPtr));
  267. }
  268. else {
  269. DBGOUT(("< ????<majorFunc=%xh> for %s status=%xh (irp=%ph)",
  270. majorFunc,
  271. isForCollectionPdo ? "collection" : "device",
  272. status,
  273. irpPtr));
  274. }
  275. }
  276. else {
  277. if (funcName){
  278. DBGOUT(("> %s (irp=%xh)", funcName, irpPtr));
  279. }
  280. else {
  281. DBGOUT(("> ????<majorFunc=%xh> (irp=%xh)", majorFunc, irpPtr));
  282. }
  283. }
  284. }
  285. }
  286. #define DBG_MAX_PNP_IRP_RECORDS 0x1000
  287. dbgPnPIrpRecord dbgPnPIrps[DBG_MAX_PNP_IRP_RECORDS] = {0};
  288. VOID DbgLogPnpIrp(ULONG_PTR irpPtr, ULONG minorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
  289. {
  290. char *funcName;
  291. ULONG funcShortName;
  292. int i;
  293. switch (minorFunc){
  294. #undef MAKE_CASE
  295. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; funcShortName = *(ULONG *)(funcName+7); break;
  296. MAKE_CASE(IRP_MN_START_DEVICE)
  297. MAKE_CASE(IRP_MN_QUERY_REMOVE_DEVICE)
  298. MAKE_CASE(IRP_MN_REMOVE_DEVICE)
  299. MAKE_CASE(IRP_MN_CANCEL_REMOVE_DEVICE)
  300. MAKE_CASE(IRP_MN_STOP_DEVICE)
  301. MAKE_CASE(IRP_MN_QUERY_STOP_DEVICE)
  302. MAKE_CASE(IRP_MN_CANCEL_STOP_DEVICE)
  303. MAKE_CASE(IRP_MN_QUERY_DEVICE_RELATIONS)
  304. MAKE_CASE(IRP_MN_QUERY_INTERFACE)
  305. MAKE_CASE(IRP_MN_QUERY_CAPABILITIES)
  306. MAKE_CASE(IRP_MN_QUERY_RESOURCES)
  307. MAKE_CASE(IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
  308. MAKE_CASE(IRP_MN_QUERY_DEVICE_TEXT)
  309. MAKE_CASE(IRP_MN_READ_CONFIG)
  310. MAKE_CASE(IRP_MN_WRITE_CONFIG)
  311. MAKE_CASE(IRP_MN_EJECT)
  312. MAKE_CASE(IRP_MN_SET_LOCK)
  313. MAKE_CASE(IRP_MN_QUERY_ID)
  314. MAKE_CASE(IRP_MN_QUERY_PNP_DEVICE_STATE)
  315. MAKE_CASE(IRP_MN_QUERY_BUS_INFORMATION)
  316. MAKE_CASE(IRP_MN_DEVICE_USAGE_NOTIFICATION)
  317. MAKE_CASE(IRP_MN_SURPRISE_REMOVAL)
  318. #ifndef IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  319. #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
  320. #endif // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
  321. MAKE_CASE(IRP_MN_QUERY_LEGACY_BUS_INFORMATION)
  322. default: funcName = NULL; funcShortName = (ULONG)'\?\?\?\?'; break;
  323. }
  324. if (dbgVerbose){
  325. if (isComplete){
  326. if (funcName){
  327. DBGOUT((" < %s for %s status=%xh (irp=%ph)",
  328. funcName,
  329. isForCollectionPdo ? "collection" : "device",
  330. status,
  331. irpPtr));
  332. }
  333. else {
  334. DBGOUT((" < ?? <minorFunc=%xh> for %s status=%xh (irp=%ph)",
  335. minorFunc,
  336. isForCollectionPdo ? "collection" : "device",
  337. status,
  338. irpPtr));
  339. }
  340. }
  341. else {
  342. if (funcName){
  343. DBGOUT((" > %s for %s (irp=%xh)",
  344. funcName,
  345. isForCollectionPdo ? "collection" : "device",
  346. irpPtr));
  347. }
  348. else {
  349. DBGOUT((" > ?? <minorFunc=%xh> for %s (irp=%xh)",
  350. minorFunc,
  351. isForCollectionPdo ? "collection" : "device",
  352. irpPtr));
  353. }
  354. }
  355. }
  356. if (isComplete){
  357. for (i = 0; (i < DBG_MAX_PNP_IRP_RECORDS) && dbgPnPIrps[i].irpPtr; i++){
  358. if ((dbgPnPIrps[i].irpPtr == irpPtr) &&
  359. ((dbgPnPIrps[i].status == 0xFFFFFFFF) || (dbgPnPIrps[i].status == STATUS_PENDING))){
  360. dbgPnPIrps[i].status = status;
  361. break;
  362. }
  363. }
  364. }
  365. else {
  366. for (i = 0; i < DBG_MAX_PNP_IRP_RECORDS; i++){
  367. if (!dbgPnPIrps[i].irpPtr){
  368. dbgPnPIrps[i].irpPtr = irpPtr;
  369. dbgPnPIrps[i].func = funcShortName;
  370. dbgPnPIrps[i].isForCollectionPdo = isForCollectionPdo;
  371. dbgPnPIrps[i].status = 0xFFFFFFFF;
  372. break;
  373. }
  374. }
  375. }
  376. }
  377. VOID DbgLogPowerIrp(PVOID devExt, UCHAR minorFunc, ULONG isClientPdo, ULONG isComplete, PCHAR type, ULONG powerState, ULONG status)
  378. {
  379. char *funcName;
  380. switch (minorFunc){
  381. #undef MAKE_CASE
  382. #define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
  383. MAKE_CASE(IRP_MN_WAIT_WAKE)
  384. MAKE_CASE(IRP_MN_POWER_SEQUENCE)
  385. MAKE_CASE(IRP_MN_SET_POWER)
  386. MAKE_CASE(IRP_MN_QUERY_POWER)
  387. default: funcName = "????"; break;
  388. }
  389. if (dbgVerbose){
  390. if (isComplete){
  391. DBGOUT((" < %s for %s(ext=%ph) status=%xh ",
  392. funcName,
  393. isClientPdo ? "collection" : "device",
  394. devExt,
  395. status));
  396. }
  397. else if (minorFunc == IRP_MN_SET_POWER){
  398. DBGOUT((" > %s for %s(ext=%ph) type=%s, powerState=%ph",
  399. funcName,
  400. isClientPdo ? "collection" : "device",
  401. devExt,
  402. type,
  403. powerState));
  404. }
  405. else {
  406. DBGOUT((" > %s for %s(ext=%ph) ",
  407. funcName,
  408. isClientPdo ? "collection" : "device",
  409. devExt));
  410. }
  411. }
  412. }
  413. #define DBG_MAX_REPORT_RECORDS 0x100
  414. dbgReportRecord dbgReportRecords[DBG_MAX_REPORT_RECORDS] = { 0 };
  415. ULONG dbgCurrentReportRecord = 0;
  416. VOID DbgLogReport(ULONG collectionNumber, ULONG numRecipients, ULONG numPending, ULONG numFailed, PUCHAR report, ULONG reportLength)
  417. {
  418. ASSERT(dbgCurrentReportRecord <= DBG_MAX_REPORT_RECORDS);
  419. if (dbgCurrentReportRecord == DBG_MAX_REPORT_RECORDS){
  420. RtlZeroMemory(dbgReportRecords, DBG_MAX_REPORT_RECORDS*sizeof(dbgReportRecord));
  421. dbgCurrentReportRecord = 0;
  422. }
  423. dbgReportRecords[dbgCurrentReportRecord].collectionNumber = (UCHAR)collectionNumber;
  424. dbgReportRecords[dbgCurrentReportRecord].numRecipients = (UCHAR)numRecipients;
  425. if (reportLength > sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes)){
  426. reportLength = sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes);
  427. }
  428. RtlCopyMemory((PUCHAR)dbgReportRecords[dbgCurrentReportRecord].reportBytes, report, reportLength);
  429. dbgCurrentReportRecord++;
  430. if (dbgVerbose){
  431. ULONG i;
  432. DBGOUT(("Report (cltn #%d, %d recipients; %d pending, %d failed):", collectionNumber, numRecipients, numPending, numFailed));
  433. DbgPrint("'\t report bytes: \t");
  434. for (i = 0; i < reportLength; i++){
  435. DbgPrint("%02x ", report[i]);
  436. }
  437. DbgPrint("\n");
  438. }
  439. }
  440. VOID DbgLogIoctl(ULONG_PTR fdo, ULONG ioControlCode, ULONG status)
  441. {
  442. if (dbgVerbose){
  443. PCHAR ioctlStr;
  444. switch (ioControlCode){
  445. #undef MAKE_CASE
  446. #define MAKE_CASE(ioctl) case ioctl: ioctlStr = #ioctl; break;
  447. MAKE_CASE(IOCTL_HID_GET_DRIVER_CONFIG)
  448. MAKE_CASE(IOCTL_HID_SET_DRIVER_CONFIG)
  449. MAKE_CASE(IOCTL_HID_GET_POLL_FREQUENCY_MSEC)
  450. MAKE_CASE(IOCTL_HID_SET_POLL_FREQUENCY_MSEC)
  451. MAKE_CASE(IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS)
  452. MAKE_CASE(IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS)
  453. MAKE_CASE(IOCTL_HID_GET_COLLECTION_INFORMATION)
  454. MAKE_CASE(IOCTL_HID_GET_COLLECTION_DESCRIPTOR)
  455. MAKE_CASE(IOCTL_HID_FLUSH_QUEUE)
  456. MAKE_CASE(IOCTL_HID_SET_FEATURE)
  457. MAKE_CASE(IOCTL_HID_GET_FEATURE)
  458. MAKE_CASE(IOCTL_GET_PHYSICAL_DESCRIPTOR)
  459. MAKE_CASE(IOCTL_HID_GET_HARDWARE_ID)
  460. MAKE_CASE(IOCTL_HID_GET_MANUFACTURER_STRING)
  461. MAKE_CASE(IOCTL_HID_GET_PRODUCT_STRING)
  462. MAKE_CASE(IOCTL_HID_GET_SERIALNUMBER_STRING)
  463. MAKE_CASE(IOCTL_HID_GET_INDEXED_STRING)
  464. default: ioctlStr = "???"; break;
  465. }
  466. DBGOUT(("IOCTL %s (%xh) status=%xh (fdo=%ph)",
  467. ioctlStr, ioControlCode, status, fdo));
  468. }
  469. }
  470. #endif