diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 3c8b207a4a3..e9c35cf7e31 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -975,6 +975,17 @@ void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size ) (PIO_STACK_LOCATION)(irp + 1) + stack_size; } +void WINAPI IoReuseIrp(IRP *irp, NTSTATUS iostatus) +{ + UCHAR AllocationFlags; + + TRACE("irp %p, iostatus %#x.\n", irp, iostatus); + + AllocationFlags = irp->AllocationFlags; + IoInitializeIrp(irp, irp->Size, irp->StackCount); + irp->AllocationFlags = AllocationFlags; + irp->IoStatus.u.Status = iostatus; +} /*********************************************************************** * IoInitializeTimer (NTOSKRNL.EXE.@) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index c4426566940..3b36a62269d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -462,7 +462,7 @@ @ stub IoReportTargetDeviceChange @ stub IoReportTargetDeviceChangeAsynchronous @ stub IoRequestDeviceEject -@ stub IoReuseIrp +@ stdcall IoReuseIrp(ptr long) @ stub IoSetCompletionRoutineEx @ stdcall IoSetDeviceInterfaceState(ptr long) @ stub IoSetDeviceToVerify diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index e762ad0ccd7..f6cc442bab0 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -211,9 +211,18 @@ static void *get_proc_address(const char *name) static FILE_OBJECT *last_created_file; static unsigned int create_count, close_count; +static NTSTATUS WINAPI test_irp_struct_completion_routine(DEVICE_OBJECT *reserved, IRP *irp, void *context) +{ + unsigned int *result = context; + + *result = 1; + return STATUS_MORE_PROCESSING_REQUIRED; +} + static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + unsigned int irp_completion_result; ok(device == upper_device, "Expected device %p, got %p.\n", upper_device, device); ok(last_created_file != NULL, "last_created_file = NULL\n"); @@ -225,6 +234,34 @@ static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device) "IRP thread is not the current thread\n"); ok(IoGetRequestorProcess(irp) == IoGetCurrentProcess(), "processes didn't match\n"); + + irp = IoAllocateIrp(1, FALSE); + ok(irp->AllocationFlags == IRP_ALLOCATED_FIXED_SIZE, "Got unexpected irp->AllocationFlags %#x.\n", + irp->AllocationFlags); + ok(irp->CurrentLocation == 2, + "Got unexpected irp->CurrentLocation %u.\n", irp->CurrentLocation); + IoSetCompletionRoutine(irp, test_irp_struct_completion_routine, &irp_completion_result, + TRUE, TRUE, TRUE); + + irp_completion_result = 0; + + irp->IoStatus.Status = STATUS_SUCCESS; + --irp->CurrentLocation; + --irp->Tail.Overlay.CurrentStackLocation; + IoCompleteRequest(irp, IO_NO_INCREMENT); + ok(irp->CurrentLocation == 2, + "Got unexpected irp->CurrentLocation %u.\n", irp->CurrentLocation); + ok(irp_completion_result, "IRP completion was not called.\n"); + + --irp->CurrentLocation; + --irp->Tail.Overlay.CurrentStackLocation; + IoReuseIrp(irp, STATUS_UNSUCCESSFUL); + ok(irp->CurrentLocation == 2, + "Got unexpected irp->CurrentLocation %u.\n", irp->CurrentLocation); + ok(irp->AllocationFlags == IRP_ALLOCATED_FIXED_SIZE, "Got unexpected irp->AllocationFlags %#x.\n", + irp->AllocationFlags); + + IoFreeIrp(irp); } static void test_mdl_map(void) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 0d98680cfa5..57e4cf4fe53 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1679,6 +1679,7 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(PDEVICE_OBJECT,const GUID*,PUNICODE_S void WINAPI IoReleaseCancelSpinLock(KIRQL); void WINAPI IoReleaseRemoveLockAndWaitEx(IO_REMOVE_LOCK*,void*,ULONG); void WINAPI IoReleaseRemoveLockEx(IO_REMOVE_LOCK*,void*,ULONG); +void WINAPI IoReuseIrp(IRP*,NTSTATUS); NTSTATUS WINAPI IoSetDeviceInterfaceState(UNICODE_STRING*,BOOLEAN); NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT,ULONG);