mirror of https://github.com/tongzx/nt5src
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
644 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
debug.c
|
|
|
|
Abstract
|
|
|
|
Debug/performance routines
|
|
|
|
Author:
|
|
|
|
Ervin P.
|
|
|
|
Environment:
|
|
|
|
Kernel mode only
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
#if DBG
|
|
|
|
// can poke this in the debugger to trap for warnings
|
|
BOOLEAN dbgTrapOnWarn = FALSE;
|
|
|
|
BOOLEAN dbgTrapOnSS = FALSE;
|
|
|
|
BOOLEAN dbgVerbose = FALSE;
|
|
|
|
BOOLEAN dbgInfo = TRUE;
|
|
|
|
BOOLEAN dbgSkipSecurity = FALSE;
|
|
|
|
BOOLEAN dbgTrapOnHiccup = FALSE;
|
|
|
|
ULONG dbgLastEntry = 0;
|
|
ULONG dbgInHidclass = 0;
|
|
VOID DbgCommonEntryExit(BOOLEAN isEntering)
|
|
{
|
|
if (isEntering){
|
|
dbgInHidclass++;
|
|
#ifdef _X86_
|
|
_asm nop
|
|
_asm mov eax, [ebp+4] /* <- set breakpt here */
|
|
_asm mov dbgLastEntry, eax
|
|
#endif
|
|
}
|
|
else {
|
|
dbgInHidclass--;
|
|
}
|
|
}
|
|
|
|
VOID InitFdoExtDebugInfo(PHIDCLASS_DEVICE_EXTENSION hidclassExt)
|
|
{
|
|
FDO_EXTENSION *fdoExt = &hidclassExt->fdoExt;
|
|
NTSTATUS status;
|
|
ULONG actualLen;
|
|
|
|
status = IoGetDeviceProperty( hidclassExt->hidExt.PhysicalDeviceObject,
|
|
DevicePropertyDriverKeyName,
|
|
sizeof(fdoExt->dbgDriverKeyName),
|
|
fdoExt->dbgDriverKeyName,
|
|
&actualLen);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
//
|
|
// We couldn't get the driver key name. This will happen during
|
|
// textmode setup on NT, for example, when we're loaded as part of
|
|
// bootstrapping the system (long before the device installer/class
|
|
// installer have run).
|
|
//
|
|
// Simply initialize the driver key name field to an empty string.
|
|
//
|
|
*(fdoExt->dbgDriverKeyName) = L'\0';
|
|
}
|
|
}
|
|
|
|
|
|
ULONG dbgMinInterruptDelta = 0x0fffffff;
|
|
ULONG dbgMaxInterruptsPerSecond = 0;
|
|
ULONG dbgShortestInt = 0x0fffffff;
|
|
ULONG dbgLongestInt = 0;
|
|
LARGE_INTEGER dbgLastIntStart = {0};
|
|
ULONG dbgAveIntTime = 0;
|
|
|
|
VOID DbgLogIntStart()
|
|
{
|
|
static ULONG dbgInterruptsThisSecond = 0;
|
|
static ULONG dbgThisSecondStartTime = 0;
|
|
|
|
LARGE_INTEGER timeNow;
|
|
ULONG lastTimeMilliSec, timeNowMilliSec;
|
|
|
|
KeQuerySystemTime(&timeNow);
|
|
|
|
// convert from usec to millisec
|
|
timeNowMilliSec = timeNow.LowPart/10000;
|
|
lastTimeMilliSec = dbgLastIntStart.LowPart/10000;
|
|
|
|
if (timeNow.HighPart == dbgLastIntStart.HighPart){
|
|
ULONG delta = timeNowMilliSec - lastTimeMilliSec;
|
|
|
|
if (delta < dbgMinInterruptDelta){
|
|
dbgMinInterruptDelta = delta;
|
|
}
|
|
|
|
if (timeNowMilliSec - dbgThisSecondStartTime < 1000){
|
|
dbgInterruptsThisSecond++;
|
|
if (dbgInterruptsThisSecond > dbgMaxInterruptsPerSecond){
|
|
dbgMaxInterruptsPerSecond = dbgInterruptsThisSecond;
|
|
}
|
|
}
|
|
else {
|
|
dbgThisSecondStartTime = timeNowMilliSec;
|
|
dbgInterruptsThisSecond = 0;
|
|
}
|
|
}
|
|
else {
|
|
// this case is harder so skip it
|
|
dbgThisSecondStartTime = timeNowMilliSec;
|
|
dbgInterruptsThisSecond = 0;
|
|
}
|
|
|
|
dbgLastIntStart = timeNow;
|
|
}
|
|
|
|
VOID DbgLogIntEnd()
|
|
{
|
|
LARGE_INTEGER timeNow;
|
|
|
|
KeQuerySystemTime(&timeNow);
|
|
|
|
if (timeNow.HighPart == dbgLastIntStart.HighPart){
|
|
ULONG timeNowMilliSec = timeNow.LowPart/10000;
|
|
ULONG intStartTimeMilliSec = dbgLastIntStart.LowPart/10000;
|
|
ULONG delta = timeNowMilliSec - intStartTimeMilliSec;
|
|
|
|
if (delta < dbgShortestInt){
|
|
dbgShortestInt = delta;
|
|
}
|
|
else if (delta > dbgLongestInt){
|
|
dbgLongestInt = delta;
|
|
}
|
|
|
|
{
|
|
static ULONG dbgIntCount = 0;
|
|
static ULONG dbgTimeLast1000Ints = 0;
|
|
|
|
if (dbgIntCount < 1000){
|
|
dbgIntCount++;
|
|
dbgTimeLast1000Ints += delta;
|
|
}
|
|
else {
|
|
dbgAveIntTime = dbgTimeLast1000Ints/1000;
|
|
dbgTimeLast1000Ints = 0;
|
|
dbgIntCount = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
// This is harder so we just skip it
|
|
}
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS DbgTestGetDeviceStringCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
|
|
{
|
|
ASSERT(NT_SUCCESS(Irp->IoStatus.Status));
|
|
ExFreePool(Irp->UserBuffer);
|
|
IoFreeIrp(Irp);
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
VOID DbgTestGetDeviceString(PFDO_EXTENSION fdoExt)
|
|
{
|
|
PIRP Irp;
|
|
const ULONG inputLen = 200;
|
|
|
|
Irp = IoAllocateIrp(fdoExt->fdo->StackSize, FALSE);
|
|
if (Irp){
|
|
Irp->UserBuffer = ALLOCATEPOOL(NonPagedPool, inputLen);
|
|
if (Irp->UserBuffer){
|
|
ULONG stringId = HID_STRING_ID_IMANUFACTURER;
|
|
ULONG languageId = 0x0409; // English
|
|
PIO_STACK_LOCATION currentIrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Irp->MdlAddress->MappedSystemVa = Irp->UserBuffer;
|
|
Irp->MdlAddress->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
currentIrpSp->Parameters.DeviceIoControl.OutputBufferLength = inputLen;
|
|
|
|
IoSetCompletionRoutine( Irp,
|
|
DbgTestGetDeviceStringCompletion,
|
|
(PVOID)NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
HidpGetDeviceString(fdoExt, Irp, stringId, languageId);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID DbgTestGetIndexedString(PFDO_EXTENSION fdoExt)
|
|
{
|
|
PIRP Irp;
|
|
const ULONG inputLen = 200;
|
|
|
|
Irp = IoAllocateIrp(fdoExt->fdo->StackSize, FALSE);
|
|
if (Irp){
|
|
Irp->UserBuffer = ALLOCATEPOOL(NonPagedPool, inputLen);
|
|
if (Irp->UserBuffer){
|
|
ULONG stringIndex = 1; // ???
|
|
ULONG languageId = 0x0409; // English
|
|
PIO_STACK_LOCATION currentIrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
Irp->MdlAddress->MappedSystemVa = Irp->UserBuffer;
|
|
Irp->MdlAddress->MdlFlags |= MDL_SOURCE_IS_NONPAGED_POOL;
|
|
|
|
currentIrpSp->Parameters.DeviceIoControl.InputBufferLength = inputLen;
|
|
|
|
IoSetCompletionRoutine( Irp,
|
|
DbgTestGetDeviceStringCompletion,
|
|
(PVOID)NULL,
|
|
TRUE,
|
|
TRUE,
|
|
TRUE);
|
|
|
|
HidpGetIndexedString(fdoExt, Irp, stringIndex, languageId);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define DBG_MAX_DEVOBJ_RECORDS 100
|
|
dbgDevObjRecord dbgDevObjs[DBG_MAX_DEVOBJ_RECORDS] = {0};
|
|
|
|
VOID DbgRecordDevObj(PDEVICE_OBJECT devObj, PCHAR str)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < DBG_MAX_DEVOBJ_RECORDS; i++){
|
|
if (!ISPTR(dbgDevObjs[i].devObj)){
|
|
break;
|
|
}
|
|
else if (dbgDevObjs[i].devObj == devObj){
|
|
// already there
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((i < DBG_MAX_DEVOBJ_RECORDS) && !dbgDevObjs[i].devObj){
|
|
ULONG j;
|
|
dbgDevObjs[i].devObj = devObj;
|
|
for (j = 0; str[j] && (j < dbgDevObjRecord_STRINGSIZE); j++){
|
|
dbgDevObjs[i].str[j] = str[j];
|
|
}
|
|
}
|
|
}
|
|
|
|
#define DBG_MAX_FEATURE_RECORDS 0x1000
|
|
dbgFeatureRecord dbgFeatures[DBG_MAX_FEATURE_RECORDS] = {0};
|
|
ULONG dbgFeatureFirstFreeIndex = 0;
|
|
VOID DbgRecordReport(ULONG reportId, ULONG controlCode, BOOLEAN isComplete)
|
|
{
|
|
ULONG typeId;
|
|
|
|
switch (controlCode){
|
|
case IOCTL_HID_GET_FEATURE: typeId = (ULONG)'fteG'; break;
|
|
case IOCTL_HID_SET_FEATURE: typeId = (ULONG)'fteS'; break;
|
|
case IOCTL_HID_GET_INPUT_REPORT: typeId = (ULONG)'iteG'; break;
|
|
case IOCTL_HID_SET_OUTPUT_REPORT: typeId = (ULONG)'oteS'; break;
|
|
default: typeId = (ULONG)'xxxx'; TRAP; break;
|
|
}
|
|
|
|
if (isComplete){
|
|
LONG i;
|
|
// step back to find the report that got completed
|
|
// assumes no overlapped calls to same feature
|
|
ASSERT(dbgFeatureFirstFreeIndex > 0);
|
|
i = dbgFeatureFirstFreeIndex-1;
|
|
while ((i >= 0) &&
|
|
((dbgFeatures[i].reportId != reportId) ||
|
|
(dbgFeatures[i].type != typeId) ||
|
|
dbgFeatures[i].completed)){
|
|
i--;
|
|
}
|
|
ASSERT(i >= 0);
|
|
if (i >= 0){
|
|
dbgFeatures[i].completed = 1;
|
|
}
|
|
}
|
|
else {
|
|
if (dbgFeatureFirstFreeIndex >= DBG_MAX_FEATURE_RECORDS){
|
|
RtlZeroMemory(dbgFeatures, sizeof(dbgFeatures));
|
|
dbgFeatureFirstFreeIndex = 0;
|
|
}
|
|
|
|
dbgFeatures[dbgFeatureFirstFreeIndex].marker = (ULONG)'taeF';
|
|
dbgFeatures[dbgFeatureFirstFreeIndex].reportId = reportId;
|
|
dbgFeatures[dbgFeatureFirstFreeIndex].type = typeId;
|
|
dbgFeatures[dbgFeatureFirstFreeIndex].completed = 0;
|
|
dbgFeatureFirstFreeIndex++;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#define DBG_MAX_READ_RECORDS 0x1000
|
|
dbgReadRecord dbgReads[DBG_MAX_READ_RECORDS] = {0};
|
|
VOID DbgRecordRead(PIRP irp, ULONG length, ULONG reportId, ULONG completed)
|
|
{
|
|
LONG i;
|
|
|
|
for (i = 0;
|
|
(i < DBG_MAX_READ_RECORDS) &&
|
|
dbgReads[i].irpPtr &&
|
|
((dbgReads[i].irpPtr != (ULONG_PTR)irp) || dbgReads[i].completed);
|
|
i++){
|
|
}
|
|
|
|
if (i < DBG_MAX_READ_RECORDS){
|
|
if (dbgReads[i].irpPtr){
|
|
ASSERT(dbgReads[i].irpPtr == (ULONG_PTR)irp);
|
|
ASSERT(!dbgReads[i].completed);
|
|
ASSERT(completed);
|
|
dbgReads[i].length = length;
|
|
dbgReads[i].reportId = reportId;
|
|
dbgReads[i].completed = completed;
|
|
}
|
|
else {
|
|
dbgReads[i].irpPtr = (ULONG_PTR)irp;
|
|
dbgReads[i].length = length;
|
|
dbgReads[i].reportId = reportId;
|
|
dbgReads[i].completed = completed;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID DbgLogIrpMajor(ULONG_PTR irpPtr, ULONG majorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
|
|
{
|
|
|
|
if (dbgVerbose){
|
|
char *funcName;
|
|
|
|
switch (majorFunc){
|
|
#undef MAKE_CASE
|
|
#define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
|
|
|
|
MAKE_CASE(IRP_MJ_CREATE)
|
|
MAKE_CASE(IRP_MJ_CREATE_NAMED_PIPE)
|
|
MAKE_CASE(IRP_MJ_CLOSE)
|
|
MAKE_CASE(IRP_MJ_READ)
|
|
MAKE_CASE(IRP_MJ_WRITE)
|
|
MAKE_CASE(IRP_MJ_QUERY_INFORMATION)
|
|
MAKE_CASE(IRP_MJ_SET_INFORMATION)
|
|
MAKE_CASE(IRP_MJ_QUERY_EA)
|
|
MAKE_CASE(IRP_MJ_SET_EA)
|
|
MAKE_CASE(IRP_MJ_FLUSH_BUFFERS)
|
|
MAKE_CASE(IRP_MJ_QUERY_VOLUME_INFORMATION)
|
|
MAKE_CASE(IRP_MJ_SET_VOLUME_INFORMATION)
|
|
MAKE_CASE(IRP_MJ_DIRECTORY_CONTROL)
|
|
MAKE_CASE(IRP_MJ_FILE_SYSTEM_CONTROL)
|
|
MAKE_CASE(IRP_MJ_DEVICE_CONTROL)
|
|
MAKE_CASE(IRP_MJ_INTERNAL_DEVICE_CONTROL)
|
|
MAKE_CASE(IRP_MJ_SHUTDOWN)
|
|
MAKE_CASE(IRP_MJ_LOCK_CONTROL)
|
|
MAKE_CASE(IRP_MJ_CLEANUP)
|
|
MAKE_CASE(IRP_MJ_CREATE_MAILSLOT)
|
|
MAKE_CASE(IRP_MJ_QUERY_SECURITY)
|
|
MAKE_CASE(IRP_MJ_SET_SECURITY)
|
|
MAKE_CASE(IRP_MJ_POWER)
|
|
MAKE_CASE(IRP_MJ_SYSTEM_CONTROL)
|
|
MAKE_CASE(IRP_MJ_DEVICE_CHANGE)
|
|
MAKE_CASE(IRP_MJ_QUERY_QUOTA)
|
|
MAKE_CASE(IRP_MJ_SET_QUOTA)
|
|
MAKE_CASE(IRP_MJ_PNP)
|
|
|
|
default: funcName = NULL; break;
|
|
}
|
|
|
|
if (isComplete){
|
|
if (funcName){
|
|
DBGOUT(("< %s for %s status=%xh (irp=%ph)",
|
|
funcName,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
status,
|
|
irpPtr));
|
|
}
|
|
else {
|
|
DBGOUT(("< ????<majorFunc=%xh> for %s status=%xh (irp=%ph)",
|
|
majorFunc,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
status,
|
|
irpPtr));
|
|
}
|
|
}
|
|
else {
|
|
if (funcName){
|
|
DBGOUT(("> %s (irp=%xh)", funcName, irpPtr));
|
|
}
|
|
else {
|
|
DBGOUT(("> ????<majorFunc=%xh> (irp=%xh)", majorFunc, irpPtr));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DBG_MAX_PNP_IRP_RECORDS 0x1000
|
|
dbgPnPIrpRecord dbgPnPIrps[DBG_MAX_PNP_IRP_RECORDS] = {0};
|
|
|
|
VOID DbgLogPnpIrp(ULONG_PTR irpPtr, ULONG minorFunc, ULONG isForCollectionPdo, ULONG isComplete, ULONG status)
|
|
{
|
|
char *funcName;
|
|
ULONG funcShortName;
|
|
int i;
|
|
|
|
switch (minorFunc){
|
|
#undef MAKE_CASE
|
|
#define MAKE_CASE(fnc) case fnc: funcName = #fnc; funcShortName = *(ULONG *)(funcName+7); break;
|
|
|
|
MAKE_CASE(IRP_MN_START_DEVICE)
|
|
MAKE_CASE(IRP_MN_QUERY_REMOVE_DEVICE)
|
|
MAKE_CASE(IRP_MN_REMOVE_DEVICE)
|
|
MAKE_CASE(IRP_MN_CANCEL_REMOVE_DEVICE)
|
|
MAKE_CASE(IRP_MN_STOP_DEVICE)
|
|
MAKE_CASE(IRP_MN_QUERY_STOP_DEVICE)
|
|
MAKE_CASE(IRP_MN_CANCEL_STOP_DEVICE)
|
|
MAKE_CASE(IRP_MN_QUERY_DEVICE_RELATIONS)
|
|
MAKE_CASE(IRP_MN_QUERY_INTERFACE)
|
|
MAKE_CASE(IRP_MN_QUERY_CAPABILITIES)
|
|
MAKE_CASE(IRP_MN_QUERY_RESOURCES)
|
|
MAKE_CASE(IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
|
|
MAKE_CASE(IRP_MN_QUERY_DEVICE_TEXT)
|
|
MAKE_CASE(IRP_MN_READ_CONFIG)
|
|
MAKE_CASE(IRP_MN_WRITE_CONFIG)
|
|
MAKE_CASE(IRP_MN_EJECT)
|
|
MAKE_CASE(IRP_MN_SET_LOCK)
|
|
MAKE_CASE(IRP_MN_QUERY_ID)
|
|
MAKE_CASE(IRP_MN_QUERY_PNP_DEVICE_STATE)
|
|
MAKE_CASE(IRP_MN_QUERY_BUS_INFORMATION)
|
|
MAKE_CASE(IRP_MN_DEVICE_USAGE_NOTIFICATION)
|
|
MAKE_CASE(IRP_MN_SURPRISE_REMOVAL)
|
|
|
|
#ifndef IRP_MN_QUERY_LEGACY_BUS_INFORMATION
|
|
#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
|
|
#endif // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
|
|
MAKE_CASE(IRP_MN_QUERY_LEGACY_BUS_INFORMATION)
|
|
|
|
default: funcName = NULL; funcShortName = (ULONG)'\?\?\?\?'; break;
|
|
}
|
|
|
|
if (dbgVerbose){
|
|
if (isComplete){
|
|
if (funcName){
|
|
DBGOUT((" < %s for %s status=%xh (irp=%ph)",
|
|
funcName,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
status,
|
|
irpPtr));
|
|
}
|
|
else {
|
|
DBGOUT((" < ?? <minorFunc=%xh> for %s status=%xh (irp=%ph)",
|
|
minorFunc,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
status,
|
|
irpPtr));
|
|
}
|
|
}
|
|
else {
|
|
if (funcName){
|
|
DBGOUT((" > %s for %s (irp=%xh)",
|
|
funcName,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
irpPtr));
|
|
}
|
|
else {
|
|
DBGOUT((" > ?? <minorFunc=%xh> for %s (irp=%xh)",
|
|
minorFunc,
|
|
isForCollectionPdo ? "collection" : "device",
|
|
irpPtr));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isComplete){
|
|
for (i = 0; (i < DBG_MAX_PNP_IRP_RECORDS) && dbgPnPIrps[i].irpPtr; i++){
|
|
if ((dbgPnPIrps[i].irpPtr == irpPtr) &&
|
|
((dbgPnPIrps[i].status == 0xFFFFFFFF) || (dbgPnPIrps[i].status == STATUS_PENDING))){
|
|
dbgPnPIrps[i].status = status;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i < DBG_MAX_PNP_IRP_RECORDS; i++){
|
|
if (!dbgPnPIrps[i].irpPtr){
|
|
dbgPnPIrps[i].irpPtr = irpPtr;
|
|
dbgPnPIrps[i].func = funcShortName;
|
|
dbgPnPIrps[i].isForCollectionPdo = isForCollectionPdo;
|
|
dbgPnPIrps[i].status = 0xFFFFFFFF;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID DbgLogPowerIrp(PVOID devExt, UCHAR minorFunc, ULONG isClientPdo, ULONG isComplete, PCHAR type, ULONG powerState, ULONG status)
|
|
{
|
|
char *funcName;
|
|
|
|
switch (minorFunc){
|
|
#undef MAKE_CASE
|
|
#define MAKE_CASE(fnc) case fnc: funcName = #fnc; break;
|
|
|
|
MAKE_CASE(IRP_MN_WAIT_WAKE)
|
|
MAKE_CASE(IRP_MN_POWER_SEQUENCE)
|
|
MAKE_CASE(IRP_MN_SET_POWER)
|
|
MAKE_CASE(IRP_MN_QUERY_POWER)
|
|
|
|
default: funcName = "????"; break;
|
|
}
|
|
|
|
|
|
if (dbgVerbose){
|
|
if (isComplete){
|
|
DBGOUT((" < %s for %s(ext=%ph) status=%xh ",
|
|
funcName,
|
|
isClientPdo ? "collection" : "device",
|
|
devExt,
|
|
status));
|
|
}
|
|
else if (minorFunc == IRP_MN_SET_POWER){
|
|
DBGOUT((" > %s for %s(ext=%ph) type=%s, powerState=%ph",
|
|
funcName,
|
|
isClientPdo ? "collection" : "device",
|
|
devExt,
|
|
type,
|
|
powerState));
|
|
}
|
|
else {
|
|
DBGOUT((" > %s for %s(ext=%ph) ",
|
|
funcName,
|
|
isClientPdo ? "collection" : "device",
|
|
devExt));
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#define DBG_MAX_REPORT_RECORDS 0x100
|
|
dbgReportRecord dbgReportRecords[DBG_MAX_REPORT_RECORDS] = { 0 };
|
|
ULONG dbgCurrentReportRecord = 0;
|
|
|
|
VOID DbgLogReport(ULONG collectionNumber, ULONG numRecipients, ULONG numPending, ULONG numFailed, PUCHAR report, ULONG reportLength)
|
|
{
|
|
ASSERT(dbgCurrentReportRecord <= DBG_MAX_REPORT_RECORDS);
|
|
|
|
if (dbgCurrentReportRecord == DBG_MAX_REPORT_RECORDS){
|
|
RtlZeroMemory(dbgReportRecords, DBG_MAX_REPORT_RECORDS*sizeof(dbgReportRecord));
|
|
dbgCurrentReportRecord = 0;
|
|
}
|
|
|
|
dbgReportRecords[dbgCurrentReportRecord].collectionNumber = (UCHAR)collectionNumber;
|
|
dbgReportRecords[dbgCurrentReportRecord].numRecipients = (UCHAR)numRecipients;
|
|
if (reportLength > sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes)){
|
|
reportLength = sizeof(dbgReportRecords[dbgCurrentReportRecord].reportBytes);
|
|
}
|
|
RtlCopyMemory((PUCHAR)dbgReportRecords[dbgCurrentReportRecord].reportBytes, report, reportLength);
|
|
|
|
dbgCurrentReportRecord++;
|
|
|
|
if (dbgVerbose){
|
|
ULONG i;
|
|
|
|
DBGOUT(("Report (cltn #%d, %d recipients; %d pending, %d failed):", collectionNumber, numRecipients, numPending, numFailed));
|
|
DbgPrint("'\t report bytes: \t");
|
|
for (i = 0; i < reportLength; i++){
|
|
DbgPrint("%02x ", report[i]);
|
|
}
|
|
DbgPrint("\n");
|
|
}
|
|
}
|
|
|
|
|
|
VOID DbgLogIoctl(ULONG_PTR fdo, ULONG ioControlCode, ULONG status)
|
|
{
|
|
if (dbgVerbose){
|
|
PCHAR ioctlStr;
|
|
|
|
switch (ioControlCode){
|
|
#undef MAKE_CASE
|
|
#define MAKE_CASE(ioctl) case ioctl: ioctlStr = #ioctl; break;
|
|
|
|
MAKE_CASE(IOCTL_HID_GET_DRIVER_CONFIG)
|
|
MAKE_CASE(IOCTL_HID_SET_DRIVER_CONFIG)
|
|
MAKE_CASE(IOCTL_HID_GET_POLL_FREQUENCY_MSEC)
|
|
MAKE_CASE(IOCTL_HID_SET_POLL_FREQUENCY_MSEC)
|
|
MAKE_CASE(IOCTL_GET_NUM_DEVICE_INPUT_BUFFERS)
|
|
MAKE_CASE(IOCTL_SET_NUM_DEVICE_INPUT_BUFFERS)
|
|
MAKE_CASE(IOCTL_HID_GET_COLLECTION_INFORMATION)
|
|
MAKE_CASE(IOCTL_HID_GET_COLLECTION_DESCRIPTOR)
|
|
MAKE_CASE(IOCTL_HID_FLUSH_QUEUE)
|
|
MAKE_CASE(IOCTL_HID_SET_FEATURE)
|
|
MAKE_CASE(IOCTL_HID_GET_FEATURE)
|
|
MAKE_CASE(IOCTL_GET_PHYSICAL_DESCRIPTOR)
|
|
MAKE_CASE(IOCTL_HID_GET_HARDWARE_ID)
|
|
MAKE_CASE(IOCTL_HID_GET_MANUFACTURER_STRING)
|
|
MAKE_CASE(IOCTL_HID_GET_PRODUCT_STRING)
|
|
MAKE_CASE(IOCTL_HID_GET_SERIALNUMBER_STRING)
|
|
MAKE_CASE(IOCTL_HID_GET_INDEXED_STRING)
|
|
MAKE_CASE(IOCTL_INTERNAL_HID_SET_BLUESCREEN)
|
|
|
|
default: ioctlStr = "???"; break;
|
|
}
|
|
|
|
DBGOUT(("IOCTL %s (%xh) status=%xh (fdo=%ph)",
|
|
ioctlStr, ioControlCode, status, fdo));
|
|
}
|
|
}
|
|
|
|
#endif
|