#pragma PAGEDCODE NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("DriverB:Enter B HelloDDKRead ")); NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING DeviceName; RtlInitUnicodeString( &DeviceName, L"\Device\MyDDKDeviceA" ); PDEVICE_OBJECT DeviceObject = NULL; PFILE_OBJECT FileObject = NULL; //得到设备对象指针 ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject); KdPrint(("DriverB:FileObject:%x ",FileObject)); KdPrint(("DriverB:DeviceObject:%x ",DeviceObject)); if (!NT_SUCCESS(ntStatus)) { KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x ", ntStatus )); ntStatus = STATUS_UNSUCCESSFUL; // 完成IRP pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("DriverB:Leave B HelloDDKRead ")); return ntStatus; } KEVENT event; KeInitializeEvent(&event,NotificationEvent,FALSE); PIRP pNewIrp = IoAllocateIrp(DeviceObject->StackSize,FALSE); KdPrint(("pNewIrp->UserEvent :%x ",pNewIrp->UserEvent)); pNewIrp->UserEvent = &event; IO_STATUS_BLOCK status_block; pNewIrp->UserIosb = &status_block; pNewIrp->Tail.Overlay.Thread = PsGetCurrentThread(); //因为DriverA是BUFFER IO设备 pNewIrp->AssociatedIrp.SystemBuffer = NULL; KdPrint(("DriverB:pNewIrp:%x ",pNewIrp)); PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp); stack->MajorFunction = IRP_MJ_READ; stack->MinorFunction=IRP_MN_NORMAL;//0 stack->FileObject = FileObject; //调用DriverA驱动 NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp); if (status == STATUS_PENDING) { status = KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, // Not alertable NULL); KdPrint(("STATUS_PENDING ")); } ObDereferenceObject( FileObject ); IoFreeIrp(pNewIrp); ntStatus = STATUS_SUCCESS; // 完成IRP pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("DriverB:Leave B HelloDDKRead ")); return ntStatus; }
《windows驱动开发详解》中有一个例子,使用DriverB创建一个DriverA的IRP并使用IoCallDriver发送IRP请求,我不明白为什么在设置DriverA堆栈时使用IoGetNextIrpStackLocation 获取下层堆栈并设置