ntoskrnl.exe: Implement IoCancelIrp.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
da5b97c8b4
commit
5f10c86d5b
|
@ -2321,6 +2321,31 @@ void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* IoCancelIrp (NTOSKRNL.EXE.@)
|
||||
*/
|
||||
BOOLEAN WINAPI IoCancelIrp( IRP *irp )
|
||||
{
|
||||
PDRIVER_CANCEL cancel_routine;
|
||||
KIRQL irql;
|
||||
|
||||
TRACE( "(%p)\n", irp );
|
||||
|
||||
IoAcquireCancelSpinLock( &irql );
|
||||
irp->Cancel = TRUE;
|
||||
if (!(cancel_routine = IoSetCancelRoutine( irp, NULL )))
|
||||
{
|
||||
IoReleaseCancelSpinLock( irp->CancelIrql );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* CancelRoutine is responsible for calling IoReleaseCancelSpinLock */
|
||||
irp->CancelIrql = irql;
|
||||
cancel_routine( IoGetCurrentIrpStackLocation(irp)->DeviceObject, irp );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* InterlockedCompareExchange (NTOSKRNL.EXE.@)
|
||||
*/
|
||||
|
|
|
@ -336,7 +336,7 @@
|
|||
@ stdcall IoBuildSynchronousFsdRequest(long ptr ptr long ptr ptr ptr)
|
||||
@ stdcall IoCallDriver(ptr ptr)
|
||||
@ stub IoCancelFileOpen
|
||||
@ stub IoCancelIrp
|
||||
@ stdcall IoCancelIrp(ptr)
|
||||
@ stub IoCheckDesiredAccess
|
||||
@ stub IoCheckEaBufferValidity
|
||||
@ stub IoCheckFunctionAccess
|
||||
|
|
|
@ -758,6 +758,125 @@ static void test_call_driver(DEVICE_OBJECT *device)
|
|||
ok(status == STATUS_SUCCESS, "got %#x\n", status);
|
||||
}
|
||||
|
||||
static int cancel_cnt;
|
||||
|
||||
static void WINAPI cancel_irp(DEVICE_OBJECT *device, IRP *irp)
|
||||
{
|
||||
IoReleaseCancelSpinLock(irp->CancelIrql);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
ok(!irp->CancelRoutine, "CancelRoutine = %p\n", irp->CancelRoutine);
|
||||
irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
irp->IoStatus.Information = 0;
|
||||
cancel_cnt++;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI cancel_test_completion(DEVICE_OBJECT *device, IRP *irp, void *context)
|
||||
{
|
||||
ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
|
||||
*(BOOL*)context = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void test_cancel_irp(DEVICE_OBJECT *device)
|
||||
{
|
||||
IO_STACK_LOCATION *irpsp;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
IRP *irp = NULL;
|
||||
BOOL completion_called;
|
||||
BOOLEAN r;
|
||||
NTSTATUS status;
|
||||
|
||||
/* cancel IRP with no cancel routine */
|
||||
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
|
||||
|
||||
r = IoCancelIrp(irp);
|
||||
ok(!r, "IoCancelIrp returned %x\n", r);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
|
||||
r = IoCancelIrp(irp);
|
||||
ok(!r, "IoCancelIrp returned %x\n", r);
|
||||
IoFreeIrp(irp);
|
||||
|
||||
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
|
||||
|
||||
/* cancel IRP with cancel routine */
|
||||
status = IoCallDriver(device, irp);
|
||||
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
|
||||
|
||||
ok(irp->CurrentLocation == 1, "CurrentLocation = %u\n", irp->CurrentLocation);
|
||||
irpsp = IoGetCurrentIrpStackLocation(irp);
|
||||
ok(irpsp->DeviceObject == device, "DeviceObject = %u\n", irpsp->DeviceObject);
|
||||
|
||||
IoSetCancelRoutine(irp, cancel_irp);
|
||||
cancel_cnt = 0;
|
||||
r = IoCancelIrp(irp);
|
||||
ok(r == TRUE, "IoCancelIrp returned %x\n", r);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
|
||||
|
||||
cancel_cnt = 0;
|
||||
r = IoCancelIrp(irp);
|
||||
ok(!r, "IoCancelIrp returned %x\n", r);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
ok(!cancel_cnt, "cancel_cnt = %d\n", cancel_cnt);
|
||||
|
||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||||
|
||||
/* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_ERROR */
|
||||
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
|
||||
IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, FALSE, TRUE);
|
||||
|
||||
status = IoCallDriver(device, irp);
|
||||
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
|
||||
|
||||
IoSetCancelRoutine(irp, cancel_irp);
|
||||
cancel_cnt = 0;
|
||||
r = IoCancelIrp(irp);
|
||||
ok(r == TRUE, "IoCancelIrp returned %x\n", r);
|
||||
ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
|
||||
completion_called = FALSE;
|
||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||||
ok(completion_called, "completion not called\n");
|
||||
|
||||
/* cancel IRP with cancel and completion routines with no SL_INVOKE_ON_CANCEL flag */
|
||||
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
|
||||
IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, TRUE, FALSE);
|
||||
|
||||
status = IoCallDriver(device, irp);
|
||||
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
|
||||
|
||||
IoSetCancelRoutine(irp, cancel_irp);
|
||||
cancel_cnt = 0;
|
||||
r = IoCancelIrp(irp);
|
||||
ok(r == TRUE, "IoCancelIrp returned %x\n", r);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
|
||||
|
||||
completion_called = FALSE;
|
||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||||
ok(completion_called, "completion not called\n");
|
||||
|
||||
/* cancel IRP with cancel and completion routines, but no SL_INVOKE_ON_ERROR nor SL_INVOKE_ON_CANCEL flag */
|
||||
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, device, NULL, 0, NULL, &iosb);
|
||||
IoSetCompletionRoutine(irp, cancel_test_completion, &completion_called, TRUE, FALSE, FALSE);
|
||||
|
||||
status = IoCallDriver(device, irp);
|
||||
ok(status == STATUS_PENDING, "IoCallDriver returned %#x\n", status);
|
||||
|
||||
IoSetCancelRoutine(irp, cancel_irp);
|
||||
cancel_cnt = 0;
|
||||
r = IoCancelIrp(irp);
|
||||
ok(r == TRUE, "IoCancelIrp returned %x\n", r);
|
||||
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||
ok(cancel_cnt == 1, "cancel_cnt = %d\n", cancel_cnt);
|
||||
|
||||
completion_called = FALSE;
|
||||
IoCompleteRequest(irp, IO_NO_INCREMENT);
|
||||
ok(!completion_called, "completion not called\n");
|
||||
}
|
||||
|
||||
static int callout_cnt;
|
||||
|
||||
static void WINAPI callout(void *parameter)
|
||||
|
@ -1294,6 +1413,7 @@ static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context)
|
|||
|
||||
test_current_thread(TRUE);
|
||||
test_call_driver(device);
|
||||
test_cancel_irp(device);
|
||||
|
||||
/* print process report */
|
||||
if (winetest_debug)
|
||||
|
|
|
@ -1493,6 +1493,9 @@ NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#define IoSetCancelRoutine(irp, routine) \
|
||||
((PDRIVER_CANCEL)InterlockedExchangePointer((void **)&(irp)->CancelRoutine, routine))
|
||||
|
||||
static inline void IoSetCompletionRoutine(IRP *irp, PIO_COMPLETION_ROUTINE routine, void *context,
|
||||
BOOLEAN on_success, BOOLEAN on_error, BOOLEAN on_cancel)
|
||||
{
|
||||
|
@ -1563,6 +1566,7 @@ PIRP WINAPI IoBuildAsynchronousFsdRequest(ULONG,DEVICE_OBJECT*,void*,ULONG,
|
|||
PIRP WINAPI IoBuildDeviceIoControlRequest(ULONG,DEVICE_OBJECT*,PVOID,ULONG,PVOID,ULONG,BOOLEAN,PKEVENT,IO_STATUS_BLOCK*);
|
||||
PIRP WINAPI IoBuildSynchronousFsdRequest(ULONG,DEVICE_OBJECT*,PVOID,ULONG,PLARGE_INTEGER,PKEVENT,IO_STATUS_BLOCK*);
|
||||
NTSTATUS WINAPI IoCallDriver(DEVICE_OBJECT*,IRP*);
|
||||
BOOLEAN WINAPI IoCancelIrp(IRP*);
|
||||
VOID WINAPI IoCompleteRequest(IRP*,UCHAR);
|
||||
NTSTATUS WINAPI IoCreateDevice(DRIVER_OBJECT*,ULONG,UNICODE_STRING*,DEVICE_TYPE,ULONG,BOOLEAN,DEVICE_OBJECT**);
|
||||
NTSTATUS WINAPI IoCreateDriver(UNICODE_STRING*,PDRIVER_INITIALIZE);
|
||||
|
|
Loading…
Reference in New Issue