KdPrint/DbgPrint and UNICODE_STRING/ANSI_STRING

KdPrint/DbgPrint and UNICODE_STRING/ANSI_STRING

KdPrint/DbgPrint and UNICODE_STRING/ANSI_STRING 
KdPrint/DbgPrint and UNICODE_STRING/ANSI_STRING
Just to remember:
NT likes string of the following form: 

typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;

typedef struct _STRING {
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} STRING;
typedef STRING *PSTRING;

typedef STRING ANSI_STRING;
typedef PSTRING PANSI_STRING;



To make life easier MS have extended kernel CRTL output() function with Z format specifier. This works for all kernel functions those understand formatted strings (e.g. sprintf, _vsnprintf, KdPrint/DbgPrint). For example: 

PUNICODE_STRING pUStr;
PANSI_STRING pAStr;
...
KdPrint(("Unicode string: %wZ\n", pUStr));
KdPrint(("ANSI string: %Z\n", pAStr));

Though, you can use a little more complicated documented way. Btw, this form is suitable for printing byte array of strictly defined length. 

KdPrint(("Unicode string: %*.*ws\n",pUStr->Length/sizeof(WCHAR),
pUStr->Length/sizeof(WCHAR), pUStr));
KdPrint(("Unicode string: %*.*S\n",pUStr->Length/sizeof(WCHAR),
pUStr->Length/sizeof(WCHAR), pUStr));
KdPrint(("ANSI string: %*.*s\n", pAStr->Length/sizeof(CHAR),
pAStr->Length/sizeof(CHAR), pAStr));

Or, if you want to take into account NULL-terminator, but limit output length to specified number of characters: 

KdPrint(("Unicode string: %.*ws\n",
pUStr->Length/sizeof(WCHAR), pUStr));
KdPrint(("Unicode string: %.*S\n",
pUStr->Length/sizeof(WCHAR), pUStr));
KdPrint(("ANSI string: %.*s\n",
pAStr->Length/sizeof(CHAR), pAStr));

转 http://hi.baidu.com/deathsoft/item/4f5415ece5f97f0f64db005d
#include <ntddk.h> #include <wdm.h> #include <ntddndis.h> // 调试级别定义(必须放在所有include之后) #define DPFLTR_IHVDRIVER_ID 0x63 // 自定义驱动标识(0-63) #define MYDRIVER_TRACE_LEVEL_INFO DPFLTR_INFO_LEVEL // 0x0 #define MYDRIVER_TRACE_LEVEL_WARNING DPFLTR_WARNING_LEVEL // 0x1 #define MYDRIVER_TRACE_LEVEL_ERROR DPFLTR_ERROR_LEVEL // 0x2 #define MYDRIVER_TRACE_LEVEL_VERBOSE 0x3 // 自定义详细级别 #define IOCTL_PROTOCOL_CONTROL CTL_CODE(FILE_DEVICE_NETWORK, 0x800, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) typedef struct _PROTOCOL_DRIVER { PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject; KEVENT CompletionEvent; IO_STATUS_BLOCK IoStatus; } PROTOCOL_DRIVER; // 协议特征结构 typedef struct _PROTOCOL_CHARACTERISTICS { ULONG Magic; USHORT HeaderSize; UCHAR Checksum; } PROTOCOL_CHARACTERISTICS; // 全局变量 PROTOCOL_DRIVER g_ProtocolDriver; PROTOCOL_CHARACTERISTICS g_ProtocolChars = { 0x4E455449, sizeof(PROTOCOL_CHARACTERISTICS), 0xAA }; // IRP完成回调 NTSTATUS ProtocolIoCompletion( _In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID Context) { UNREFERENCED_PARAMETER(DeviceObject); PKEVENT event = (PKEVENT)Context; KeSetEvent(event, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; } // 绑定到协议驱动 NTSTATUS AttachToProtocolDriver() { UNICODE_STRING protoName; RtlInitUnicodeString(&protoName, L"\\Device\\Tcp"); NTSTATUS status = IoGetDeviceObjectPointer( &protoName, FILE_ALL_ACCESS, &g_ProtocolDriver.FileObject, &g_ProtocolDriver.DeviceObject); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DBG_LEVEL_ERROR, "[%s] Failed to attach to protocol driver: 0x%X\n", __FUNCTION__, status); return status; } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DBG_LEVEL_INFO, "[%s] Successfully attached to protocol driver at 0x%p\n", __FUNCTION__, g_ProtocolDriver.DeviceObject); return STATUS_SUCCESS; }
最新发布
03-31
<think>好的,用户想了解如何通过Windows驱动程序附加到协议驱动并处理IRP完成回调,并需要一个示例。我需要先回忆相关知识点,并结合提供的引用内容来构建答案。 首先,用户提到的“附加到协议驱动”可能是指将驱动程序附加到现有的设备堆栈上,以便拦截和处理IRP。这在Windows驱动开发中是常见的操作,例如过滤驱动程序。根据引用[3]提到的文件系统或过滤器驱动安装时的问题,可能涉及到驱动签名和加载的问题,但用户的问题更关注技术实现。 接下来,处理IRP完成回调需要了解IRP的生命周期。当IRP被发送到底层驱动处理后,在完成时会触发完成例程。开发者可以注册一个完成回调函数来在此处进行处理。引用[4]提到了NTSTATUS代码,这可能与处理IRP时返回的状态有关,例如在回调中检查操作是否成功。 然后,我需要考虑如何正确附加到协议驱动。通常,这涉及到调用IoAttachDeviceToDeviceStackSafe函数来将过滤设备附加到目标设备堆栈。这需要先找到目标设备对象,可能通过设备名称或类型来定位。例如,协议驱动可能有一个特定的设备名称,需要在代码中指定。 然后,编写驱动程序的入口点,如DriverEntry函数,在其中创建设备对象并附加到目标设备。在创建设备对象时,需要设置适当的设备特征和标志,确保正确处理IRP。 处理IRP完成回调时,需要创建一个完成例程函数,并在派遣函数中调用IoSetCompletionRoutineEx来注册它。在完成例程中,可以访问IRP的结果数据,并进行处理。需要注意的是,完成例程中必须正确管理IRP的状态,避免内存泄漏或系统崩溃。 此外,引用[1]提到驱动程序加载失败的问题,可能是因为之前的驱动版本仍在内存中。这提示在开发过程中需要正确卸载驱动,避免残留。引用[2]涉及证书错误,可能和驱动签名有关,但用户的问题可能暂时不需要关注这点,除非示例代码运行时出现签名问题。 最后,确保示例代码符合WDK的规范,使用正确的函数和参数。例如,使用IoCopyCurrentIrpStackLocationToNext来复制IRP栈位置,然后调用IoCallDriver传递IRP。在完成例程中,检查IRP的状态,并执行必要的处理。 总结步骤:附加到协议驱动、设置派遣函数、注册完成回调、处理IRP完成后的操作。同时,注意驱动卸载时的清理工作,如分离设备堆栈和删除设备对象。</think>以下是关于如何通过Windows驱动程序附加到协议驱动并处理IRP完成回调的逐步说明: --- ### 1. **驱动附加到协议驱动的核心步骤** #### (1) 获取目标设备对象 通过设备名称或设备类型定位协议驱动的设备对象。例如,使用`IoGetDeviceObjectPointer`获取目标设备对象指针: ```c UNICODE_STRING targetDeviceName; RtlInitUnicodeString(&targetDeviceName, L"\\Device\\ProtocolDriver"); PFILE_OBJECT fileObject; PDEVICE_OBJECT targetDeviceObject; NTSTATUS status = IoGetDeviceObjectPointer(&targetDeviceName, FILE_ALL_ACCESS, &fileObject, &targetDeviceObject); ``` #### (2) 创建设备对象并附加 创建过滤设备对象,并将其附加到目标设备堆栈: ```c PDEVICE_OBJECT filterDeviceObject; status = IoCreateDevice( DriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &filterDeviceObject ); // 附加到协议驱动的设备堆栈 PDEVICE_OBJECT attachedDevice = IoAttachDeviceToDeviceStackSafe(filterDeviceObject, targetDeviceObject); ``` --- ### 2. **IRP完成回调的实现** #### (1) 定义完成回调函数 在IRP完成时触发的回调函数中处理结果: ```c NTSTATUS CompletionRoutine( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { if (Irp->PendingReturned) { IoMarkIrpPending(Irp); } // 处理IRP完成后的数据(例如读取缓冲区) if (NT_SUCCESS(Irp->IoStatus.Status)) { KdPrint(("IRP completed successfully, Bytes transferred: %d", Irp->IoStatus.Information)); } return STATUS_SUCCESS; } ``` #### (2) 在派遣函数中注册回调 在IRP派遣函数中设置完成回调: ```c NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); // 复制当前IRP栈到下一层驱动 IoCopyCurrentIrpStackLocationToNext(Irp); // 设置完成回调 IoSetCompletionRoutineEx( DeviceObject, Irp, CompletionRoutine, NULL, // Context TRUE, // InvokeOnSuccess TRUE, // InvokeOnError TRUE // InvokeOnCancel ); // 传递IRP到下层驱动 return IoCallDriver(((PFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedDevice, Irp); } ``` --- ### 3. **关键注意事项** - **设备扩展结构**:建议使用设备扩展(`DEVICE_EXTENSION`)存储附加设备对象指针等上下文信息。 - **IRP状态管理**:在完成回调中必须正确处理`Irp->PendingReturned`,否则可能导致系统崩溃[^4]。 - **卸载处理**:在驱动卸载例程中分离设备堆栈并删除设备对象: ```c VOID DriverUnload(PDRIVER_OBJECT DriverObject) { PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; IoDetachDevice(((PFILTER_DEVICE_EXTENSION)deviceObject->DeviceExtension)->AttachedDevice); IoDeleteDevice(deviceObject); } ``` --- ### 示例代码框架 ```c #include <ntddk.h> typedef struct _FILTER_DEVICE_EXTENSION { PDEVICE_OBJECT AttachedDevice; } FILTER_DEVICE_EXTENSION, *PFILTER_DEVICE_EXTENSION; NTSTATUS CompletionRoutine(PDEVICE_OBJECT, PIRP, PVOID); NTSTATUS DispatchRead(PDEVICE_OBJECT, PIRP); VOID DriverUnload(PDRIVER_OBJECT); NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead; // 创建设备并附加到协议驱动(此处需补充设备创建和附加代码) return STATUS_SUCCESS; } ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值