в результате приложение получит status, но не получит Irp->IoStatus.Status
вопрос для чего он нужен?
В режиме ядра приложение получит оба кода.
Посмотрим на ф-цию
NTSTATUS ZwDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN PVOID InputBufferLength,
OUT PVOID OutputBuffer,
OUT PVOID OutputBufferLength
);
возвращенное этой ф-цией значение - это то что вернула ф-ция ToasterDispatchIoctl путем return status; . Но как видно ф-ции ZwDeviceIoControlFile необходимо передать PIO_STATUS_BLOCK IoStatusBlock, причем структура *IoStatusBlock должна быть создана, а ее указаетль передается в ф-цию. Этот указатель и копируется в Irp->IoStatus.
Аналогично, если создается просто запрос, например через IoBuildDeviceIoControlRequest или IoAllocateIrp, то необходимр поместить указатель в Irp->IoStatus на созданную структуру IO_STATUS_BLOCK. Тогда IoCallDriver вернет то что вернула ф-ция дтспетчеризации, а в IO_STATUS_BLOCK будет код завершения.
Нужен IO_STATUS_BLOCK именно потому что ф-ция диспетчеризации может вернуть STATUS_PENDING, тем самым отложив обработку, но после ее завершения надо как-то сообщить о статусе- вот он и будет в IO_STATUS_BLOCK. То есть для асинхронных операций имеет значение IO_STATUS_BLOCK так как именно из него берут статус завершения, возвращенный ZwDeviceIoControlFile, а для синхронных операций возвращенное значение и значение в IO_STATUS_BLOCK должны совпадать(я так думаю), так как для синхронных операций сложно сказать на основании чего принимается решение о возврате значения из ZwDeviceIoControlFile пользовательскому приложению, по моему это не определено.
Кстати в примере из DDK для toaster сделано так как я и написал(равны значения) для синхронного запроса. Откуда ты взял свой код?
NTSTATUS
ToasterDispatchIoctl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handle user mode DeviceIoControl requests.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status= STATUS_SUCCESS;
PFDO_DATA fdoData;
PAGED_CODE ();
ToasterDebugPrint((3, "Ioctl called\n"));
fdoData = (PFDO_DATA) DeviceObject->DeviceExtension;
ToasterIoIncrement (fdoData);
if (HoldRequests == fdoData->QueueState) {
return ToasterQueueRequest(fdoData, Irp);
} else if (Deleted == fdoData->DevicePnPState) {
//
// Since the device is removed, we will not hold any IRPs.
// We just fail it.
//
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
ToasterIoDecrement(fdoData);
return STATUS_DELETE_PENDING;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_TOASTER_DONT_DISPLAY_IN_UI_DEVICE:
fdoData->DontDisplayInUI = TRUE;
IoInvalidateDeviceState(fdoData->UnderlyingPDO);
Irp->IoStatus.Information = 0;
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
ToasterIoDecrement(fdoData);
return status;
}