@@ -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}
0 commit comments