Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
200d7b25
Commit
200d7b25
authored
Jul 09, 2022
by
Zebediah Figura
Committed by
Alexandre Julliard
Jul 11, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntoskrnl/tests: Test asynchronicity of device PnP events.
parent
1215bc80
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
59 additions
and
6 deletions
+59
-6
driver_pnp.c
dlls/ntoskrnl.exe/tests/driver_pnp.c
+59
-6
No files found.
dlls/ntoskrnl.exe/tests/driver_pnp.c
View file @
200d7b25
...
...
@@ -41,10 +41,7 @@ static UNICODE_STRING control_symlink, bus_symlink;
static
DRIVER_OBJECT
*
driver_obj
;
static
DEVICE_OBJECT
*
bus_fdo
,
*
bus_pdo
;
static
DWORD
remove_device_count
;
static
DWORD
surprise_removal_count
;
static
DWORD
query_remove_device_count
;
static
DWORD
cancel_remove_device_count
;
static
unsigned
int
remove_device_count
,
surprise_removal_count
,
query_remove_device_count
,
cancel_remove_device_count
;
struct
irp_queue
{
...
...
@@ -100,6 +97,7 @@ struct device
UNICODE_STRING
child_symlink
;
DEVICE_POWER_STATE
power_state
;
struct
irp_queue
irp_queue
;
HANDLE
plug_event
,
plug_event2
;
};
static
struct
list
device_list
=
LIST_INIT
(
device_list
);
...
...
@@ -255,6 +253,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
case
IRP_MN_START_DEVICE
:
{
static
const
LARGE_INTEGER
wait_time
=
{.
QuadPart
=
-
500
*
10000
};
POWER_STATE
state
=
{.
DeviceState
=
PowerDeviceD0
};
NTSTATUS
status
;
...
...
@@ -271,6 +270,12 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
state
=
PoSetPowerState
(
device_obj
,
DevicePowerState
,
state
);
todo_wine
ok
(
state
.
DeviceState
==
device
->
power_state
,
"got previous state %u
\n
"
,
state
.
DeviceState
);
device
->
power_state
=
PowerDeviceD0
;
status
=
ZwWaitForSingleObject
(
device
->
plug_event
,
TRUE
,
&
wait_time
);
todo_wine
ok
(
!
status
,
"Failed to wait for child plug event, status %#lx.
\n
"
,
status
);
status
=
ZwSetEvent
(
device
->
plug_event2
,
NULL
);
ok
(
!
status
,
"Failed to set event, status %#lx.
\n
"
,
status
);
ret
=
STATUS_SUCCESS
;
break
;
}
...
...
@@ -288,6 +293,8 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
{
IoSetDeviceInterfaceState
(
&
device
->
child_symlink
,
FALSE
);
RtlFreeUnicodeString
(
&
device
->
child_symlink
);
ZwClose
(
device
->
plug_event
);
ZwClose
(
device
->
plug_event2
);
irp
->
IoStatus
.
Status
=
STATUS_SUCCESS
;
IoCompleteRequest
(
irp
,
IO_NO_INCREMENT
);
IoDeleteDevice
(
device
->
device_obj
);
...
...
@@ -351,10 +358,21 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
}
case
IRP_MN_SURPRISE_REMOVAL
:
{
static
const
LARGE_INTEGER
wait_time
=
{.
QuadPart
=
-
500
*
10000
};
NTSTATUS
status
;
surprise_removal_count
++
;
irp_queue_clear
(
&
device
->
irp_queue
);
status
=
ZwWaitForSingleObject
(
device
->
plug_event
,
TRUE
,
&
wait_time
);
ok
(
!
status
,
"Failed to wait for child plug event, status %#lx.
\n
"
,
status
);
status
=
ZwSetEvent
(
device
->
plug_event2
,
NULL
);
ok
(
!
status
,
"Failed to set event, status %#lx.
\n
"
,
status
);
ret
=
STATUS_SUCCESS
;
break
;
}
case
IRP_MN_QUERY_REMOVE_DEVICE
:
query_remove_device_count
++
;
...
...
@@ -584,7 +602,9 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
case
IOCTL_WINETEST_BUS_ADD_CHILD
:
{
static
const
LARGE_INTEGER
wait_time
=
{.
QuadPart
=
-
500
*
10000
};
DEVICE_OBJECT
*
device_obj
;
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
string
;
struct
device
*
device
;
NTSTATUS
status
;
...
...
@@ -605,6 +625,11 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
device
->
device_obj
=
device_obj
;
device
->
id
=
id
;
device
->
removed
=
FALSE
;
InitializeObjectAttributes
(
&
attr
,
NULL
,
OBJ_KERNEL_HANDLE
,
NULL
,
NULL
);
status
=
ZwCreateEvent
(
&
device
->
plug_event
,
EVENT_ALL_ACCESS
,
&
attr
,
SynchronizationEvent
,
FALSE
);
ok
(
!
status
,
"Failed to create event, status %#lx.
\n
"
,
status
);
status
=
ZwCreateEvent
(
&
device
->
plug_event2
,
EVENT_ALL_ACCESS
,
&
attr
,
SynchronizationEvent
,
FALSE
);
ok
(
!
status
,
"Failed to create event, status %#lx.
\n
"
,
status
);
ExAcquireFastMutex
(
&
driver_lock
);
list_add_tail
(
&
device_list
,
&
device
->
entry
);
...
...
@@ -613,13 +638,26 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
device_obj
->
Flags
&=
~
DO_DEVICE_INITIALIZING
;
IoInvalidateDeviceRelations
(
bus_pdo
,
BusRelations
);
IoInvalidateDeviceRelations
(
bus_pdo
,
BusRelations
);
/* Synchronize both ways, to show that the bus invalidation happens
* completely asynchronously and that neither thread blocks waiting
* for the other. */
status
=
ZwSetEvent
(
device
->
plug_event
,
NULL
);
ok
(
!
status
,
"Failed to set event, status %#lx.
\n
"
,
status
);
status
=
ZwWaitForSingleObject
(
device
->
plug_event2
,
TRUE
,
&
wait_time
);
ok
(
!
status
,
"Failed to wait for child plug event, status %#lx.
\n
"
,
status
);
return
STATUS_SUCCESS
;
}
case
IOCTL_WINETEST_BUS_REMOVE_CHILD
:
{
static
const
LARGE_INTEGER
wait_time
=
{.
QuadPart
=
-
500
*
10000
};
HANDLE
plug_event
=
NULL
,
plug_event2
=
NULL
;
struct
device
*
device
;
NTSTATUS
status
;
int
id
;
if
(
stack
->
Parameters
.
DeviceIoControl
.
InputBufferLength
<
sizeof
(
int
))
...
...
@@ -631,6 +669,8 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
{
if
(
device
->
id
==
id
)
{
plug_event
=
device
->
plug_event
;
plug_event2
=
device
->
plug_event2
;
list_remove
(
&
device
->
entry
);
device
->
removed
=
TRUE
;
break
;
...
...
@@ -639,9 +679,22 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code)
ExReleaseFastMutex
(
&
driver_lock
);
IoInvalidateDeviceRelations
(
bus_pdo
,
BusRelations
);
IoInvalidateDeviceRelations
(
bus_pdo
,
BusRelations
);
/* The actual removal might be asynchronous; we can't test that the
* device is gone here. */
/* Synchronize both ways, to show that the bus invalidation happens
* completely asynchronously and that neither thread blocks waiting
* for the other. */
status
=
ZwSetEvent
(
plug_event
,
NULL
);
todo_wine
ok
(
!
status
,
"Failed to set event, status %#lx.
\n
"
,
status
);
status
=
ZwWaitForSingleObject
(
plug_event2
,
TRUE
,
&
wait_time
);
todo_wine
ok
(
!
status
,
"Failed to wait for child plug event, status %#lx.
\n
"
,
status
);
ok
(
surprise_removal_count
==
1
,
"Got %u surprise removal events.
\n
"
,
surprise_removal_count
);
/* We shouldn't get IRP_MN_REMOVE_DEVICE until all user-space
* handles to the device are closed (and the user-space thread is
* currently blocked in this ioctl and won't close its handle
* yet.) */
todo_wine
ok
(
!
remove_device_count
,
"Got %u remove events.
\n
"
,
remove_device_count
);
return
STATUS_SUCCESS
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment