From 715edfb0b2c42ae79a60300b87eca000c6e59cd2 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Tue, 6 Jul 2021 10:11:47 +0100 Subject: [PATCH] mountmgr.sys: Move dhcp lookup to a worker thread. While this is a reasonable change per se, the motivation is to avoid a deadlock when mountmgr.sys calls into iphlpapi and further into nsiproxy.sys via the nsi device. nsiproxy.sys is hosted by the same process as mountmgr.sys so is unable to handle the request while it is also waiting for that same request to return. The correct long-term solution is for mountmgr.sys to call the netio.sys versions of the iphlpapi functions. These will call the kernel-side versions of the nsi functions without going through the nsi device. Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/mountmgr.sys/mountmgr.c | 46 ++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/dlls/mountmgr.sys/mountmgr.c b/dlls/mountmgr.sys/mountmgr.c index 61d51d8e61d..b94944a350c 100644 --- a/dlls/mountmgr.sys/mountmgr.c +++ b/dlls/mountmgr.sys/mountmgr.c @@ -286,32 +286,48 @@ static NTSTATUS define_unix_drive( const void *in_buff, SIZE_T insize ) } /* implementation of IOCTL_MOUNTMGR_QUERY_DHCP_REQUEST_PARAMS */ -static NTSTATUS query_dhcp_request_params( void *buff, SIZE_T insize, - SIZE_T outsize, IO_STATUS_BLOCK *iosb ) +static void WINAPI query_dhcp_request_params( TP_CALLBACK_INSTANCE *instance, void *context ) { - struct mountmgr_dhcp_request_params *query = buff; - ULONG i, offset; + IRP *irp = context; + struct mountmgr_dhcp_request_params *query = irp->AssociatedIrp.SystemBuffer; + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + SIZE_T insize = irpsp->Parameters.DeviceIoControl.InputBufferLength; + SIZE_T outsize = irpsp->Parameters.DeviceIoControl.OutputBufferLength; + ULONG i, offset = 0; /* sanity checks */ if (FIELD_OFFSET(struct mountmgr_dhcp_request_params, params[query->count]) > insize || - !memchrW( query->adapter, 0, ARRAY_SIZE(query->adapter) )) return STATUS_INVALID_PARAMETER; + !memchrW( query->adapter, 0, ARRAY_SIZE(query->adapter) )) + { + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + goto err; + } + for (i = 0; i < query->count; i++) - if (query->params[i].offset + query->params[i].size > insize) return STATUS_INVALID_PARAMETER; + if (query->params[i].offset + query->params[i].size > insize) + { + irp->IoStatus.u.Status = STATUS_INVALID_PARAMETER; + goto err; + } + offset = FIELD_OFFSET(struct mountmgr_dhcp_request_params, params[query->count]); for (i = 0; i < query->count; i++) { - offset += get_dhcp_request_param( query->adapter, &query->params[i], buff, offset, outsize - offset ); + offset += get_dhcp_request_param( query->adapter, &query->params[i], (char *)query, offset, outsize - offset ); if (offset > outsize) { if (offset >= sizeof(query->size)) query->size = offset; - iosb->Information = sizeof(query->size); - return STATUS_MORE_ENTRIES; + offset = sizeof(query->size); + irp->IoStatus.u.Status = STATUS_MORE_ENTRIES; + goto err; } } + irp->IoStatus.u.Status = STATUS_SUCCESS; - iosb->Information = offset; - return STATUS_SUCCESS; +err: + irp->IoStatus.Information = offset; + IoCompleteRequest( irp, IO_NO_INCREMENT ); } /* implementation of Wine extension to use host APIs to find symbol file by GUID */ @@ -929,10 +945,10 @@ static NTSTATUS WINAPI mountmgr_ioctl( DEVICE_OBJECT *device, IRP *irp ) status = STATUS_INVALID_PARAMETER; break; } - status = query_dhcp_request_params( irp->AssociatedIrp.SystemBuffer, - irpsp->Parameters.DeviceIoControl.InputBufferLength, - irpsp->Parameters.DeviceIoControl.OutputBufferLength, - &irp->IoStatus ); + + if (TrySubmitThreadpoolCallback( query_dhcp_request_params, irp, NULL )) + return (irp->IoStatus.u.Status = STATUS_PENDING); + status = STATUS_NO_MEMORY; break; #ifdef __APPLE__ case IOCTL_MOUNTMGR_QUERY_SYMBOL_FILE: