[Wine-patches] [14/23] ntoskrnl.exe: Partially implement IoInvalidateDeviceRelations.
Alexander Morozov
=?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Пн Янв 19 18:24:40 MSK 2009
For eterhack branch
----------- следующая часть -----------
From ca463407bb8937f939b2215aab1ad67b733b43a0 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Thu, 15 Jan 2009 12:32:17 +0300
Subject: [PATCH] ntoskrnl.exe: Partially implement IoInvalidateDeviceRelations.
---
dlls/ntoskrnl.exe/Makefile.in | 2 +-
dlls/ntoskrnl.exe/ntoskrnl.c | 191 ++++++++++++++++++++++++++++++++++-
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +
include/ddk/wdm.h | 5 +
4 files changed, 196 insertions(+), 4 deletions(-)
diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in
index 1cd60dc..d6d8540 100644
--- a/dlls/ntoskrnl.exe/Makefile.in
+++ b/dlls/ntoskrnl.exe/Makefile.in
@@ -4,7 +4,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = ntoskrnl.exe
IMPORTLIB = ntoskrnl.exe
-IMPORTS = kernel32 ntdll setupapi
+IMPORTS = kernel32 ntdll setupapi advapi32
C_SRCS = \
ntoskrnl.c
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 3b27024..094f0f3 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -32,6 +32,7 @@
#include "winternl.h"
#include "winioctl.h"
#include "winbase.h"
+#include "winsvc.h"
#include "winuser.h"
#include "winreg.h"
#include "setupapi.h"
@@ -134,12 +135,90 @@ struct InterfaceInstance
"jmp " __ASM_NAME("__regs_") #name )
#endif
+NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp );
+
static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
{
if (!us) return "<null>";
return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) );
}
+static BOOL start_service( WCHAR *name )
+{
+ SC_HANDLE scm, service;
+ BOOL ret;
+
+ scm = OpenSCManagerA( NULL, NULL, SC_MANAGER_ALL_ACCESS );
+ if (scm == NULL)
+ return FALSE;
+
+ service = OpenServiceW( scm, name, SERVICE_ALL_ACCESS );
+ if (service == NULL)
+ {
+ CloseServiceHandle( scm );
+ return FALSE;
+ }
+
+ ret = StartServiceW( service, 0, NULL );
+ if (!ret && ERROR_SERVICE_ALREADY_RUNNING == GetLastError())
+ ret = TRUE;
+
+ CloseServiceHandle( service );
+ CloseServiceHandle( scm );
+
+ return ret;
+}
+
+/* get name of driver service for device with given id */
+static BOOL get_service( WCHAR *device_id, WCHAR **service_name )
+{
+ SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } };
+ HDEVINFO set;
+ WCHAR *ptr, *enum_name, *id = NULL;
+ DWORD size, i = 0;
+ BOOL ret;
+
+ *service_name = NULL;
+ ptr = strchrW( device_id, '\\' );
+ if (!ptr) return FALSE;
+ size = ptr - device_id + 1;
+ enum_name = RtlAllocateHeap( GetProcessHeap(), 0, size * sizeof(WCHAR) );
+ if (!enum_name) return FALSE;
+ lstrcpynW( enum_name, device_id, size );
+
+ set = SetupDiGetClassDevsW( NULL, enum_name, 0, DIGCF_ALLCLASSES );
+ if (set == INVALID_HANDLE_VALUE) goto end;
+ while (SetupDiEnumDeviceInfo( set, i++, &devInfo ))
+ {
+ SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_HARDWAREID,
+ NULL, NULL, 0, &size );
+ if (id) RtlFreeHeap( GetProcessHeap(), 0, id );
+ id = RtlAllocateHeap( GetProcessHeap(), 0, size );
+ if (!id) break;
+ ret = SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_HARDWAREID,
+ NULL, (BYTE *)id, size, NULL );
+ if (!ret) break;
+ if (strcmpiW( device_id, id )) continue;
+ SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_SERVICE,
+ NULL, NULL, 0, &size );
+ *service_name = RtlAllocateHeap( GetProcessHeap(), 0, size );
+ if (!*service_name) break;
+ ret = SetupDiGetDeviceRegistryPropertyW( set, &devInfo, SPDRP_SERVICE,
+ NULL, (BYTE *)*service_name, size, NULL );
+ if (!ret)
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, *service_name );
+ *service_name = NULL;
+ break;
+ }
+ }
+ SetupDiDestroyDeviceInfoList( set );
+end:
+ if (id) RtlFreeHeap( GetProcessHeap(), 0, id );
+ if (enum_name) RtlFreeHeap( GetProcessHeap(), 0, enum_name );
+ return (*service_name != NULL);
+}
+
static HANDLE get_device_manager(void)
{
static HANDLE device_manager;
@@ -226,8 +305,6 @@ static void save_pid( DWORD pid )
LeaveCriticalSection( &cs );
}
-NTSTATUS WINAPI __regs_IofCallDriver( DEVICE_OBJECT *device, IRP *irp );
-
/* process an ioctl request for a given device */
static NTSTATUS process_ioctl( DEVICE_OBJECT *device, ULONG code, void *in_buff, ULONG in_size,
void *out_buff, ULONG *out_size )
@@ -426,6 +503,57 @@ DRIVER_OBJECT * CDECL __wine_get_driver_object( const WCHAR *service )
/***********************************************************************
+ * __wine_add_device (Not a Windows API)
+ */
+NTSTATUS CDECL __wine_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *dev )
+{
+ NTSTATUS status;
+ NTSTATUS (WINAPI *AddDevice)( PDRIVER_OBJECT, PDEVICE_OBJECT ) =
+ driver->DriverExtension->AddDevice;
+
+ if (TRACE_ON(relay))
+ DPRINTF( "%04x:Call AddDevice %p (%p,%p)\n",
+ GetCurrentThreadId(), AddDevice, driver, dev );
+
+ status = AddDevice( driver, dev );
+
+ if (TRACE_ON(relay))
+ DPRINTF( "%04x:Ret AddDevice %p (%p,%p) retval=%08x\n",
+ GetCurrentThreadId(), AddDevice, driver, dev, status );
+
+ return status;
+}
+
+
+/***********************************************************************
+ * __wine_start_device (Not a Windows API)
+ */
+NTSTATUS CDECL __wine_start_device( DRIVER_OBJECT *driver )
+{
+ DEVICE_OBJECT *device = driver->DeviceObject;
+ IO_STACK_LOCATION *irpsp;
+ PIRP irp;
+ NTSTATUS status;
+
+ if (driver->MajorFunction[IRP_MJ_PNP] == NULL)
+ return STATUS_NOT_SUPPORTED;
+ irp = IoAllocateIrp( device->StackSize, FALSE );
+ if (irp == NULL) return STATUS_NO_MEMORY;
+
+ irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+ irp->RequestorMode = KernelMode;
+ irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED;
+ irpsp->MajorFunction = IRP_MJ_PNP;
+ irpsp->MinorFunction = IRP_MN_START_DEVICE;
+ irpsp->DeviceObject = device;
+ device->CurrentIrp = irp;
+ status = __regs_IofCallDriver( device, irp );
+ IoFreeIrp( irp );
+ return status;
+}
+
+
+/***********************************************************************
* ExAcquireFastMutexUnsafe (NTOSKRNL.EXE.@)
*/
#ifdef DEFINE_FASTCALL1_ENTRYPOINT
@@ -911,7 +1039,64 @@ NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *targ
void WINAPI IoInvalidateDeviceRelations( PDEVICE_OBJECT DeviceObject,
DEVICE_RELATION_TYPE Type )
{
- FIXME( "%p, %u\n", DeviceObject, Type );
+ TRACE( "%p, %u\n", DeviceObject, Type );
+
+ while (DeviceObject->AttachedDevice)
+ DeviceObject = DeviceObject->AttachedDevice;
+ if (Type == BusRelations)
+ {
+ DEVICE_RELATIONS *rel;
+ IO_STACK_LOCATION *irpsp;
+ IRP *irp;
+ NTSTATUS status;
+
+ irp = IoAllocateIrp( DeviceObject->StackSize, FALSE );
+ if (irp == NULL) return;
+ irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+ irpsp->MajorFunction = IRP_MJ_PNP;
+ irpsp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
+ irpsp->Parameters.QueryDeviceRelations.Type = BusRelations;
+ status = __regs_IofCallDriver( DeviceObject, irp );
+ rel = (DEVICE_RELATIONS *)irp->IoStatus.Information;
+ if (status == STATUS_SUCCESS && rel && rel->Count)
+ {
+ unsigned int k;
+
+ for (k = 0; k < rel->Count; ++k)
+ {
+ IoFreeIrp( irp );
+ irp = IoAllocateIrp( rel->Objects[k]->StackSize, FALSE );
+ if (irp == NULL) return;
+ irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation - 1;
+ irpsp->MajorFunction = IRP_MJ_PNP;
+ irpsp->MinorFunction = IRP_MN_QUERY_ID;
+ irpsp->Parameters.QueryId.IdType = BusQueryDeviceID;
+ status = __regs_IofCallDriver( rel->Objects[k], irp );
+ if (status == STATUS_SUCCESS)
+ {
+ WCHAR *service;
+
+ if (get_service( (WCHAR *)irp->IoStatus.Information, &service )
+ && start_service( service ))
+ {
+ DRIVER_OBJECT *driver;
+
+ while (!(driver = __wine_get_driver_object( service )))
+ Sleep( 100 );
+ status = __wine_add_device( driver, rel->Objects[k] );
+ if (status == STATUS_SUCCESS)
+ __wine_start_device( driver );
+ }
+ if (service) RtlFreeHeap( GetProcessHeap(), 0, service );
+ }
+ ExFreePool( (void *)irp->IoStatus.Information );
+ }
+ ExFreePool( rel );
+ }
+ IoFreeIrp( irp );
+ }
+ else
+ FIXME( "DEVICE_RELATION_TYPE %u not implemented\n", Type );
}
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 68ab9e2..d123928 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -1490,6 +1490,8 @@
@ cdecl wine_ntoskrnl_main_loop(long)
@ cdecl wine_complete_request(ptr long)
+@ cdecl __wine_add_device(ptr ptr)
@ cdecl __wine_add_driver_object(ptr wstr)
@ cdecl __wine_del_driver_object(ptr)
@ cdecl __wine_get_driver_object(wstr)
+@ cdecl __wine_start_device(ptr)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 923bffc..e5f07b5 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -1033,6 +1033,11 @@ typedef enum _LOCK_OPERATION {
IoModifyAccess
} LOCK_OPERATION;
+typedef struct _DEVICE_RELATIONS {
+ ULONG Count;
+ PDEVICE_OBJECT Objects[1];
+} DEVICE_RELATIONS, *PDEVICE_RELATIONS;
+
NTSTATUS WINAPI ObCloseHandle(IN HANDLE handle);
#define IoGetCurrentIrpStackLocation(_Irp) ((_Irp)->Tail.Overlay.CurrentStackLocation)
--
1.6.0.2.GIT
Подробная информация о списке рассылки Wine-patches