Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/async.c | 2 +- server/change.c | 1 + server/console.c | 6 ++++++ server/device.c | 1 + server/fd.c | 10 ++++++++++ server/file.c | 1 + server/file.h | 4 ++++ server/mailslot.c | 3 +++ server/mapping.c | 1 + server/named_pipe.c | 3 +++ server/serial.c | 1 + server/sock.c | 2 ++ 12 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/server/async.c b/server/async.c index 50cb47dec92..278048bc7a3 100644 --- a/server/async.c +++ b/server/async.c @@ -502,7 +502,7 @@ restart: (!thread || async->thread == thread) && (!iosb || async->data.iosb == iosb)) { - async_terminate( async, STATUS_CANCELLED ); + fd_cancel_async( async->fd, async ); woken++; goto restart; } diff --git a/server/change.c b/server/change.c index b02a9cd65bf..5edeebf89d3 100644 --- a/server/change.c +++ b/server/change.c @@ -144,6 +144,7 @@ static const struct fd_ops dir_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/console.c b/server/console.c index 2a23081037b..3a5b1270116 100644 --- a/server/console.c +++ b/server/console.c @@ -115,6 +115,7 @@ static const struct fd_ops console_fd_ops = console_get_file_info, /* get_file_info */ console_get_volume_info, /* get_volume_info */ console_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -185,6 +186,7 @@ static const struct fd_ops console_server_fd_ops = no_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ console_server_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -254,6 +256,7 @@ static const struct fd_ops screen_buffer_fd_ops = console_get_file_info, /* get_file_info */ console_get_volume_info, /* get_volume_info */ screen_buffer_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -340,6 +343,7 @@ static const struct fd_ops console_input_fd_ops = console_get_file_info, /* get_file_info */ console_get_volume_info, /* get_volume_info */ console_input_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -395,6 +399,7 @@ static const struct fd_ops console_output_fd_ops = console_get_file_info, /* get_file_info */ console_get_volume_info, /* get_volume_info */ console_output_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -451,6 +456,7 @@ static const struct fd_ops console_connection_fd_ops = no_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ console_connection_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/device.c b/server/device.c index d9199e8ddd8..2310de43ac4 100644 --- a/server/device.c +++ b/server/device.c @@ -243,6 +243,7 @@ static const struct fd_ops device_file_fd_ops = default_fd_get_file_info, /* get_file_info */ device_file_get_volume_info, /* get_volume_info */ device_file_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ device_file_reselect_async /* reselect_async */ }; diff --git a/server/fd.c b/server/fd.c index 7a88f412c7a..904b4e4217d 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2216,6 +2216,11 @@ void fd_async_wake_up( struct fd *fd, int type, unsigned int status ) } }
+void fd_cancel_async( struct fd *fd, struct async *async ) +{ + fd->fd_ops->cancel_async( fd, async ); +} + void fd_reselect_async( struct fd *fd, struct async_queue *queue ) { fd->fd_ops->reselect_async( fd, queue ); @@ -2226,6 +2231,11 @@ void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count set_error( STATUS_OBJECT_TYPE_MISMATCH ); }
+void default_fd_cancel_async( struct fd *fd, struct async *async ) +{ + async_terminate( async, STATUS_CANCELLED ); +} + void default_fd_queue_async( struct fd *fd, struct async *async, int type, int count ) { fd_queue_async( fd, async, type ); diff --git a/server/file.c b/server/file.c index aff4d9e09e1..2c7cb0ce5ca 100644 --- a/server/file.c +++ b/server/file.c @@ -124,6 +124,7 @@ static const struct fd_ops file_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/file.h b/server/file.h index b481a68e530..22879b75c05 100644 --- a/server/file.h +++ b/server/file.h @@ -68,6 +68,8 @@ struct fd_ops void (*get_volume_info)( struct fd *, struct async *, unsigned int ); /* perform an ioctl on the file */ void (*ioctl)(struct fd *fd, ioctl_code_t code, struct async *async ); + /* cancel an async operation */ + void (*cancel_async)(struct fd *fd, struct async *async); /* queue an async operation */ void (*queue_async)(struct fd *, struct async *async, int type, int count); /* selected events for async i/o need an update */ @@ -106,6 +108,7 @@ extern void get_nt_name( struct fd *fd, struct unicode_str *name ); extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry ); extern int default_fd_get_poll_events( struct fd *fd ); extern void default_poll_event( struct fd *fd, int event ); +extern void fd_cancel_async( struct fd *fd, struct async *async ); extern void fd_queue_async( struct fd *fd, struct async *async, int type ); extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status ); extern void fd_reselect_async( struct fd *fd, struct async_queue *queue ); @@ -117,6 +120,7 @@ extern void default_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsign extern void no_fd_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class ); extern void no_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); extern void default_fd_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); +extern void default_fd_cancel_async( struct fd *fd, struct async *async ); extern void no_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void default_fd_queue_async( struct fd *fd, struct async *async, int type, int count ); extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue ); diff --git a/server/mailslot.c b/server/mailslot.c index d4b2fd1b562..1f4cb87d0fc 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -108,6 +108,7 @@ static const struct fd_ops mailslot_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ mailslot_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -165,6 +166,7 @@ static const struct fd_ops mail_writer_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; @@ -255,6 +257,7 @@ static const struct fd_ops mailslot_device_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/mapping.c b/server/mapping.c index a814fe8090f..eb500ea67f4 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -204,6 +204,7 @@ static const struct fd_ops mapping_fd_ops = no_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ no_fd_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ no_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/named_pipe.c b/server/named_pipe.c index 234dfc701d9..f964ae19637 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -194,6 +194,7 @@ static const struct fd_ops pipe_server_fd_ops = pipe_end_get_file_info, /* get_file_info */ pipe_end_get_volume_info, /* get_volume_info */ pipe_server_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ no_fd_queue_async, /* queue_async */ pipe_end_reselect_async /* reselect_async */ }; @@ -237,6 +238,7 @@ static const struct fd_ops pipe_client_fd_ops = pipe_end_get_file_info, /* get_file_info */ pipe_end_get_volume_info, /* get_volume_info */ pipe_client_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ no_fd_queue_async, /* queue_async */ pipe_end_reselect_async /* reselect_async */ }; @@ -314,6 +316,7 @@ static const struct fd_ops named_pipe_device_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ named_pipe_device_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ default_fd_reselect_async /* reselect_async */ }; diff --git a/server/serial.c b/server/serial.c index a5f7ef917b9..bdc27de8e4f 100644 --- a/server/serial.c +++ b/server/serial.c @@ -119,6 +119,7 @@ static const struct fd_ops serial_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ serial_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ serial_queue_async, /* queue_async */ serial_reselect_async /* reselect_async */ }; diff --git a/server/sock.c b/server/sock.c index 3c5f2612b51..bfaf6329ff4 100644 --- a/server/sock.c +++ b/server/sock.c @@ -274,6 +274,7 @@ static const struct fd_ops sock_fd_ops = default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ sock_ioctl, /* ioctl */ + default_fd_cancel_async, /* cancel_async */ sock_queue_async, /* queue_async */ sock_reselect_async /* reselect_async */ }; @@ -2973,6 +2974,7 @@ static const struct fd_ops ifchange_fd_ops = no_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ no_fd_ioctl, /* ioctl */ + NULL, /* cancel_async */ NULL, /* queue_async */ NULL /* reselect_async */ };
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 22 ---------------------- server/async.c | 9 ++++++++- server/device.c | 23 ++++++++++------------- 3 files changed, 18 insertions(+), 36 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 5c3a42c3d76..f7a9d8e8efe 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -419,17 +419,6 @@ static void *create_file_object( HANDLE handle )
DECLARE_CRITICAL_SECTION(irp_completion_cs);
-static void WINAPI cancel_completed_irp( DEVICE_OBJECT *device, IRP *irp ) -{ - TRACE( "(%p %p)\n", device, irp ); - - IoReleaseCancelSpinLock(irp->CancelIrql); - - irp->IoStatus.u.Status = STATUS_CANCELLED; - irp->IoStatus.Information = 0; - IoCompleteRequest(irp, IO_NO_INCREMENT); -} - /* transfer result of IRP back to wineserver */ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context ) { @@ -455,17 +444,6 @@ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, } SERVER_END_REQ;
- if (status == STATUS_MORE_PROCESSING_REQUIRED) - { - /* IRP is complete, but server may have already ordered cancel call. In such case, - * it will return STATUS_MORE_PROCESSING_REQUIRED, leaving the IRP alive until - * cancel frees it. */ - if (irp->Cancel) - status = STATUS_SUCCESS; - else - IoSetCancelRoutine( irp, cancel_completed_irp ); - } - if (irp->UserBuffer != irp->AssociatedIrp.SystemBuffer) { HeapFree( GetProcessHeap(), 0, irp->UserBuffer ); diff --git a/server/async.c b/server/async.c index 278048bc7a3..fad4fe13a9a 100644 --- a/server/async.c +++ b/server/async.c @@ -53,6 +53,7 @@ struct async unsigned int direct_result :1;/* a flag if we're passing result directly from request instead of APC */ unsigned int alerted :1; /* fd is signaled, but we are waiting for client-side I/O */ unsigned int terminated :1; /* async has been terminated */ + unsigned int cancelled :1; /* have we already queued cancellation for this async? */ unsigned int unknown_status :1; /* initial status is not known yet */ struct completion *completion; /* completion associated with fd */ apc_param_t comp_key; /* completion key associated with fd */ @@ -259,6 +260,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->direct_result = 0; async->alerted = 0; async->terminated = 0; + async->cancelled = 0; async->unknown_status = 0; async->completion = fd_get_completion( fd, &async->comp_key ); async->comp_flags = 0; @@ -494,14 +496,19 @@ static int cancel_async( struct process *process, struct object *obj, struct thr struct async *async; int woken = 0;
+ /* FIXME: it would probably be nice to replace the "cancelled" flag with a + * single LIST_FOR_EACH_ENTRY_SAFE, but currently cancelling an async can + * cause other asyncs to be removed via async_reselect() */ + restart: LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry ) { - if (async->terminated) continue; + if (async->terminated || async->cancelled) continue; if ((!obj || (get_fd_user( async->fd ) == obj)) && (!thread || async->thread == thread) && (!iosb || async->data.iosb == iosb)) { + async->cancelled = 1; fd_cancel_async( async->fd, async ); woken++; goto restart; diff --git a/server/device.c b/server/device.c index 2310de43ac4..9515d238fb4 100644 --- a/server/device.c +++ b/server/device.c @@ -205,7 +205,7 @@ static void device_file_read( struct fd *fd, struct async *async, file_pos_t pos static void device_file_write( struct fd *fd, struct async *async, file_pos_t pos ); static void device_file_flush( struct fd *fd, struct async *async ); static void device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ); -static void device_file_reselect_async( struct fd *fd, struct async_queue *queue ); +static void device_file_cancel_async( struct fd *fd, struct async *async ); static void device_file_get_volume_info( struct fd *fd, struct async *async, unsigned int info_class );
static const struct object_ops device_file_ops = @@ -243,9 +243,9 @@ static const struct fd_ops device_file_fd_ops = default_fd_get_file_info, /* get_file_info */ device_file_get_volume_info, /* get_volume_info */ device_file_ioctl, /* ioctl */ - default_fd_cancel_async, /* cancel_async */ + device_file_cancel_async, /* cancel_async */ default_fd_queue_async, /* queue_async */ - device_file_reselect_async /* reselect_async */ + default_fd_reselect_async, /* reselect_async */ };
@@ -687,21 +687,21 @@ static void cancel_irp_call( struct irp_call *irp ) add_irp_to_queue( irp->file->device->manager, cancel_irp, NULL ); release_object( cancel_irp ); } - - set_irp_result( irp, STATUS_CANCELLED, NULL, 0, 0 ); }
-static void device_file_reselect_async( struct fd *fd, struct async_queue *queue ) +static void device_file_cancel_async( struct fd *fd, struct async *async ) { struct device_file *file = get_fd_user( fd ); struct irp_call *irp;
LIST_FOR_EACH_ENTRY( irp, &file->requests, struct irp_call, dev_entry ) - if (irp->iosb->status != STATUS_PENDING) + { + if (irp->async == async) { cancel_irp_call( irp ); return; } + } }
static struct device *create_device( struct object *root, const struct unicode_str *name, @@ -1018,12 +1018,9 @@ DECL_HANDLER(set_irp_result)
if ((irp = (struct irp_call *)get_handle_obj( current->process, req->handle, 0, &irp_call_ops ))) { - if (!irp->canceled) - set_irp_result( irp, req->status, get_req_data(), get_req_data_size(), req->size ); - else if(irp->user_ptr) /* cancel already queued */ - set_error( STATUS_MORE_PROCESSING_REQUIRED ); - else /* we may be still dispatching the IRP. don't bother queuing cancel if it's already complete */ - irp->canceled = 0; + set_irp_result( irp, req->status, get_req_data(), get_req_data_size(), req->size ); + /* we may be still dispatching the IRP. don't bother queuing cancel if it's already complete */ + irp->canceled = 0; close_handle( current->process, req->handle ); /* avoid an extra round-trip for close */ release_object( irp ); }
Zebediah Figura zfigura@codeweavers.com writes:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
dlls/ntoskrnl.exe/ntoskrnl.c | 22 ---------------------- server/async.c | 9 ++++++++- server/device.c | 23 ++++++++++------------- 3 files changed, 18 insertions(+), 36 deletions(-)
This breaks the tests:
tools/runtest -q -P wine -T . -M httpapi.dll -p dlls/httpapi/tests/httpapi_test.exe httpapi && touch dlls/httpapi/tests/httpapi.ok httpapi.c:355: Test failed: Got error 996. httpapi.c:356: Test failed: Got size 3735928559. make: *** [Makefile:62335: dlls/httpapi/tests/httpapi.ok] Error 2
On 9/7/21 2:38 PM, Alexandre Julliard wrote:
Zebediah Figura zfigura@codeweavers.com writes:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
dlls/ntoskrnl.exe/ntoskrnl.c | 22 ---------------------- server/async.c | 9 ++++++++- server/device.c | 23 ++++++++++------------- 3 files changed, 18 insertions(+), 36 deletions(-)
This breaks the tests:
tools/runtest -q -P wine -T . -M httpapi.dll -p dlls/httpapi/tests/httpapi_test.exe httpapi && touch dlls/httpapi/tests/httpapi.ok httpapi.c:355: Test failed: Got error 996. httpapi.c:356: Test failed: Got size 3735928559. make: *** [Makefile:62335: dlls/httpapi/tests/httpapi.ok] Error 2
The attached patch should fix it. The rest of the series should remain unchanged.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver.c | 59 +++++++++++++++++++++++++----- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 44 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 10 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 0d40053b0e6..8cb97507ab5 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1959,15 +1959,12 @@ static void test_object_name(void) ok(!name->Name.MaximumLength, "got maximum length %u\n", name->Name.MaximumLength); }
-static PIO_WORKITEM main_test_work_item; +static PIO_WORKITEM work_item;
static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) { IRP *irp = context;
- IoFreeWorkItem(main_test_work_item); - main_test_work_item = NULL; - test_current_thread(TRUE); test_critical_region(FALSE); test_call_driver(device); @@ -2337,13 +2334,8 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_process_memory(test_input); test_permanence();
- if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR; - - main_test_work_item = IoAllocateWorkItem(lower_device); - ok(main_test_work_item != NULL, "main_test_work_item = NULL\n"); - IoMarkIrpPending(irp); - IoQueueWorkItem(main_test_work_item, main_test_task, DelayedWorkQueue, irp); + IoQueueWorkItem(work_item, main_test_task, DelayedWorkQueue, irp);
return STATUS_PENDING; } @@ -2611,6 +2603,32 @@ static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp) return STATUS_PENDING; }
+static void WINAPI blocking_irp_task(DEVICE_OBJECT *device, void *context) +{ + LARGE_INTEGER timeout; + IRP *irp = context; + + timeout.QuadPart = -100 * 10000; + KeDelayExecutionThread( KernelMode, FALSE, &timeout ); + + irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.Information = 0; + IoCompleteRequest(irp, IO_NO_INCREMENT); +} + +static void WINAPI blocking_irp_failure_task(DEVICE_OBJECT *device, void *context) +{ + LARGE_INTEGER timeout; + IRP *irp = context; + + timeout.QuadPart = -100 * 10000; + KeDelayExecutionThread( KernelMode, FALSE, &timeout ); + + irp->IoStatus.Status = STATUS_DEVICE_NOT_READY; + irp->IoStatus.Information = 0; + IoCompleteRequest(irp, IO_NO_INCREMENT); +} + static BOOL compare_file_name(const struct file_context *context, const WCHAR *expect) { return context->namelen == wcslen(expect) * sizeof(WCHAR) @@ -2717,6 +2735,21 @@ static NTSTATUS WINAPI driver_QueryVolumeInformation(DEVICE_OBJECT *device, IRP ret = STATUS_SUCCESS; break; } + + case FileFsSizeInformation: + { + IoMarkIrpPending(irp); + IoQueueWorkItem(work_item, blocking_irp_task, DelayedWorkQueue, irp); + return STATUS_PENDING; + } + + case FileFsFullSizeInformation: + { + IoMarkIrpPending(irp); + IoQueueWorkItem(work_item, blocking_irp_failure_task, DelayedWorkQueue, irp); + return STATUS_PENDING; + } + default: ret = STATUS_NOT_IMPLEMENTED; break; @@ -2744,6 +2777,9 @@ static VOID WINAPI driver_Unload(DRIVER_OBJECT *driver)
DbgPrint("unloading driver\n");
+ IoFreeWorkItem(work_item); + work_item = NULL; + RtlInitUnicodeString(&linkW, L"\DosDevices\WineTestDriver"); IoDeleteSymbolicLink(&linkW);
@@ -2802,5 +2838,8 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) IoAttachDeviceToDeviceStack(upper_device, lower_device); upper_device->Flags &= ~DO_DEVICE_INITIALIZING;
+ work_item = IoAllocateWorkItem(lower_device); + ok(work_item != NULL, "work_item = NULL\n"); + return STATUS_SUCCESS; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index b85c0078620..4f8dd6585a4 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1139,6 +1139,49 @@ static void test_object_info(void) CloseHandle(file); }
+static void test_blocking_irp(void) +{ + char buffer[40]; + IO_STATUS_BLOCK io; + NTSTATUS status; + HANDLE file; + + file = CreateFileA("\\.\WineTestDriver\", FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + memset(&io, 0xcc, sizeof(io)); + status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsSizeInformation); + ok(!status, "got %#x\n", status); + ok(!io.Status, "got iosb status %#x\n", io.Status); + ok(!io.Information, "got information %#Ix\n", io.Information); + + io.Status = 0xdeadf00d; + io.Information = 0xdeadf00d; + status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsFullSizeInformation); + ok(status == STATUS_DEVICE_NOT_READY, "got %#x\n", status); + todo_wine ok(io.Status == 0xdeadf00d, "got iosb status %#x\n", io.Status); + todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + + CloseHandle(file); + + file = CreateFileA("\\.\WineTestDriver\", FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + ok(file != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + memset(&io, 0xcc, sizeof(io)); + status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsSizeInformation); + todo_wine ok(!status, "got %#x\n", status); + todo_wine ok(!io.Status, "got iosb status %#x\n", io.Status); + todo_wine ok(!io.Information, "got information %#Ix\n", io.Information); + + memset(&io, 0xcc, sizeof(io)); + status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsFullSizeInformation); + todo_wine ok(status == STATUS_DEVICE_NOT_READY, "got %#x\n", status); + todo_wine ok(io.Status == STATUS_DEVICE_NOT_READY, "got iosb status %#x\n", io.Status); + todo_wine ok(!io.Information, "got information %#Ix\n", io.Information); + + CloseHandle(file); +} + static void test_driver3(struct testsign_context *ctx) { WCHAR filename[MAX_PATH]; @@ -3487,6 +3530,7 @@ START_TEST(ntoskrnl) test_file_handles(); test_return_status(); test_object_info(); + test_blocking_irp();
/* We need a separate ioctl to call IoDetachDevice(); calling it in the * driver unload routine causes a live-lock. */
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=97326
Your paranoid android.
=== debiant2 (64 bit WoW report) ===
ntoskrnl.exe: Unhandled exception: page fault on execute access to 0x00000000 in 64-bit code (0x0000000000000000).
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/async.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/server/async.c b/server/async.c index fad4fe13a9a..6aba392fd84 100644 --- a/server/async.c +++ b/server/async.c @@ -55,6 +55,7 @@ struct async unsigned int terminated :1; /* async has been terminated */ unsigned int cancelled :1; /* have we already queued cancellation for this async? */ unsigned int unknown_status :1; /* initial status is not known yet */ + unsigned int blocking :1; /* async is blocking */ struct completion *completion; /* completion associated with fd */ apc_param_t comp_key; /* completion key associated with fd */ unsigned int comp_flags; /* completion flags */ @@ -262,6 +263,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da async->terminated = 0; async->cancelled = 0; async->unknown_status = 0; + async->blocking = !is_fd_overlapped( fd ); async->completion = fd_get_completion( fd, &async->comp_key ); async->comp_flags = 0; async->completion_callback = NULL; @@ -300,6 +302,8 @@ void set_async_pending( struct async *async, int signal ) /* return async object status and wait handle to client */ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_blocking ) { + async->blocking = force_blocking || async->blocking; + if (async->unknown_status) { /* even the initial status is not known yet */ @@ -338,7 +342,7 @@ obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_ { async->direct_result = 0; async->pending = 1; - if (!force_blocking && async->fd && is_fd_overlapped( async->fd )) + if (!async->blocking) { close_handle( async->thread->process, async->wait_handle); async->wait_handle = 0;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 12 ++++++------ server/async.c | 4 ++-- server/device.c | 2 +- server/file.h | 2 +- server/sock.c | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 4f8dd6585a4..de09abb04ba 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1169,15 +1169,15 @@ static void test_blocking_irp(void)
memset(&io, 0xcc, sizeof(io)); status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsSizeInformation); - todo_wine ok(!status, "got %#x\n", status); - todo_wine ok(!io.Status, "got iosb status %#x\n", io.Status); - todo_wine ok(!io.Information, "got information %#Ix\n", io.Information); + ok(!status, "got %#x\n", status); + ok(!io.Status, "got iosb status %#x\n", io.Status); + ok(!io.Information, "got information %#Ix\n", io.Information);
memset(&io, 0xcc, sizeof(io)); status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsFullSizeInformation); - todo_wine ok(status == STATUS_DEVICE_NOT_READY, "got %#x\n", status); - todo_wine ok(io.Status == STATUS_DEVICE_NOT_READY, "got iosb status %#x\n", io.Status); - todo_wine ok(!io.Information, "got information %#Ix\n", io.Information); + ok(status == STATUS_DEVICE_NOT_READY, "got %#x\n", status); + ok(io.Status == STATUS_DEVICE_NOT_READY, "got iosb status %#x\n", io.Status); + ok(!io.Information, "got information %#Ix\n", io.Information);
CloseHandle(file); } diff --git a/server/async.c b/server/async.c index 6aba392fd84..4822b0735c6 100644 --- a/server/async.c +++ b/server/async.c @@ -285,13 +285,13 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da return async; }
-void set_async_pending( struct async *async, int signal ) +void set_async_pending( struct async *async ) { if (!async->terminated) { async->pending = 1; async->unknown_status = 0; - if (signal && !async->signaled) + if (!async->blocking && !async->signaled) { async->signaled = 1; wake_up( &async->obj, 0 ); diff --git a/server/device.c b/server/device.c index 9515d238fb4..a2383ecdc7c 100644 --- a/server/device.c +++ b/server/device.c @@ -961,7 +961,7 @@ DECL_HANDLER(get_next_device_request) * so we need to do it now */ cancel_irp_call( irp ); else if (irp->async) - set_async_pending( irp->async, irp->file && is_fd_overlapped( irp->file->fd ) ); + set_async_pending( irp->async );
free_irp_params( irp ); release_object( irp ); diff --git a/server/file.h b/server/file.h index 22879b75c05..80f2191c050 100644 --- a/server/file.h +++ b/server/file.h @@ -229,7 +229,7 @@ extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned extern void async_set_result( struct object *obj, unsigned int status, apc_param_t total ); extern void async_set_completion_callback( struct async *async, async_completion_callback func, void *private ); extern void async_set_unknown_status( struct async *async ); -extern void set_async_pending( struct async *async, int signal ); +extern void set_async_pending( struct async *async ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern void async_request_complete( struct async *async, unsigned int status, data_size_t result, diff --git a/server/sock.c b/server/sock.c index bfaf6329ff4..d61ed5b95b2 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2399,7 +2399,7 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) obj_handle_t event_handle; int mask;
- set_async_pending( async, 0 ); + set_async_pending( async );
if (is_machine_64bit( current->process->machine )) { @@ -2530,7 +2530,7 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) #endif }
- set_async_pending( async, 0 ); + set_async_pending( async );
if (bind( unix_fd, &bind_addr.addr, unix_len ) < 0) {