ntoskrnl: Store root PnP devices per driver.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
414003e2d9
commit
6977b81807
|
@ -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 );
|
||||
|
@ -110,6 +88,24 @@ static struct wine_rb_tree wine_drivers = { wine_drivers_rb_compare };
|
|||
|
||||
DECLARE_CRITICAL_SECTION(drivers_cs);
|
||||
|
||||
struct wine_driver *get_driver( const WCHAR *name )
|
||||
{
|
||||
static const WCHAR driverW[] = L"\\Driver\\";
|
||||
struct wine_rb_entry *entry;
|
||||
UNICODE_STRING drv_name;
|
||||
|
||||
drv_name.Length = (wcslen( driverW ) + wcslen( name )) * sizeof(WCHAR);
|
||||
if (!(drv_name.Buffer = malloc( drv_name.Length + sizeof(WCHAR) )))
|
||||
return NULL;
|
||||
wcscpy( drv_name.Buffer, driverW );
|
||||
wcscat( drv_name.Buffer, name );
|
||||
entry = wine_rb_get( &wine_drivers, &drv_name );
|
||||
free( drv_name.Buffer );
|
||||
|
||||
if (entry) return WINE_RB_ENTRY_VALUE( entry, struct wine_driver, entry );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HANDLE get_device_manager(void)
|
||||
{
|
||||
static HANDLE device_manager;
|
||||
|
@ -902,6 +898,7 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
HANDLE manager = get_device_manager();
|
||||
struct dispatch_context context;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
struct wine_driver *driver;
|
||||
HANDLE handles[2];
|
||||
|
||||
context.handle = NULL;
|
||||
|
@ -983,9 +980,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event )
|
|||
|
||||
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();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1486,6 +1487,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 ))
|
||||
|
|
|
@ -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,12 +90,24 @@ 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_start(void) DECLSPEC_HIDDEN;
|
||||
void pnp_manager_stop_driver( struct wine_driver *driver ) DECLSPEC_HIDDEN;
|
||||
void pnp_manager_stop(void) DECLSPEC_HIDDEN;
|
||||
|
||||
struct wine_driver *get_driver( const WCHAR *name ) DECLSPEC_HIDDEN;
|
||||
|
||||
static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y',
|
||||
'\\','M','a','c','h','i','n','e',
|
||||
'\\','S','y','s','t','e','m',
|
||||
|
|
|
@ -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,12 +1033,16 @@ 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 );
|
||||
}
|
||||
|
@ -1066,6 +1054,7 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
|
|||
WCHAR buffer[MAX_SERVICE_NAME + ARRAY_SIZE(driverW)], id[MAX_DEVICE_ID_LEN];
|
||||
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
|
||||
struct root_pnp_device *pnp_device;
|
||||
struct wine_driver *driver;
|
||||
DEVICE_OBJECT *device;
|
||||
NTSTATUS status;
|
||||
unsigned int i;
|
||||
|
@ -1073,6 +1062,8 @@ void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
|
|||
|
||||
TRACE("Searching for new root-enumerated devices for driver %s.\n", debugstr_w(driver_name));
|
||||
|
||||
driver = get_driver( driver_name );
|
||||
|
||||
set = SetupDiGetClassDevsW( NULL, rootW, NULL, DIGCF_ALLCLASSES );
|
||||
if (set == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
|
@ -1091,7 +1082,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 +1097,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 );
|
||||
}
|
||||
|
|
|
@ -19,23 +19,12 @@
|
|||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winternl.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"
|
||||
#include "ddk/ntddk.h"
|
||||
|
||||
#include "wine/heap.h"
|
||||
#include "wine/server.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntoskrnl);
|
||||
|
||||
|
|
Loading…
Reference in New Issue