[PATCH 4/8] ntoskrnl: Store root PnP devices per driver.
Zebediah Figura
z.figura12 at gmail.com
Wed Mar 31 11:16:34 CDT 2021
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/ntoskrnl.exe/ntoskrnl.c | 36 ++++++++-------------------
dlls/ntoskrnl.exe/ntoskrnl_private.h | 26 ++++++++++++++++++-
dlls/ntoskrnl.exe/pnp.c | 37 ++++++++++------------------
dlls/ntoskrnl.exe/sync.c | 13 +---------
4 files changed, 49 insertions(+), 63 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index b50886da137..f51055fd6c0 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -21,34 +21,20 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <stdarg.h>
#include <assert.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winsvc.h"
-#include "winternl.h"
+#include "ntoskrnl_private.h"
#include "excpt.h"
-#include "winioctl.h"
-#include "winbase.h"
#include "winreg.h"
#include "ntsecapi.h"
#include "ddk/csq.h"
-#include "ddk/ntddk.h"
-#include "ddk/ntifs.h"
-#include "ddk/wdm.h"
#include "wine/server.h"
-#include "wine/debug.h"
#include "wine/heap.h"
-#include "wine/rbtree.h"
#include "wine/svcctl.h"
-#include "ntoskrnl_private.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
WINE_DECLARE_DEBUG_CHANNEL(relay);
@@ -90,14 +76,6 @@ static void *ldr_notify_cookie;
static PLOAD_IMAGE_NOTIFY_ROUTINE load_image_notify_routines[8];
static unsigned int load_image_notify_routine_count;
-struct wine_driver
-{
- DRIVER_OBJECT driver_obj;
- DRIVER_EXTENSION driver_extension;
- SERVICE_STATUS_HANDLE service_handle;
- struct wine_rb_entry entry;
-};
-
static int wine_drivers_rb_compare( const void *key, const struct wine_rb_entry *entry )
{
const struct wine_driver *driver = WINE_RB_ENTRY_VALUE( entry, const struct wine_driver, entry );
@@ -962,6 +940,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop(void)
struct dispatch_context context;
NTSTATUS status = STATUS_SUCCESS;
WCHAR driver_dir[MAX_PATH];
+ struct wine_driver *driver;
SC_HANDLE manager_handle;
HANDLE handles[2];
@@ -1065,9 +1044,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop(void)
done:
/* Native PnP drivers expect that all of their devices will be removed when
- * their unload routine is called, so we must stop the PnP manager first. */
- pnp_manager_stop();
+ * their unload routine is called. Moreover, we cannot unload a module
+ * until we have removed devices for all lower drivers, so we have to stop
+ * all devices first, and then unload all drivers. */
+ WINE_RB_FOR_EACH_ENTRY( driver, &wine_drivers, struct wine_driver, entry )
+ pnp_manager_stop_driver( driver );
wine_rb_destroy( &wine_drivers, unload_driver, NULL );
+ pnp_manager_stop();
set_service_status( group_handle, SERVICE_STOPPED, 0 );
CloseServiceHandle( manager_handle );
@@ -1573,6 +1556,7 @@ NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
build_driver_keypath( driver->driver_obj.DriverName.Buffer, &driver->driver_extension.ServiceKeyName );
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
driver->driver_obj.MajorFunction[i] = unhandled_irp;
+ list_init( &driver->root_pnp_devices );
EnterCriticalSection( &drivers_cs );
if (wine_rb_put( &wine_drivers, &driver->driver_obj.DriverName, &driver->entry ))
@@ -3909,7 +3893,7 @@ NTSTATUS WINAPI ZwLoadDriver( const UNICODE_STRING *service_name )
driver = WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
driver->service_handle = service_handle;
- pnp_manager_enumerate_root_devices( service_name->Buffer + wcslen( servicesW ) );
+ pnp_manager_enumerate_root_devices( driver );
set_service_status( service_handle, SERVICE_RUNNING,
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN );
diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h
index a1e1b892e8c..3a6b2144004 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl_private.h
+++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h
@@ -21,7 +21,21 @@
#ifndef __WINE_NTOSKRNL_PRIVATE_H
#define __WINE_NTOSKRNL_PRIVATE_H
+#include <stdarg.h>
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winioctl.h"
+#include "winbase.h"
+#include "winsvc.h"
+#include "winternl.h"
+#include "ddk/ntifs.h"
+#include "ddk/wdm.h"
+
#include "wine/asm.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "wine/rbtree.h"
static inline LPCSTR debugstr_us( const UNICODE_STRING *us )
{
@@ -76,10 +90,20 @@ extern POBJECT_TYPE SeTokenObjectType;
0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 };
+struct wine_driver
+{
+ DRIVER_OBJECT driver_obj;
+ DRIVER_EXTENSION driver_extension;
+ SERVICE_STATUS_HANDLE service_handle;
+ struct wine_rb_entry entry;
+ struct list root_pnp_devices;
+};
+
void ObReferenceObject( void *obj ) DECLSPEC_HIDDEN;
-void pnp_manager_enumerate_root_devices( const WCHAR *driver_name ) DECLSPEC_HIDDEN;
+void pnp_manager_enumerate_root_devices( struct wine_driver *driver ) DECLSPEC_HIDDEN;
void pnp_manager_start(void) DECLSPEC_HIDDEN;
+void pnp_manager_stop_driver( struct wine_driver *driver ) DECLSPEC_HIDDEN;
void pnp_manager_stop(void) DECLSPEC_HIDDEN;
static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
index 913a63e8f0d..1c1f241591b 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -20,31 +20,17 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <stdarg.h>
-
#define NONAMELESSUNION
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "winioctl.h"
+#include "ntoskrnl_private.h"
#include "winreg.h"
#include "winuser.h"
-#include "winsvc.h"
-#include "winternl.h"
#include "setupapi.h"
#include "cfgmgr32.h"
#include "dbt.h"
-#include "ddk/wdm.h"
-#include "ddk/ntifs.h"
-#include "wine/debug.h"
#include "wine/exception.h"
#include "wine/heap.h"
-#include "wine/rbtree.h"
-#include "wine/list.h"
-#include "ntoskrnl_private.h"
#include "plugplay.h"
#include "initguid.h"
@@ -928,13 +914,11 @@ struct root_pnp_device
DEVICE_OBJECT *device;
};
-static struct list root_pnp_devices = LIST_INIT(root_pnp_devices);
-
-static struct root_pnp_device *find_root_pnp_device( const WCHAR *id )
+static struct root_pnp_device *find_root_pnp_device( struct wine_driver *driver, const WCHAR *id )
{
struct root_pnp_device *device;
- LIST_FOR_EACH_ENTRY( device, &root_pnp_devices, struct root_pnp_device, entry )
+ LIST_FOR_EACH_ENTRY( device, &driver->root_pnp_devices, struct root_pnp_device, entry )
{
if (!wcsicmp( id, device->id ))
return device;
@@ -1049,18 +1033,23 @@ void pnp_manager_start(void)
ERR("RpcBindingFromStringBinding() failed, error %#x\n", err);
}
-void pnp_manager_stop(void)
+void pnp_manager_stop_driver( struct wine_driver *driver )
{
struct root_pnp_device *device, *next;
- LIST_FOR_EACH_ENTRY_SAFE( device, next, &root_pnp_devices, struct root_pnp_device, entry )
+ LIST_FOR_EACH_ENTRY_SAFE( device, next, &driver->root_pnp_devices, struct root_pnp_device, entry )
remove_device( device->device );
+}
+
+void pnp_manager_stop(void)
+{
IoDeleteDriver( pnp_manager );
RpcBindingFree( &plugplay_binding_handle );
}
-void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
+void pnp_manager_enumerate_root_devices( struct wine_driver *driver )
{
+ const WCHAR *driver_name = wcsrchr( driver->driver_obj.DriverName.Buffer, '\\' ) + 1;
static const WCHAR driverW[] = {'\\','D','r','i','v','e','r','\\',0};
static const WCHAR rootW[] = {'R','O','O','T',0};
WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(driverW)], id[MAX_DEVICE_ID_LEN];
@@ -1091,7 +1080,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
SetupDiGetDeviceInstanceIdW( set, &sp_device, id, ARRAY_SIZE(id), NULL );
- if (find_root_pnp_device( id ))
+ if (find_root_pnp_device( driver, id ))
continue;
TRACE("Adding new root-enumerated device %s.\n", debugstr_w(id));
@@ -1106,7 +1095,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
pnp_device = device->DeviceExtension;
wcscpy( pnp_device->id, id );
pnp_device->device = device;
- list_add_tail( &root_pnp_devices, &pnp_device->entry );
+ list_add_tail( &driver->root_pnp_devices, &pnp_device->entry );
start_device( device, set, &sp_device );
}
diff --git a/dlls/ntoskrnl.exe/sync.c b/dlls/ntoskrnl.exe/sync.c
index 2aa60a0f2a0..445c8d890ab 100644
--- a/dlls/ntoskrnl.exe/sync.c
+++ b/dlls/ntoskrnl.exe/sync.c
@@ -19,24 +19,13 @@
*/
#include <limits.h>
-#include <stdarg.h>
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "windef.h"
-#include "winbase.h"
-#include "winternl.h"
+#include "ntoskrnl_private.h"
#include "ddk/ntddk.h"
-#include "ddk/wdm.h"
-#include "ddk/ntifs.h"
-#include "wine/asm.h"
-#include "wine/debug.h"
#include "wine/heap.h"
#include "wine/server.h"
-#include "ntoskrnl_private.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
enum object_type
--
2.30.2
More information about the wine-devel
mailing list