Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/driver.c | 47 ++++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/driver.h | 1 + include/ddk/wdm.h | 8 ++++++ 3 files changed, 56 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index fa8d7b20e3..f4b373264f 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1570,6 +1570,33 @@ static void test_stack_limits(void) ok(low < (ULONG_PTR)&low && (ULONG_PTR)&low < high, "stack variable is not in stack limits\n"); }
+static unsigned int got_completion; + +static NTSTATUS WINAPI completion_cb(DEVICE_OBJECT *device, IRP *irp, void *context) +{ + todo_wine ok(device == context, "Got device %p; expected %p.\n", device, context); + ++got_completion; + return STATUS_SUCCESS; +} + +static void test_completion(void) +{ + IO_STATUS_BLOCK io; + NTSTATUS ret; + KEVENT event; + IRP *irp; + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + irp = IoBuildDeviceIoControlRequest(IOCTL_WINETEST_COMPLETION, upper_device, + NULL, 0, NULL, 0, FALSE, &event, &io); + + IoSetCompletionRoutine(irp, completion_cb, NULL, TRUE, TRUE, TRUE); + ret = IoCallDriver(upper_device, irp); + ok(ret == STATUS_SUCCESS, "IoCallDriver returned %#x\n", ret); + ok(got_completion == 2, "got %u calls to completion routine\n"); +} + static void test_IoAttachDeviceToDeviceStack(void) { DEVICE_OBJECT *dev1, *dev2, *dev3, *ret; @@ -1714,6 +1741,7 @@ static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) test_call_driver(device); test_cancel_irp(device); test_stack_limits(); + test_completion();
/* print process report */ if (winetest_debug) @@ -2174,6 +2202,23 @@ static NTSTATUS test_mismatched_status_ioctl(IRP *irp, IO_STACK_LOCATION *stack, return STATUS_SUCCESS; }
+static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp) +{ + if (device == upper_device) + { + IoCopyCurrentIrpStackLocationToNext(irp); + IoSetCompletionRoutine(irp, completion_cb, upper_device, TRUE, TRUE, TRUE); + return IoCallDriver(lower_device, irp); + } + else + { + ok(device == lower_device, "Got wrong device.\n"); + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } +} + static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); @@ -2237,6 +2282,8 @@ static NTSTATUS WINAPI driver_IoControl(DEVICE_OBJECT *device, IRP *irp) break; case IOCTL_WINETEST_MISMATCHED_STATUS: return test_mismatched_status_ioctl(irp, stack, &irp->IoStatus.Information); + case IOCTL_WINETEST_COMPLETION: + return test_completion_ioctl(device, irp); default: break; } diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index 6012efc41c..4b70046b8e 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -34,6 +34,7 @@ #define IOCTL_WINETEST_GET_FSCONTEXT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_RETURN_STATUS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80a, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_MISMATCHED_STATUS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80b, METHOD_NEITHER, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_COMPLETION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80c, METHOD_NEITHER, FILE_ANY_ACCESS)
static const char teststr[] = "Wine is not an emulator";
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 78667a95db..e2108b9852 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1606,6 +1606,14 @@ static inline void IoMarkIrpPending(IRP *irp) IoGetCurrentIrpStackLocation(irp)->Control |= SL_PENDING_RETURNED; }
+static inline void IoCopyCurrentIrpStackLocationToNext(IRP *irp) +{ + IO_STACK_LOCATION *current = IoGetCurrentIrpStackLocation(irp); + IO_STACK_LOCATION *next = IoGetNextIrpStackLocation(irp); + memcpy(next, current, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); + next->Control = 0; +} + #define KernelMode 0 #define UserMode 1
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index ebdd623eec..b49b288fa9 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1902,6 +1902,7 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost ) IO_STACK_LOCATION *irpsp; PIO_COMPLETION_ROUTINE routine; NTSTATUS status, stat; + DEVICE_OBJECT *device; int call_flag = 0;
TRACE( "%p %u\n", irp, priority_boost ); @@ -1923,11 +1924,14 @@ VOID WINAPI IoCompleteRequest( IRP *irp, UCHAR priority_boost ) } ++irp->CurrentLocation; ++irp->Tail.Overlay.s.u2.CurrentStackLocation; + if (irp->CurrentLocation <= irp->StackCount) + device = IoGetCurrentIrpStackLocation(irp)->DeviceObject; + else + device = NULL; if (call_flag) { - TRACE( "calling %p( %p, %p, %p )\n", routine, - irpsp->DeviceObject, irp, irpsp->Context ); - stat = routine( irpsp->DeviceObject, irp, irpsp->Context ); + TRACE( "calling %p( %p, %p, %p )\n", routine, device, irp, irpsp->Context ); + stat = routine( device, irp, irpsp->Context ); TRACE( "CompletionRoutine returned %x\n", stat ); if (STATUS_MORE_PROCESSING_REQUIRED == stat) return;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=73487
Your paranoid android.
=== debiant (32 bit report) ===
ntoskrnl.exe: driver.c:1577: Test succeeded inside todo block: Got device 001FBCD8; expected 001FBCD8. driver.c:1577: Test succeeded inside todo block: Got device 00000000; expected 00000000.
Report validation errors: ntoskrnl.exe:ntoskrnl returned success despite having failures
=== debiant (32 bit Chinese:China report) ===
ntoskrnl.exe: driver.c:1577: Test succeeded inside todo block: Got device 00A0AD88; expected 00A0AD88. driver.c:1577: Test succeeded inside todo block: Got device 00000000; expected 00000000.
Report validation errors: ntoskrnl.exe:ntoskrnl returned success despite having failures