Skip to content

Commit d35691a

Browse files
committed
[KBDHID][MOUHID] Wait for startup fixes
1 parent f63ce4b commit d35691a

2 files changed

Lines changed: 102 additions & 32 deletions

File tree

drivers/hid/kbdhid/kbdhid.c

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ KbdHid_Create(
279279
{
280280
/* request pending */
281281
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
282+
Status = Irp->IoStatus.Status;
282283
}
283284

284285
/* check for success */
@@ -290,30 +291,41 @@ KbdHid_Create(
290291
return Status;
291292
}
292293

293-
/* is the driver already in use */
294-
if (DeviceExtension->FileObject == NULL)
294+
/*
295+
* Capture the FileObject used by the class driver for subsequent IRP_MJ_READ.
296+
* Do NOT start the read loop here: CREATE may arrive before StartDevice has
297+
* initialized the report buffer/MDL.
298+
*/
299+
if (DeviceExtension->FileObject == NULL && IoStack->FileObject != NULL)
295300
{
296-
/* did the caller specify correct attributes */
297-
ASSERT(IoStack->Parameters.Create.SecurityContext);
298-
if (IoStack->Parameters.Create.SecurityContext->DesiredAccess)
299-
{
300-
/* store file object */
301-
DeviceExtension->FileObject = IoStack->FileObject;
302-
303-
/* reset event */
304-
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
305-
306-
/* initiating read */
307-
Status = KbdHid_InitiateRead(DeviceExtension);
308-
DPRINT("[KBDHID] KbdHid_InitiateRead: status %x\n", Status);
309-
if (Status == STATUS_PENDING)
310-
{
311-
/* report irp is pending */
312-
Status = STATUS_SUCCESS;
313-
}
314-
}
301+
DeviceExtension->FileObject = IoStack->FileObject;
302+
DeviceExtension->StopReadReport = FALSE;
315303
}
316304

305+
/* If we're already started and connected, we can safely start the read loop now. */
306+
if (DeviceExtension->ClassService != NULL &&
307+
DeviceExtension->FileObject != NULL &&
308+
DeviceExtension->ReportMDL != NULL &&
309+
DeviceExtension->ReportLength != 0 &&
310+
!DeviceExtension->ReadReportActive)
311+
{
312+
DeviceExtension->StopReadReport = FALSE;
313+
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
314+
Status = KbdHid_InitiateRead(DeviceExtension);
315+
DPRINT("[KBDHID] KbdHid_InitiateRead (create/post-start): status %x\n", Status);
316+
if (Status == STATUS_PENDING)
317+
{
318+
Status = STATUS_SUCCESS;
319+
}
320+
}
321+
322+
/*
323+
* Do not start the read loop from CREATE.
324+
* CREATE can arrive before IRP_MN_START_DEVICE finished initializing
325+
* the input report buffer/MDL; starting reads early can crash the lower HID stack.
326+
* The read loop is started from IOCTL_INTERNAL_KEYBOARD_CONNECT and/or after StartDevice.
327+
*/
328+
317329
/* complete request */
318330
Irp->IoStatus.Status = Status;
319331
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -368,6 +380,7 @@ KbdHid_InternalDeviceControl(
368380
PKBDHID_DEVICE_EXTENSION DeviceExtension;
369381
PCONNECT_DATA Data;
370382
PKEYBOARD_ATTRIBUTES Attributes;
383+
NTSTATUS Status;
371384

372385
/* get current stack location */
373386
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -430,6 +443,25 @@ KbdHid_InternalDeviceControl(
430443
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
431444
DeviceExtension->ClassService = Data->ClassService;
432445

446+
/* Some callers won't supply a FileObject on internal IOCTLs; keep it if present. */
447+
if (DeviceExtension->FileObject == NULL && IoStack->FileObject != NULL)
448+
{
449+
DeviceExtension->FileObject = IoStack->FileObject;
450+
}
451+
452+
/* Start the read loop only if StartDevice has initialized the report buffer/MDL. */
453+
if (DeviceExtension->FileObject != NULL &&
454+
DeviceExtension->ReportMDL != NULL &&
455+
DeviceExtension->ReportLength != 0 &&
456+
!DeviceExtension->ReadReportActive)
457+
{
458+
DeviceExtension->StopReadReport = FALSE;
459+
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
460+
461+
Status = KbdHid_InitiateRead(DeviceExtension);
462+
DPRINT("[KBDHID] KbdHid_InitiateRead (connect): status %x\n", Status);
463+
}
464+
433465
/* completed successfully */
434466
Irp->IoStatus.Status = STATUS_SUCCESS;
435467
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -782,6 +814,17 @@ KbdHid_StartDevice(
782814
/* store preparsed data */
783815
DeviceExtension->PreparsedData = PreparsedData;
784816

817+
/* If the class driver already connected & opened us, start the read loop now. */
818+
if (DeviceExtension->ClassService != NULL &&
819+
DeviceExtension->FileObject != NULL &&
820+
!DeviceExtension->ReadReportActive)
821+
{
822+
DeviceExtension->StopReadReport = FALSE;
823+
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
824+
Status = KbdHid_InitiateRead(DeviceExtension);
825+
DPRINT("[KBDHID] KbdHid_InitiateRead (start): status %x\n", Status);
826+
}
827+
785828
/* completed successfully */
786829
return STATUS_SUCCESS;
787830
}

drivers/hid/mouhid/mouhid.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,35 @@ MouHid_InitiateRead(
447447
return Status;
448448
}
449449

450+
static
451+
NTSTATUS
452+
MouHid_TryStartRead(
453+
_In_ PMOUHID_DEVICE_EXTENSION DeviceExtension)
454+
{
455+
NTSTATUS Status;
456+
457+
if (!DeviceExtension->ClassService || !DeviceExtension->ClassDeviceObject)
458+
return STATUS_DEVICE_NOT_READY;
459+
460+
if (!DeviceExtension->FileObject)
461+
return STATUS_DEVICE_NOT_READY;
462+
463+
if (!DeviceExtension->Report || !DeviceExtension->ReportMDL || !DeviceExtension->ReportLength)
464+
return STATUS_DEVICE_NOT_READY;
465+
466+
if (DeviceExtension->ReadReportActive)
467+
return STATUS_SUCCESS;
468+
469+
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
470+
471+
Status = MouHid_InitiateRead(DeviceExtension);
472+
DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
473+
if (Status == STATUS_PENDING)
474+
Status = STATUS_SUCCESS;
475+
476+
return Status;
477+
}
478+
450479
NTSTATUS
451480
NTAPI
452481
MouHid_CreateCompletion(
@@ -498,6 +527,7 @@ MouHid_Create(
498527
{
499528
/* request pending */
500529
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
530+
Status = Irp->IoStatus.Status;
501531
}
502532

503533
/* check for success */
@@ -519,17 +549,8 @@ MouHid_Create(
519549
/* store file object */
520550
DeviceExtension->FileObject = IoStack->FileObject;
521551

522-
/* reset event */
523-
KeClearEvent(&DeviceExtension->ReadCompletionEvent);
524-
525-
/* initiating read */
526-
Status = MouHid_InitiateRead(DeviceExtension);
527-
DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
528-
if (Status == STATUS_PENDING)
529-
{
530-
/* report irp is pending */
531-
Status = STATUS_SUCCESS;
532-
}
552+
/* Start reads only once we're started and connected */
553+
Status = MouHid_TryStartRead(DeviceExtension);
533554
}
534555
}
535556

@@ -664,6 +685,9 @@ MouHid_InternalDeviceControl(
664685
DeviceExtension->ClassDeviceObject = Data->ClassDeviceObject;
665686
DeviceExtension->ClassService = Data->ClassService;
666687

688+
/* If the device is already opened and started, begin the read loop now */
689+
(VOID)MouHid_TryStartRead(DeviceExtension);
690+
667691
/* completed successfully */
668692
Irp->IoStatus.Status = STATUS_SUCCESS;
669693
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -979,6 +1003,9 @@ MouHid_StartDevice(
9791003
DeviceExtension->MouseAbsolute = TRUE;
9801004
}
9811005

1006+
/* If class driver is already connected and we have a FileObject, start reads now */
1007+
(VOID)MouHid_TryStartRead(DeviceExtension);
1008+
9821009
/* completed successfully */
9831010
return STATUS_SUCCESS;
9841011
}

0 commit comments

Comments
 (0)