dinput/tests: Introduce a new Wine Test Bus driver.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
24785b4096
commit
657e07aea5
|
@ -3,6 +3,8 @@ IMPORTS = dinput dinput8 ole32 version user32 advapi32 hid uuid crypt32 newdev
|
|||
|
||||
driver_IMPORTS = winecrt0 ntoskrnl hal hidclass
|
||||
driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
|
||||
driver_bus_IMPORTS = winecrt0 ntoskrnl hal
|
||||
driver_bus_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
|
||||
|
||||
SOURCES = \
|
||||
device.c \
|
||||
|
@ -10,6 +12,8 @@ SOURCES = \
|
|||
dinput.c \
|
||||
driver.c \
|
||||
driver.spec \
|
||||
driver_bus.c \
|
||||
driver_bus.spec \
|
||||
force_feedback.c \
|
||||
hid.c \
|
||||
hotplug.c \
|
||||
|
|
|
@ -54,6 +54,8 @@ extern BOOL localized; /* object names get translated */
|
|||
|
||||
BOOL hid_device_start(void);
|
||||
void hid_device_stop(void);
|
||||
BOOL bus_device_start(void);
|
||||
void bus_device_stop(void);
|
||||
|
||||
void cleanup_registry_keys(void);
|
||||
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Plug and Play test driver
|
||||
*
|
||||
* Copyright 2022 Rémi Bernon for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winternl.h"
|
||||
#include "winioctl.h"
|
||||
#include "ddk/wdm.h"
|
||||
|
||||
#include "wine/list.h"
|
||||
|
||||
#include "initguid.h"
|
||||
#include "driver_hid.h"
|
||||
|
||||
typedef ULONG PNP_DEVICE_STATE;
|
||||
#define PNP_DEVICE_REMOVED 8
|
||||
|
||||
struct device
|
||||
{
|
||||
KSPIN_LOCK lock;
|
||||
PNP_DEVICE_STATE state;
|
||||
};
|
||||
|
||||
static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device )
|
||||
{
|
||||
return (struct device *)device->DeviceExtension;
|
||||
}
|
||||
|
||||
struct func_device
|
||||
{
|
||||
struct device base;
|
||||
DEVICE_OBJECT *pdo; /* lower PDO */
|
||||
UNICODE_STRING control_iface;
|
||||
};
|
||||
|
||||
static inline struct func_device *fdo_from_DEVICE_OBJECT( DEVICE_OBJECT *device )
|
||||
{
|
||||
struct device *impl = impl_from_DEVICE_OBJECT( device );
|
||||
return CONTAINING_RECORD( impl, struct func_device, base );
|
||||
}
|
||||
|
||||
#ifdef __ASM_USE_FASTCALL_WRAPPER
|
||||
extern void *WINAPI wrap_fastcall_func1( void *func, const void *a );
|
||||
__ASM_STDCALL_FUNC( wrap_fastcall_func1, 8,
|
||||
"popl %ecx\n\t"
|
||||
"popl %eax\n\t"
|
||||
"xchgl (%esp),%ecx\n\t"
|
||||
"jmp *%eax" );
|
||||
#define call_fastcall_func1( func, a ) wrap_fastcall_func1( func, a )
|
||||
#else
|
||||
#define call_fastcall_func1( func, a ) func( a )
|
||||
#endif
|
||||
|
||||
static ULONG_PTR get_device_relations( DEVICE_OBJECT *device, DEVICE_RELATIONS *previous,
|
||||
ULONG count, DEVICE_OBJECT **devices )
|
||||
{
|
||||
DEVICE_RELATIONS *relations;
|
||||
ULONG new_count = count;
|
||||
|
||||
if (previous) new_count += previous->Count;
|
||||
if (!(relations = ExAllocatePool( PagedPool, offsetof( DEVICE_RELATIONS, Objects[new_count] ) )))
|
||||
{
|
||||
ok( 0, "Failed to allocate memory\n" );
|
||||
return (ULONG_PTR)previous;
|
||||
}
|
||||
|
||||
if (!previous) relations->Count = 0;
|
||||
else
|
||||
{
|
||||
memcpy( relations, previous, offsetof( DEVICE_RELATIONS, Objects[previous->Count] ) );
|
||||
ExFreePool( previous );
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
call_fastcall_func1( ObfReferenceObject, *devices );
|
||||
relations->Objects[relations->Count++] = *devices++;
|
||||
}
|
||||
|
||||
return (ULONG_PTR)relations;
|
||||
}
|
||||
|
||||
static NTSTATUS fdo_pnp( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
struct func_device *impl = fdo_from_DEVICE_OBJECT( device );
|
||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||
ULONG code = stack->MinorFunction;
|
||||
PNP_DEVICE_STATE state;
|
||||
NTSTATUS status;
|
||||
KIRQL irql;
|
||||
|
||||
if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_pnp(code) );
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
state = (code == IRP_MN_START_DEVICE || code == IRP_MN_CANCEL_REMOVE_DEVICE) ? 0 : PNP_DEVICE_REMOVED;
|
||||
KeAcquireSpinLock( &impl->base.lock, &irql );
|
||||
impl->base.state = state;
|
||||
KeReleaseSpinLock( &impl->base.lock, irql );
|
||||
IoSetDeviceInterfaceState( &impl->control_iface, state != PNP_DEVICE_REMOVED );
|
||||
if (code != IRP_MN_REMOVE_DEVICE) status = STATUS_SUCCESS;
|
||||
else
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation( irp );
|
||||
status = IoCallDriver( impl->pdo, irp );
|
||||
IoDetachDevice( impl->pdo );
|
||||
RtlFreeUnicodeString( &impl->control_iface );
|
||||
IoDeleteDevice( device );
|
||||
if (winetest_debug > 1) trace( "Deleted Bus FDO %p from PDO %p, status %#lx\n", impl, impl->pdo, status );
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
||||
KeAcquireSpinLock( &impl->base.lock, &irql );
|
||||
irp->IoStatus.Information = impl->base.state;
|
||||
KeReleaseSpinLock( &impl->base.lock, irql );
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
{
|
||||
DEVICE_RELATION_TYPE type = stack->Parameters.QueryDeviceRelations.Type;
|
||||
switch (type)
|
||||
{
|
||||
case BusRelations:
|
||||
if (winetest_debug > 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" );
|
||||
ok( !irp->IoStatus.Information, "got unexpected BusRelations relations\n" );
|
||||
irp->IoStatus.Information = get_device_relations( device, (void *)irp->IoStatus.Information, 0, NULL );
|
||||
if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY;
|
||||
else status = STATUS_SUCCESS;
|
||||
break;
|
||||
case RemovalRelations:
|
||||
if (winetest_debug > 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" );
|
||||
ok( !irp->IoStatus.Information, "got unexpected RemovalRelations relations\n" );
|
||||
irp->IoStatus.Information = get_device_relations( device, (void *)irp->IoStatus.Information,
|
||||
1, &impl->pdo );
|
||||
if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY;
|
||||
else status = STATUS_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type );
|
||||
status = irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IRP_MN_QUERY_CAPABILITIES:
|
||||
{
|
||||
DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities;
|
||||
caps->EjectSupported = TRUE;
|
||||
caps->Removable = TRUE;
|
||||
caps->SilentInstall = TRUE;
|
||||
caps->SurpriseRemovalOK = TRUE;
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (winetest_debug > 1) trace( "fdo_pnp code %#lx %s, not implemented!\n", code, debugstr_pnp(code) );
|
||||
status = irp->IoStatus.Status;
|
||||
break;
|
||||
}
|
||||
|
||||
irp->IoStatus.Status = status;
|
||||
IoSkipCurrentIrpStackLocation( irp );
|
||||
return IoCallDriver( impl->pdo, irp );
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
return fdo_pnp( device, irp );
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
|
||||
ok( 0, "unexpected call\n" );
|
||||
|
||||
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp );
|
||||
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
|
||||
|
||||
if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
|
||||
ok( 0, "unexpected call\n" );
|
||||
|
||||
irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *device )
|
||||
{
|
||||
struct func_device *impl;
|
||||
DEVICE_OBJECT *child;
|
||||
NTSTATUS status;
|
||||
|
||||
if (winetest_debug > 1) trace( "%s: driver %p, device %p\n", __func__, driver, device );
|
||||
|
||||
if ((status = IoCreateDevice( driver, sizeof(struct func_device), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &child )))
|
||||
{
|
||||
ok( 0, "Failed to create FDO, status %#lx.\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
impl = (struct func_device *)child->DeviceExtension;
|
||||
KeInitializeSpinLock( &impl->base.lock );
|
||||
impl->pdo = device;
|
||||
|
||||
status = IoRegisterDeviceInterface( impl->pdo, &control_class, NULL, &impl->control_iface );
|
||||
ok( !status, "IoRegisterDeviceInterface returned %#lx\n", status );
|
||||
|
||||
if (winetest_debug > 1) trace( "Created Bus FDO %p for PDO %p\n", child, device );
|
||||
|
||||
IoAttachDeviceToDeviceStack( child, device );
|
||||
child->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_create( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
if (winetest_debug > 1) trace( "%s: device %p, irp %p\n", __func__, device, irp );
|
||||
|
||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI driver_close( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
if (winetest_debug > 1) trace( "%s: device %p, irp %p\n", __func__, device, irp );
|
||||
|
||||
irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void WINAPI driver_unload( DRIVER_OBJECT *driver )
|
||||
{
|
||||
if (winetest_debug > 1) trace( "%s: driver %p\n", __func__, driver );
|
||||
winetest_cleanup();
|
||||
}
|
||||
|
||||
NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if ((status = winetest_init())) return status;
|
||||
if (winetest_debug > 1) trace( "%s: driver %p\n", __func__, driver );
|
||||
|
||||
driver->DriverExtension->AddDevice = driver_add_device;
|
||||
driver->DriverUnload = driver_unload;
|
||||
driver->MajorFunction[IRP_MJ_PNP] = driver_pnp;
|
||||
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_ioctl;
|
||||
driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = driver_internal_ioctl;
|
||||
driver->MajorFunction[IRP_MJ_CREATE] = driver_create;
|
||||
driver->MajorFunction[IRP_MJ_CLOSE] = driver_close;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
# nothing here yet
|
|
@ -315,6 +315,7 @@ static const char inf_text[] =
|
|||
|
||||
"[mfg_section.NT" EXT "]\n"
|
||||
"Wine test root driver=device_section,test_hardware_id\n"
|
||||
"Wine Test Bus Device=bus_section,WINETEST\\BUS\n"
|
||||
|
||||
"[device_section.NT" EXT "]\n"
|
||||
"CopyFiles=file_section\n"
|
||||
|
@ -322,14 +323,23 @@ static const char inf_text[] =
|
|||
"[device_section.NT" EXT ".Services]\n"
|
||||
"AddService=winetest,0x2,svc_section\n"
|
||||
|
||||
"[bus_section.NT" EXT "]\n"
|
||||
"CopyFiles=file_section\n"
|
||||
|
||||
"[bus_section.NT" EXT ".Services]\n"
|
||||
"AddService=winetest_bus,0x2,bus_service\n"
|
||||
|
||||
"[file_section]\n"
|
||||
"winetest.sys\n"
|
||||
"winetest_bus.sys\n"
|
||||
|
||||
"[SourceDisksFiles]\n"
|
||||
"winetest.sys=1\n"
|
||||
"winetest_bus.sys=1\n"
|
||||
|
||||
"[SourceDisksNames]\n"
|
||||
"1=,winetest.sys\n"
|
||||
"1=,winetest_bus.sys\n"
|
||||
|
||||
"[DestinationDirs]\n"
|
||||
"DefaultDestDir=12\n"
|
||||
|
@ -341,6 +351,14 @@ static const char inf_text[] =
|
|||
"ErrorControl=1\n"
|
||||
"LoadOrderGroup=WinePlugPlay\n"
|
||||
"DisplayName=\"winetest bus driver\"\n"
|
||||
|
||||
"[bus_service]\n"
|
||||
"ServiceBinary=%12%\\winetest_bus.sys\n"
|
||||
"ServiceType=1\n"
|
||||
"StartType=3\n"
|
||||
"ErrorControl=1\n"
|
||||
"LoadOrderGroup=WinePlugPlay\n"
|
||||
"DisplayName=\"Wine Test Bus Driver\"\n"
|
||||
"; they don't sleep anymore, on the beach\n";
|
||||
|
||||
static void add_file_to_catalog( HANDLE catalog, const WCHAR *file )
|
||||
|
@ -415,9 +433,9 @@ static void unload_driver( SC_HANDLE service )
|
|||
CloseServiceHandle( service );
|
||||
}
|
||||
|
||||
static void pnp_driver_stop(void)
|
||||
static void pnp_driver_stop( BOOL bus )
|
||||
{
|
||||
const WCHAR *service_name = L"winetest";
|
||||
const WCHAR *service_name = bus ? L"winetest_bus" : L"winetest";
|
||||
SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
|
||||
WCHAR path[MAX_PATH], dest[MAX_PATH], *filepart;
|
||||
SC_HANDLE manager, service;
|
||||
|
@ -484,9 +502,13 @@ static void pnp_driver_stop(void)
|
|||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"winetest.sys" );
|
||||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"winetest_bus.sys" );
|
||||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
/* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
|
||||
ret = DeleteFileW( L"C:/windows/system32/drivers/winetest.sys" );
|
||||
ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"C:/windows/system32/drivers/winetest_bus.sys" );
|
||||
ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
}
|
||||
|
||||
static BOOL find_hid_device_path( WCHAR *device_path )
|
||||
|
@ -525,12 +547,13 @@ static BOOL find_hid_device_path( WCHAR *device_path )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL pnp_driver_start(void)
|
||||
static BOOL pnp_driver_start( BOOL bus )
|
||||
{
|
||||
static const WCHAR hardware_id[] = L"test_hardware_id\0";
|
||||
static const WCHAR bus_hardware_id[] = L"WINETEST\\BUS";
|
||||
const WCHAR *service_name = bus ? L"winetest_bus" : L"winetest";
|
||||
SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
|
||||
WCHAR path[MAX_PATH], filename[MAX_PATH];
|
||||
const WCHAR *service_name = L"winetest";
|
||||
SC_HANDLE manager, service;
|
||||
const CERT_CONTEXT *cert;
|
||||
int old_mute_threshold;
|
||||
|
@ -546,6 +569,10 @@ static BOOL pnp_driver_start(void)
|
|||
ret = MoveFileExW( filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING );
|
||||
ok( ret, "failed to move file, error %lu\n", GetLastError() );
|
||||
|
||||
load_resource( L"driver_bus.dll", filename );
|
||||
ret = MoveFileExW( filename, L"winetest_bus.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING );
|
||||
ok( ret, "failed to move file, error %lu\n", GetLastError() );
|
||||
|
||||
f = fopen( "winetest.inf", "w" );
|
||||
ok( !!f, "failed to open winetest.inf: %s\n", strerror( errno ) );
|
||||
fputs( inf_text, f );
|
||||
|
@ -557,6 +584,7 @@ static BOOL pnp_driver_start(void)
|
|||
ok( catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %lu\n", GetLastError() );
|
||||
|
||||
add_file_to_catalog( catalog, L"winetest.sys" );
|
||||
add_file_to_catalog( catalog, L"winetest_bus.sys" );
|
||||
add_file_to_catalog( catalog, L"winetest.inf" );
|
||||
|
||||
ret = CryptCATPersistStore( catalog );
|
||||
|
@ -572,6 +600,8 @@ static BOOL pnp_driver_start(void)
|
|||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"winetest.inf" );
|
||||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"winetest_bus.sys" );
|
||||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
ret = DeleteFileW( L"winetest.sys" );
|
||||
ok( ret, "Failed to delete file, error %lu\n", GetLastError() );
|
||||
winetest_mute_threshold = old_mute_threshold;
|
||||
|
@ -586,8 +616,9 @@ static BOOL pnp_driver_start(void)
|
|||
ret = SetupDiCreateDeviceInfoW( set, L"root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device );
|
||||
ok( ret, "failed to create device, error %#lx\n", GetLastError() );
|
||||
|
||||
ret = SetupDiSetDeviceRegistryPropertyW( set, &device, SPDRP_HARDWAREID, (const BYTE *)hardware_id,
|
||||
sizeof(hardware_id) );
|
||||
ret = SetupDiSetDeviceRegistryPropertyW( set, &device, SPDRP_HARDWAREID,
|
||||
bus ? (const BYTE *)bus_hardware_id : (const BYTE *)hardware_id,
|
||||
bus ? sizeof(bus_hardware_id) : sizeof(hardware_id) );
|
||||
ok( ret, "failed to create set hardware ID, error %lu\n", GetLastError() );
|
||||
|
||||
ret = SetupDiCallClassInstaller( DIF_REGISTERDEVICE, set, &device );
|
||||
|
@ -598,7 +629,8 @@ static BOOL pnp_driver_start(void)
|
|||
|
||||
GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL );
|
||||
|
||||
ret = UpdateDriverForPlugAndPlayDevicesW( NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot );
|
||||
ret = UpdateDriverForPlugAndPlayDevicesW( NULL, bus ? bus_hardware_id : hardware_id, path,
|
||||
INSTALLFLAG_FORCE, &need_reboot );
|
||||
ok( ret, "failed to install device, error %lu\n", GetLastError() );
|
||||
ok( !need_reboot, "expected no reboot necessary\n" );
|
||||
|
||||
|
@ -630,12 +662,22 @@ static BOOL pnp_driver_start(void)
|
|||
|
||||
void hid_device_stop(void)
|
||||
{
|
||||
pnp_driver_stop();
|
||||
pnp_driver_stop( FALSE );
|
||||
}
|
||||
|
||||
BOOL hid_device_start(void)
|
||||
{
|
||||
return pnp_driver_start();
|
||||
return pnp_driver_start( FALSE );
|
||||
}
|
||||
|
||||
void bus_device_stop(void)
|
||||
{
|
||||
pnp_driver_stop( TRUE );
|
||||
}
|
||||
|
||||
BOOL bus_device_start(void)
|
||||
{
|
||||
return pnp_driver_start( TRUE );
|
||||
}
|
||||
|
||||
#define check_hidp_caps( a, b ) check_hidp_caps_( __LINE__, a, b )
|
||||
|
@ -3398,6 +3440,7 @@ BOOL dinput_test_init_( const char *file, int line )
|
|||
ok( okfile != INVALID_HANDLE_VALUE, "failed to create file, error %lu\n", GetLastError() );
|
||||
|
||||
subtest( "driver" );
|
||||
subtest( "driver_bus" );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3566,10 +3609,39 @@ DWORD WINAPI dinput_test_device_thread( void *stop_event )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void test_bus_driver(void)
|
||||
{
|
||||
HANDLE control;
|
||||
|
||||
if (!bus_device_start()) goto done;
|
||||
|
||||
control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL );
|
||||
ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() );
|
||||
CloseHandle( control );
|
||||
|
||||
bus_device_stop();
|
||||
|
||||
control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL );
|
||||
ok( control == INVALID_HANDLE_VALUE, "CreateFile succeeded\n" );
|
||||
|
||||
bus_device_start();
|
||||
|
||||
control = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0,
|
||||
NULL, OPEN_EXISTING, 0, NULL );
|
||||
ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() );
|
||||
CloseHandle( control );
|
||||
|
||||
done:
|
||||
bus_device_stop();
|
||||
}
|
||||
|
||||
START_TEST( hid )
|
||||
{
|
||||
if (!dinput_test_init()) return;
|
||||
|
||||
test_bus_driver();
|
||||
test_hidp_kdr();
|
||||
test_hid_driver( 0, FALSE );
|
||||
test_hid_driver( 1, FALSE );
|
||||
|
|
Loading…
Reference in New Issue