[PATCH] ntoskrnl.exe: Create the device interface symlink in IoSetDeviceInterfaceState().
Aric Stewart
aric at codeweavers.com
Tue Nov 20 09:54:17 CST 2018
Signed-off-by: Aric Stewart <aric at codeweavers.com>
On 11/20/18 9:47 AM, Zebediah Figura wrote:
> From: Aric Stewart <aric at codeweavers.com>
>
> Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
> ---
> dlls/ntoskrnl.exe/ntoskrnl.c | 110 +++++++++++++++++++++++++++++++++++++------
> 1 file changed, 96 insertions(+), 14 deletions(-)
>
> diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
> index e52cb168a8..aec37daa59 100644
> --- a/dlls/ntoskrnl.exe/ntoskrnl.c
> +++ b/dlls/ntoskrnl.exe/ntoskrnl.c
> @@ -102,6 +102,16 @@ struct wine_driver
> SERVICE_STATUS_HANDLE service_handle;
> };
>
> +struct device_interface
> +{
> + struct wine_rb_entry entry;
> +
> + UNICODE_STRING symbolic_link;
> + DEVICE_OBJECT *device;
> + GUID interface_class;
> + BOOL enabled;
> +};
> +
> static NTSTATUS get_device_id( DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCHAR **id );
>
> static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
> @@ -114,6 +124,16 @@ static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry
>
> static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
>
> +static int interface_rb_compare( const void *key, const struct wine_rb_entry *entry)
> +{
> + const struct device_interface *iface = WINE_RB_ENTRY_VALUE( entry, const struct device_interface, entry );
> + const UNICODE_STRING *k = key;
> +
> + return RtlCompareUnicodeString( k, &iface->symbolic_link, FALSE );
> +}
> +
> +static struct wine_rb_tree device_interfaces = { interface_rb_compare };
> +
> static CRITICAL_SECTION drivers_cs;
> static CRITICAL_SECTION_DEBUG critsect_debug =
> {
> @@ -1321,6 +1341,30 @@ NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
> return status;
> }
>
> +static NTSTATUS create_device_symlink( DEVICE_OBJECT *device, UNICODE_STRING *symlink_name )
> +{
> + UNICODE_STRING device_nameU;
> + WCHAR *device_name;
> + ULONG len = 0;
> + NTSTATUS ret;
> +
> + ret = IoGetDeviceProperty( device, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &len );
> + if (ret != STATUS_BUFFER_TOO_SMALL)
> + return ret;
> +
> + device_name = heap_alloc( len );
> + ret = IoGetDeviceProperty( device, DevicePropertyPhysicalDeviceObjectName, len, device_name, &len );
> + if (ret)
> + {
> + heap_free( device_name );
> + return ret;
> + }
> +
> + RtlInitUnicodeString( &device_nameU, device_name );
> + ret = IoCreateSymbolicLink( symlink_name, &device_nameU );
> + heap_free( device_name );
> + return ret;
> +}
>
> /***********************************************************************
> * IoSetDeviceInterfaceState (NTOSKRNL.EXE.@)
> @@ -1339,16 +1383,31 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
>
> size_t namelen = name->Length / sizeof(WCHAR);
> DEV_BROADCAST_DEVICEINTERFACE_W *broadcast;
> + struct device_interface *iface;
> HANDLE iface_key, control_key;
> OBJECT_ATTRIBUTES attr = {0};
> + struct wine_rb_entry *entry;
> WCHAR *path, *refstr, *p;
> UNICODE_STRING string;
> + DWORD data = enable;
> NTSTATUS ret;
> - size_t len;
> GUID class;
> + ULONG len;
>
> TRACE("(%s, %d)\n", debugstr_us(name), enable);
>
> + entry = wine_rb_get( &device_interfaces, name );
> + if (!entry)
> + return STATUS_OBJECT_NAME_NOT_FOUND;
> +
> + iface = WINE_RB_ENTRY_VALUE( entry, struct device_interface, entry );
> +
> + if (!enable && !iface->enabled)
> + return STATUS_OBJECT_NAME_NOT_FOUND;
> +
> + if (enable && iface->enabled)
> + return STATUS_OBJECT_NAME_EXISTS;
> +
> refstr = memrchrW(name->Buffer + 4, '\\', namelen - 4);
>
> if (!guid_from_string( (refstr ? refstr : name->Buffer + namelen) - 38, &class ))
> @@ -1374,22 +1433,37 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
> attr.ObjectName = &string;
> RtlInitUnicodeString( &string, path );
> ret = NtOpenKey( &iface_key, KEY_CREATE_SUB_KEY, &attr );
> - if (!ret)
> + heap_free(path);
> + if (ret)
> + return ret;
> +
> + attr.RootDirectory = iface_key;
> + RtlInitUnicodeString( &string, controlW );
> + ret = NtCreateKey( &control_key, KEY_SET_VALUE, &attr, 0, NULL, 0, NULL );
> + NtClose( iface_key );
> + if (ret)
> + return ret;
> +
> + RtlInitUnicodeString( &string, linkedW );
> + ret = NtSetValueKey( control_key, &string, 0, REG_DWORD, &data, sizeof(data) );
> + if (ret)
> {
> - attr.RootDirectory = iface_key;
> - RtlInitUnicodeString( &string, controlW );
> - ret = NtCreateKey( &control_key, KEY_SET_VALUE, &attr, 0, NULL, 0, NULL );
> - if (!ret)
> - {
> - DWORD data = enable;
> - RtlInitUnicodeString( &string, linkedW );
> - ret = NtSetValueKey( control_key, &string, 0, REG_DWORD, &data, sizeof(data) );
> - NtClose( control_key );
> - }
> - NtClose( iface_key );
> + NtClose( control_key );
> + return ret;
> }
>
> - heap_free( path );
> + if (enable)
> + ret = create_device_symlink( iface->device, name );
> + else
> + ret = IoDeleteSymbolicLink( name );
> + if (ret)
> + {
> + NtDeleteValueKey( control_key, &string );
> + NtClose( control_key );
> + return ret;
> + }
> +
> + iface->enabled = enable;
>
> len = offsetof(DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name[namelen + 1]);
>
> @@ -1696,6 +1770,7 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla
> SP_DEVICE_INTERFACE_DETAIL_DATA_W *data;
> DWORD required;
> BOOL rc;
> + struct device_interface *iface;
>
> TRACE( "(%p, %s, %s, %p)\n", device, debugstr_guid(class_guid), debugstr_us(reference_string), symbolic_link );
>
> @@ -1766,9 +1841,16 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla
> data->DevicePath[1] = '?';
> TRACE( "Device path %s\n",debugstr_w(data->DevicePath) );
>
> + iface = heap_alloc_zero( sizeof(struct device_interface) );
> + iface->device = device;
> + iface->interface_class = *class_guid;
> + RtlCreateUnicodeString(&iface->symbolic_link, data->DevicePath);
> if (symbolic_link)
> RtlCreateUnicodeString( symbolic_link, data->DevicePath);
>
> + if (wine_rb_put( &device_interfaces, &iface->symbolic_link, &iface->entry ))
> + ERR( "failed to insert interface %s into tree\n", debugstr_us(&iface->symbolic_link) );
> +
> HeapFree( GetProcessHeap(), 0, data );
>
> return status;
>
More information about the wine-devel
mailing list