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 <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2021-07-06 10:11:47 +01:00 committed by Alexandre Julliard
parent 34a9d3e40f
commit 715edfb0b2

View file

@ -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: