|
|
1.1 root 1:
2: /*++
3:
4: Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
5:
6: Module Name:
7:
8: mouclass.c
9:
10: Abstract:
11:
12: Mouse class driver.
13:
14: Environment:
15:
16: Kernel mode only.
17:
18: Notes:
19:
20: NOTES: (Future/outstanding issues)
21:
22: - Powerfail not implemented.
23:
24: - Consolidate duplicate code, where possible and appropriate.
25:
26: - Unload not implemented. We don't want to allow this driver
27: to unload.
28:
29: Revision History:
30:
31: --*/
32:
33: #include "stdarg.h"
34: #include "stdio.h"
35: #include "ntddk.h"
36: #include "mouclass.h"
37: #include "kbdmou.h"
38: #include "moulog.h"
39:
40:
41: NTSTATUS
42: DriverEntry(
43: IN PDRIVER_OBJECT DriverObject,
44: IN PUNICODE_STRING RegistryPath
45: );
46:
47: VOID
48: MouseClassCancel(
49: IN PDEVICE_OBJECT DeviceObject,
50: IN PIRP Irp
51: );
52:
53: NTSTATUS
54: MouseClassCleanup(
55: IN PDEVICE_OBJECT DeviceObject,
56: IN PIRP Irp
57: );
58:
59: NTSTATUS
60: MouseClassDeviceControl(
61: IN PDEVICE_OBJECT DeviceObject,
62: IN PIRP Irp
63: );
64:
65: NTSTATUS
66: MouseClassFlush(
67: IN PDEVICE_OBJECT DeviceObject,
68: IN PIRP Irp
69: );
70:
71: NTSTATUS
72: MouseClassOpenClose(
73: IN PDEVICE_OBJECT DeviceObject,
74: IN PIRP Irp
75: );
76:
77: NTSTATUS
78: MouseClassRead(
79: IN PDEVICE_OBJECT DeviceObject,
80: IN PIRP Irp
81: );
82:
83: VOID
84: MouseClassServiceCallback(
85: IN PDEVICE_OBJECT DeviceObject,
86: IN PMOUSE_INPUT_DATA InputDataStart,
87: IN PMOUSE_INPUT_DATA InputDataEnd,
88: IN OUT PULONG InputDataConsumed
89: );
90:
91: VOID
92: MouseClassStartIo(
93: IN PDEVICE_OBJECT DeviceObject,
94: IN PIRP Irp
95: );
96:
97: VOID
98: MouseClassUnload(
99: IN PDRIVER_OBJECT DriverObject
100: );
101:
102: BOOLEAN
103: MouCancelRequest(
104: IN PVOID Context
105: );
106:
107: VOID
108: MouConfiguration(
109: IN PDEVICE_EXTENSION DeviceExtension,
110: IN PUNICODE_STRING RegistryPath,
111: IN PUNICODE_STRING DeviceName
112: );
113:
114: NTSTATUS
115: MouConnectToPort(
116: IN PDEVICE_OBJECT ClassDeviceObject,
117: IN PUNICODE_STRING FullPortName,
118: IN ULONG PortIndex
119: );
120:
121: NTSTATUS
122: MouCreateClassObject(
123: IN PDRIVER_OBJECT DriverObject,
124: IN PDEVICE_EXTENSION TmpDeviceExtension,
125: IN PUNICODE_STRING RegistryPath,
126: IN PUNICODE_STRING FullDeviceName,
127: IN PUNICODE_STRING BaseDeviceName,
128: IN PDEVICE_OBJECT *ClassDeviceObject
129: );
130:
131: #if DBG
132:
133: VOID
134: MouDebugPrint(
135: ULONG DebugPrintLevel,
136: PCCHAR DebugMessage,
137: ...
138: );
139:
140: //
141: // Declare the global debug flag for this driver.
142: //
143:
144: ULONG MouseDebug = 0;
145: #define MouPrint(x) MouDebugPrint x
146: #else
147: #define MouPrint(x)
148: #endif
149:
150: NTSTATUS
151: MouDeterminePortsServiced(
152: IN PUNICODE_STRING BasePortName,
153: IN OUT PULONG NumberPortsServiced
154: );
155:
156: NTSTATUS
157: MouDeviceMapQueryCallback(
158: IN PWSTR ValueName,
159: IN ULONG ValueType,
160: IN PVOID ValueData,
161: IN ULONG ValueLength,
162: IN PVOID Context,
163: IN PVOID EntryContext
164: );
165:
166: NTSTATUS
167: MouEnableDisablePort(
168: IN PDEVICE_OBJECT DeviceObject,
169: IN BOOLEAN EnableFlag,
170: IN ULONG PortIndex
171: );
172:
173: VOID
174: MouInitializeDataQueue(
175: IN PVOID Context
176: );
177:
178: NTSTATUS
179: MouSendConnectRequest(
180: IN PDEVICE_OBJECT DeviceObject,
181: IN PVOID ServiceCallback,
182: IN ULONG PortIndex
183: );
184:
185: //
186: // Use the alloc_text pragma to specify the driver initialization routines
187: // (they can be paged out).
188: //
189:
190: #ifdef ALLOC_PRAGMA
191: #pragma alloc_text(init,DriverEntry)
192: #pragma alloc_text(init,MouConfiguration)
193: #pragma alloc_text(init,MouCreateClassObject)
194: #pragma alloc_text(init,MouDeterminePortsServiced)
195: #pragma alloc_text(init,MouDeviceMapQueryCallback)
196: #pragma alloc_text(init,MouConnectToPort)
197: #pragma alloc_text(init,MouSendConnectRequest)
198: #endif
199:
200:
201: NTSTATUS
202: DriverEntry(
203: IN PDRIVER_OBJECT DriverObject,
204: IN PUNICODE_STRING RegistryPath
205: )
206:
207: /*++
208:
209: Routine Description:
210:
211: This routine initializes the mouse class driver.
212:
213: Arguments:
214:
215: DriverObject - Pointer to driver object created by system.
216:
217: RegistryPath - Pointer to the Unicode name of the registry path
218: for this driver.
219:
220: Return Value:
221:
222: The function value is the final status from the initialization operation.
223:
224: --*/
225:
226: {
227: DEVICE_EXTENSION tmpDeviceExtension;
228: PDEVICE_OBJECT classDeviceObject = NULL;
229: PDEVICE_EXTENSION deviceExtension = NULL;
230: NTSTATUS status;
231: ULONG i;
232: ULONG portConnectionSuccessful;
233: UNICODE_STRING fullClassName;
234: UNICODE_STRING fullPortName;
235: UNICODE_STRING baseClassName;
236: UNICODE_STRING basePortName;
237: UNICODE_STRING deviceNameSuffix;
238: UNICODE_STRING registryPath;
239: PIO_ERROR_LOG_PACKET errorLogEntry;
240: ULONG uniqueErrorValue;
241: ULONG dumpCount = 0;
242: NTSTATUS errorCode = STATUS_SUCCESS;
243:
244: #define NAME_MAX 256
245: WCHAR baseClassBuffer[NAME_MAX];
246: WCHAR basePortBuffer[NAME_MAX];
247:
248: #define DUMP_COUNT 4
249: ULONG dumpData[DUMP_COUNT];
250:
251: MouPrint((1,"\n\nMOUCLASS-MouseClassInitialize: enter\n"));
252:
253: //
254: // Zero-initialize various structures.
255: //
256:
257: RtlZeroMemory(&tmpDeviceExtension, sizeof(DEVICE_EXTENSION));
258:
259: fullClassName.MaximumLength = 0;
260: fullPortName.MaximumLength = 0;
261: deviceNameSuffix.MaximumLength = 0;
262: registryPath.MaximumLength = 0;
263:
264: RtlZeroMemory(baseClassBuffer, NAME_MAX * sizeof(WCHAR));
265: baseClassName.Buffer = baseClassBuffer;
266: baseClassName.Length = 0;
267: baseClassName.MaximumLength = NAME_MAX * sizeof(WCHAR);
268:
269: RtlZeroMemory(basePortBuffer, NAME_MAX * sizeof(WCHAR));
270: basePortName.Buffer = basePortBuffer;
271: basePortName.Length = 0;
272: basePortName.MaximumLength = NAME_MAX * sizeof(WCHAR);
273:
274: //
275: // Need to ensure that the registry path is null-terminated.
276: // Allocate pool to hold a null-terminated copy of the path.
277: //
278:
279: registryPath.Buffer = ExAllocatePool(
280: PagedPool,
281: RegistryPath->Length + sizeof(UNICODE_NULL)
282: );
283:
284: if (!registryPath.Buffer) {
285: MouPrint((
286: 1,
287: "MOUCLASS-MouseClassInitialize: Couldn't allocate pool for registry path\n"
288: ));
289:
290: status = STATUS_UNSUCCESSFUL;
291: errorCode = MOUCLASS_INSUFFICIENT_RESOURCES;
292: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 2;
293: dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL);
294: dumpCount = 1;
295: goto MouseClassInitializeExit;
296:
297: } else {
298:
299: registryPath.Length = RegistryPath->Length;
300: registryPath.MaximumLength =
301: registryPath.Length + sizeof(UNICODE_NULL);
302:
303: RtlZeroMemory(
304: registryPath.Buffer,
305: registryPath.MaximumLength
306: );
307:
308: RtlMoveMemory(
309: registryPath.Buffer,
310: RegistryPath->Buffer,
311: RegistryPath->Length
312: );
313:
314: }
315:
316: //
317: // Get the configuration information for this driver.
318: //
319:
320: MouConfiguration(&tmpDeviceExtension, ®istryPath, &baseClassName);
321:
322: //
323: // Set up space for the class's device object suffix. Note that
324: // we overallocate space for the suffix string because it is much
325: // easier than figuring out exactly how much space is required.
326: // The storage gets freed at the end of driver initialization, so
327: // who cares...
328: //
329:
330: RtlInitUnicodeString(&deviceNameSuffix, NULL);
331:
332: deviceNameSuffix.MaximumLength = POINTER_PORTS_MAXIMUM * sizeof(WCHAR);
333: deviceNameSuffix.MaximumLength += sizeof(UNICODE_NULL);
334:
335: deviceNameSuffix.Buffer = ExAllocatePool(
336: PagedPool,
337: deviceNameSuffix.MaximumLength
338: );
339:
340: if (!deviceNameSuffix.Buffer) {
341:
342: MouPrint((
343: 1,
344: "MOUCLASS-MouseClassInitialize: Couldn't allocate string for device object suffix\n"
345: ));
346:
347: status = STATUS_UNSUCCESSFUL;
348: errorCode = MOUCLASS_INSUFFICIENT_RESOURCES;
349: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 4;
350: dumpData[0] = (ULONG) deviceNameSuffix.MaximumLength;
351: dumpCount = 1;
352: goto MouseClassInitializeExit;
353:
354: }
355:
356: RtlZeroMemory(deviceNameSuffix.Buffer, deviceNameSuffix.MaximumLength);
357:
358: //
359: // Set up space for the class's full device object name.
360: //
361:
362: RtlInitUnicodeString(&fullClassName, NULL);
363:
364: fullClassName.MaximumLength = sizeof(L"\\Device\\") +
365: baseClassName.Length +
366: deviceNameSuffix.MaximumLength;
367:
368:
369: fullClassName.Buffer = ExAllocatePool(
370: PagedPool,
371: fullClassName.MaximumLength
372: );
373:
374: if (!fullClassName.Buffer) {
375:
376: MouPrint((
377: 1,
378: "MOUCLASS-MouseClassInitialize: Couldn't allocate string for device object name\n"
379: ));
380:
381: status = STATUS_UNSUCCESSFUL;
382: errorCode = MOUCLASS_INSUFFICIENT_RESOURCES;
383: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 6;
384: dumpData[0] = (ULONG) fullClassName.MaximumLength;
385: dumpCount = 1;
386: goto MouseClassInitializeExit;
387:
388: }
389:
390: RtlZeroMemory(fullClassName.Buffer, fullClassName.MaximumLength);
391: RtlAppendUnicodeToString(&fullClassName, L"\\Device\\");
392: RtlAppendUnicodeToString(&fullClassName, baseClassName.Buffer);
393:
394: //
395: // Set up the base device name for the associated port device.
396: // It is the same as the base class name, with "Class" replaced
397: // by "Port".
398: //
399:
400: RtlCopyUnicodeString(&basePortName, &baseClassName);
401:
402: basePortName.Length -= (sizeof(L"Class") - sizeof(UNICODE_NULL));
403:
404: RtlAppendUnicodeToString(&basePortName, L"Port");
405:
406: //
407: // Determine how many ports this class driver is to service.
408: //
409:
410: status = MouDeterminePortsServiced(&basePortName, &i);
411:
412: if (NT_SUCCESS(status)) {
413: if (i < tmpDeviceExtension.MaximumPortsServiced)
414: tmpDeviceExtension.MaximumPortsServiced = i;
415: }
416:
417: status = STATUS_SUCCESS;
418:
419: MouPrint((
420: 1,
421: "MOUCLASS-MouseClassInitialize: Will service %d port devices\n",
422: tmpDeviceExtension.MaximumPortsServiced
423: ));
424:
425: //
426: // Set up space for the full device object name for the ports.
427: //
428:
429: RtlInitUnicodeString(&fullPortName, NULL);
430:
431: fullPortName.MaximumLength = sizeof(L"\\Device\\") +
432: basePortName.Length +
433: deviceNameSuffix.MaximumLength;
434:
435: fullPortName.Buffer = ExAllocatePool(
436: PagedPool,
437: fullPortName.MaximumLength
438: );
439:
440: if (!fullPortName.Buffer) {
441:
442: MouPrint((
443: 1,
444: "MOUCLASS-MouseClassInitialize: Couldn't allocate string for port device object name\n"
445: ));
446:
447: status = STATUS_UNSUCCESSFUL;
448: errorCode = MOUCLASS_INSUFFICIENT_RESOURCES;
449: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 8;
450: dumpData[0] = (ULONG) fullPortName.MaximumLength;
451: dumpCount = 1;
452: goto MouseClassInitializeExit;
453:
454: }
455:
456: RtlZeroMemory(fullPortName.Buffer, fullPortName.MaximumLength);
457: RtlAppendUnicodeToString(&fullPortName, L"\\Device\\");
458: RtlAppendUnicodeToString(&fullPortName, basePortName.Buffer);
459:
460: //
461: // Allocate memory for the port device object pointer list.
462: //
463:
464: (PDEVICE_OBJECT *) tmpDeviceExtension.PortDeviceObjectList =
465: ExAllocatePool(
466: NonPagedPool,
467: sizeof(PDEVICE_OBJECT) * tmpDeviceExtension.MaximumPortsServiced
468: );
469:
470: if (!tmpDeviceExtension.PortDeviceObjectList) {
471:
472: //
473: // Could not allocate memory for the port device object pointers.
474: //
475:
476: MouPrint((
477: 1,
478: "MOUCLASS-MouseClassInitialize: Could not allocate PortDeviceObjectList for %ws\n",
479: fullClassName.Buffer
480: ));
481:
482: status = STATUS_INSUFFICIENT_RESOURCES;
483: errorCode = MOUCLASS_INSUFFICIENT_RESOURCES;
484: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 10;
485: dumpData[0] = (ULONG) (sizeof(PDEVICE_OBJECT) * tmpDeviceExtension.MaximumPortsServiced);
486: dumpData[1] = (ULONG) tmpDeviceExtension.MaximumPortsServiced;
487: dumpCount = 2;
488:
489: goto MouseClassInitializeExit;
490: }
491:
492: //
493: // Set up the class device object(s) to handle the associated
494: // port devices.
495: //
496:
497: portConnectionSuccessful = 0;
498:
499:
500: for (i = 0; i < tmpDeviceExtension.MaximumPortsServiced; i++) {
501:
502: //
503: // Append the suffix to the device object name string. E.g., turn
504: // \Device\PointerClass into \Device\PointerClass0. Then attempt
505: // to create the device object. If the device object already
506: // exists increment the suffix and try again.
507: //
508:
509: status = RtlIntegerToUnicodeString(
510: i,
511: 10,
512: &deviceNameSuffix
513: );
514:
515: if (!NT_SUCCESS(status)) {
516: continue;
517: }
518:
519: RtlAppendUnicodeStringToString(
520: &fullClassName,
521: &deviceNameSuffix
522: );
523:
524: RtlAppendUnicodeStringToString(
525: &fullPortName,
526: &deviceNameSuffix
527: );
528:
529: //
530: // Create the class device object.
531: //
532:
533: if (tmpDeviceExtension.ConnectOneClassToOnePort
534: || (classDeviceObject == NULL)) {
535: classDeviceObject = NULL;
536: status = MouCreateClassObject(
537: DriverObject,
538: &tmpDeviceExtension,
539: ®istryPath,
540: &fullClassName,
541: &baseClassName,
542: &classDeviceObject
543: );
544: }
545:
546: //
547: // Connect to the port device.
548: //
549:
550: if (NT_SUCCESS(status)) {
551: status = MouConnectToPort(
552: classDeviceObject,
553: &fullPortName,
554: i
555: );
556: }
557:
558: if (NT_SUCCESS(status)) {
559:
560: portConnectionSuccessful += 1;
561:
562: if (tmpDeviceExtension.ConnectOneClassToOnePort
563: || (portConnectionSuccessful == 1)) {
564:
565: //
566: // Load the device map information into the registry so
567: // that setup can determine which mouse class driver is active.
568: //
569:
570: status = RtlWriteRegistryValue(
571: RTL_REGISTRY_DEVICEMAP,
572: baseClassName.Buffer,
573: fullClassName.Buffer,
574: REG_SZ,
575: registryPath.Buffer,
576: registryPath.Length + sizeof(UNICODE_NULL)
577: );
578:
579: if (!NT_SUCCESS(status)) {
580:
581: MouPrint((
582: 1,
583: "MOUCLASS-MouseClassInitialize: Could not store %ws in DeviceMap\n",
584: fullClassName.Buffer
585: ));
586:
587:
588: //
589: // Stop making connections, and log an error.
590: //
591:
592: errorCode = MOUCLASS_NO_DEVICEMAP_CREATED;
593: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 14;
594: dumpCount = 0;
595:
596: //
597: // N.B. 'break' should cause execution to
598: // go to KeyboardClassInitializeExit (otherwise
599: // do an explicit 'goto').
600: //
601:
602: break;
603:
604: } else {
605:
606: MouPrint((
607: 1,
608: "MOUCLASS-MouseClassInitialize: Stored %ws in DeviceMap\n",
609: fullClassName.Buffer
610: ));
611: }
612: }
613:
614: //
615: // Try the next one.
616: //
617:
618: fullClassName.Length -= deviceNameSuffix.Length;
619: fullPortName.Length -= deviceNameSuffix.Length;
620:
621: } else if (tmpDeviceExtension.ConnectOneClassToOnePort) {
622:
623: //
624: // Stop doing 1:1 class-port connections if there is
625: // a failure.
626: //
627: // Note that if we are doing 1:many class-port connections
628: // and we encounter an error, we continue to try to connect
629: // to port devices.
630: //
631:
632: break;
633: }
634:
635: }
636:
637: if (!portConnectionSuccessful) {
638:
639: //
640: // The class driver was unable to connect to any port devices.
641: // Log a warning message.
642: //
643:
644: errorCode = MOUCLASS_NO_PORT_DEVICE_OBJECT;
645: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 18;
646:
647: }
648:
649: MouseClassInitializeExit:
650:
651: if (errorCode != STATUS_SUCCESS) {
652:
653: //
654: // The initialization failed in some way. Log an error.
655: //
656:
657: errorLogEntry = (PIO_ERROR_LOG_PACKET)
658: IoAllocateErrorLogEntry(
659: (classDeviceObject == NULL) ?
660: (PVOID) DriverObject : (PVOID) classDeviceObject,
661: (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
662: + (dumpCount * sizeof(ULONG)))
663: );
664:
665: if (errorLogEntry != NULL) {
666:
667: errorLogEntry->ErrorCode = errorCode;
668: errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
669: errorLogEntry->SequenceNumber = 0;
670: errorLogEntry->MajorFunctionCode = 0;
671: errorLogEntry->IoControlCode = 0;
672: errorLogEntry->RetryCount = 0;
673: errorLogEntry->UniqueErrorValue = uniqueErrorValue;
674: errorLogEntry->FinalStatus = status;
675: for (i = 0; i < dumpCount; i++)
676: errorLogEntry->DumpData[i] = dumpData[i];
677:
678: IoWriteErrorLogEntry(errorLogEntry);
679: }
680: }
681:
682: //
683: // Free the unicode strings.
684: //
685:
686: if (deviceNameSuffix.MaximumLength != 0)
687: ExFreePool(deviceNameSuffix.Buffer);
688: if (fullClassName.MaximumLength != 0)
689: ExFreePool(fullClassName.Buffer);
690: if (fullPortName.MaximumLength != 0)
691: ExFreePool(fullPortName.Buffer);
692: if (registryPath.MaximumLength != 0)
693: ExFreePool(registryPath.Buffer);
694:
695: if ((tmpDeviceExtension.ConnectOneClassToOnePort
696: && (!NT_SUCCESS(status))) ||
697: !portConnectionSuccessful) {
698:
699: //
700: // Clean up leftover resources. If we're doing 1:1 class-port
701: // connections, then we may have created a class device object
702: // for which the connect failed. If we're doing 1:many
703: // connections, we may have created a class device object but
704: // failed to make ANY connections. In either case, we
705: // free the ring buffer and delete the class device object.
706: //
707:
708: if (classDeviceObject) {
709: deviceExtension =
710: (PDEVICE_EXTENSION) classDeviceObject->DeviceExtension;
711: if ((deviceExtension) && (deviceExtension->InputData))
712: ExFreePool(deviceExtension->InputData);
713: IoDeleteDevice(classDeviceObject);
714: }
715: }
716:
717: //
718: // If we successfully connected to at least one pointer port device,
719: // this driver's initialization was successful.
720: //
721:
722: if (portConnectionSuccessful) {
723:
724: //
725: // Set up the device driver entry points.
726: //
727:
728: DriverObject->DriverStartIo = MouseClassStartIo;
729: DriverObject->MajorFunction[IRP_MJ_CREATE] = MouseClassOpenClose;
730: DriverObject->MajorFunction[IRP_MJ_CLOSE] = MouseClassOpenClose;
731: DriverObject->MajorFunction[IRP_MJ_READ] = MouseClassRead;
732: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] =
733: MouseClassFlush;
734: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
735: MouseClassDeviceControl;
736: DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MouseClassCleanup;
737:
738: //
739: // NOTE: Don't allow this driver to unload. Otherwise, we would set
740: // DriverObject->DriverUnload = MouseClassUnload.
741: //
742:
743: status = STATUS_SUCCESS;
744: }
745:
746: MouPrint((1,"MOUCLASS-MouseClassInitialize: exit\n"));
747:
748: return(status);
749:
750: }
751:
752: VOID
753: MouseClassCancel(
754: IN PDEVICE_OBJECT DeviceObject,
755: IN PIRP Irp
756: )
757:
758: /*++
759:
760: Routine Description:
761:
762: This routine is the class cancellation routine. It is
763: called from the I/O system when a request is cancelled. Read requests
764: are currently the only cancellable requests.
765:
766: N.B. The cancel spinlock is already held upon entry to this routine.
767:
768: Arguments:
769:
770: DeviceObject - Pointer to class device object.
771:
772: Irp - Pointer to the request packet to be cancelled.
773:
774: Return Value:
775:
776: None.
777:
778: --*/
779:
780: {
781: PDEVICE_EXTENSION deviceExtension;
782: KIRQL currentIrql;
783: KIRQL cancelIrql;
784:
785: MouPrint((2,"MOUCLASS-MouseClassCancel: enter\n"));
786:
787: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
788:
789: //
790: // Release the cancel spinlock and grab the mouse class spinlock (it
791: // protects the RequestIsPending flag).
792: //
793:
794: IoReleaseCancelSpinLock(Irp->CancelIrql);
795: KeAcquireSpinLock(&deviceExtension->SpinLock, ¤tIrql);
796:
797: if ((deviceExtension->RequestIsPending)
798: && (Irp == DeviceObject->CurrentIrp)) {
799:
800: //
801: // The current request is being cancelled. Set the CurrentIrp to
802: // null, clear the RequestIsPending flag, and release the mouse class
803: // spinlock before starting the next packet.
804: //
805:
806: DeviceObject->CurrentIrp = NULL;
807: deviceExtension->RequestIsPending = FALSE;
808: KeReleaseSpinLock(&deviceExtension->SpinLock, currentIrql);
809: IoStartNextPacket(DeviceObject, TRUE);
810: } else {
811:
812: //
813: // Cancel a request in the device queue. Reacquire the cancel
814: // spinlock, remove the request from the queue, and release the
815: // cancel spinlock. Release the mouse class spinlock.
816: //
817:
818: IoAcquireCancelSpinLock(&cancelIrql);
819: if (TRUE != KeRemoveEntryDeviceQueue(
820: &DeviceObject->DeviceQueue,
821: &Irp->Tail.Overlay.DeviceQueueEntry
822: )) {
823: MouPrint((
824: 1,
825: "MOUCLASS-MouseClassCancel: Irp 0x%x not in device queue?!?\n",
826: Irp
827: ));
828: }
829: IoReleaseCancelSpinLock(cancelIrql);
830: KeReleaseSpinLock(&deviceExtension->SpinLock, currentIrql);
831: }
832:
833: //
834: // Complete the request with STATUS_CANCELLED.
835: //
836:
837: Irp->IoStatus.Status = STATUS_CANCELLED;
838: Irp->IoStatus.Information = 0;
839: IoCompleteRequest (Irp, IO_MOUSE_INCREMENT);
840:
841: MouPrint((2,"MOUCLASS-MouseClassCancel: exit\n"));
842:
843: return;
844: }
845:
846: NTSTATUS
847: MouseClassCleanup(
848: IN PDEVICE_OBJECT DeviceObject,
849: IN PIRP Irp
850: )
851:
852: /*++
853:
854: Routine Description:
855:
856: This routine is the dispatch routine for cleanup requests.
857: All requests queued to the mouse class device (on behalf of
858: the thread for whom the cleanup request was generated) are
859: completed with STATUS_CANCELLED.
860:
861: Arguments:
862:
863: DeviceObject - Pointer to class device object.
864:
865: Irp - Pointer to the request packet.
866:
867: Return Value:
868:
869: Status is returned.
870:
871: --*/
872:
873: {
874: KIRQL spinlockIrql;
875: KIRQL cancelIrql;
876: PDEVICE_EXTENSION deviceExtension;
877: PKDEVICE_QUEUE_ENTRY packet;
878: PIRP currentIrp = NULL;
879: PIO_STACK_LOCATION irpSp;
880:
881: MouPrint((2,"MOUCLASS-MouseClassCleanup: enter\n"));
882:
883: deviceExtension = DeviceObject->DeviceExtension;
884:
885: //
886: // Acquire the mouse class spinlock and the cancel spinlock.
887: //
888:
889: KeAcquireSpinLock(&deviceExtension->SpinLock, &spinlockIrql);
890: IoAcquireCancelSpinLock(&cancelIrql);
891:
892: //
893: // Get a pointer to the current stack location for this request.
894: //
895:
896: irpSp = IoGetCurrentIrpStackLocation(Irp);
897:
898: //
899: // If the file object's FsContext is non-null, then the cleanup
900: // request is being executed by the trusted subsystem. Since the
901: // trusted subsystem is the only one with sufficient privilege to make
902: // Read requests to the driver, and since only Read requests get queued
903: // to the device queue, a cleanup request from the trusted subsystem is
904: // handled by cancelling all queued requests.
905: //
906: // If the FsContext is null, there is no cleanup work to perform
907: // (only read requests can be cancelled).
908: //
909: // NOTE: If this driver is to allow more than one trusted subsystem
910: // to make read requests to the same device object some day in
911: // the future, then there needs to be a mechanism that
912: // allows Cleanup to remove only those queued requests that
913: // were made by threads using the same FileObject as the
914: // file object in the Cleanup request.
915: //
916:
917: if (irpSp->FileObject->FsContext) {
918:
919: //
920: // Indicate that the cleanup routine has been called (StartIo cares
921: // about this).
922: //
923:
924: deviceExtension->CleanupWasInitiated = TRUE;
925:
926: //
927: // Complete all requests queued by this thread with STATUS_CANCELLED.
928: // Start with the real CurrentIrp, and run down the list of requests
929: // in the device queue. Be sure to set the real CurrentIrp to NULL
930: // and the RequestIsPending flag to FALSE, so that the class
931: // service callback routine won't attempt to complete CurrentIrp.
932: // Note that we can really only trust CurrentIrp when RequestIsPending.
933: //
934:
935: currentIrp = DeviceObject->CurrentIrp;
936: DeviceObject->CurrentIrp = NULL;
937: deviceExtension->RequestIsPending = FALSE;
938:
939: while (currentIrp != NULL) {
940:
941: //
942: // Remove the CurrentIrp from the cancellable state.
943: //
944: //
945:
946: IoSetCancelRoutine(currentIrp, NULL);
947:
948: //
949: // Set Status to CANCELLED, release the spinlocks,
950: // and complete the request. Note that the IRQL is reset to
951: // DISPATCH_LEVEL when we release the spinlocks.
952: //
953:
954: currentIrp->IoStatus.Status = STATUS_CANCELLED;
955: currentIrp->IoStatus.Information = 0;
956:
957: IoReleaseCancelSpinLock(cancelIrql);
958: KeReleaseSpinLock(&deviceExtension->SpinLock, spinlockIrql);
959: IoCompleteRequest(currentIrp, IO_MOUSE_INCREMENT);
960:
961: //
962: // Reacquire the spinlocks.
963: //
964:
965: KeAcquireSpinLock(&deviceExtension->SpinLock, &spinlockIrql);
966: IoAcquireCancelSpinLock(&cancelIrql);
967:
968: //
969: // Dequeue the next packet (IRP) from the device work queue.
970: //
971:
972: packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
973: if (packet != NULL) {
974: currentIrp =
975: CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry);
976: } else {
977: currentIrp = (PIRP) NULL;
978: }
979:
980: } // end while
981: }
982:
983: //
984: // Release the spinlocks and lower IRQL.
985: //
986:
987: IoReleaseCancelSpinLock(cancelIrql);
988: KeReleaseSpinLock(&deviceExtension->SpinLock, spinlockIrql);
989:
990: //
991: // Complete the cleanup request with STATUS_SUCCESS.
992: //
993:
994: Irp->IoStatus.Status = STATUS_SUCCESS;
995: Irp->IoStatus.Information = 0;
996: IoCompleteRequest (Irp, IO_NO_INCREMENT);
997:
998: MouPrint((2,"MOUCLASS-MouseClassCleanup: exit\n"));
999:
1000: return(STATUS_SUCCESS);
1001:
1002: }
1003:
1004: NTSTATUS
1005: MouseClassDeviceControl(
1006: IN PDEVICE_OBJECT DeviceObject,
1007: IN PIRP Irp
1008: )
1009:
1010: /*++
1011:
1012: Routine Description:
1013:
1014: This routine is the dispatch routine for device control requests.
1015: All device control subfunctions are passed, asynchronously, to the
1016: connected port driver for processing and completion.
1017:
1018: Arguments:
1019:
1020: DeviceObject - Pointer to class device object.
1021:
1022: Irp - Pointer to the request packet.
1023:
1024: Return Value:
1025:
1026: Status is returned.
1027:
1028: --*/
1029:
1030: {
1031: PIO_STACK_LOCATION irpSp;
1032: PIO_STACK_LOCATION nextSp;
1033: PDEVICE_EXTENSION deviceExtension;
1034: NTSTATUS status = STATUS_SUCCESS;
1035: ULONG unitId;
1036:
1037: MouPrint((2,"MOUCLASS-MouseClassDeviceControl: enter\n"));
1038:
1039: //
1040: // Get a pointer to the device extension.
1041: //
1042:
1043: deviceExtension = DeviceObject->DeviceExtension;
1044:
1045: //
1046: // Get a pointer to the current parameters for this request. The
1047: // information is contained in the current stack location.
1048: //
1049:
1050: irpSp = IoGetCurrentIrpStackLocation(Irp);
1051:
1052: //
1053: // Check for adequate input buffer length. The input buffer
1054: // should, at a minimum, contain the unit ID specifying one of
1055: // the connected port devices. If there is no input buffer (i.e.,
1056: // the input buffer length is zero), then we assume the unit ID
1057: // is zero (for backwards compatibility).
1058: //
1059:
1060: if (irpSp->Parameters.DeviceIoControl.InputBufferLength == 0) {
1061: unitId = 0;
1062: } else if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
1063: sizeof(MOUSE_UNIT_ID_PARAMETER)) {
1064: status = STATUS_BUFFER_TOO_SMALL;
1065:
1066: } else {
1067: unitId = ((PMOUSE_UNIT_ID_PARAMETER)
1068: Irp->AssociatedIrp.SystemBuffer)->UnitId;
1069: if (unitId >= deviceExtension->MaximumPortsServiced) {
1070: status = STATUS_INVALID_PARAMETER;
1071: }
1072: }
1073:
1074: if (NT_SUCCESS(status)) {
1075:
1076: //
1077: // Pass the device control request on to the port driver,
1078: // asynchronously. Get the next IRP stack location and copy the
1079: // input parameters to the next stack location. Change the major
1080: // function to internal device control.
1081: //
1082:
1083: nextSp = IoGetNextIrpStackLocation(Irp);
1084: ASSERT(nextSp != NULL);
1085: nextSp->Parameters.DeviceIoControl =
1086: irpSp->Parameters.DeviceIoControl;
1087: nextSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
1088:
1089: //
1090: // Mark the packet pending.
1091: //
1092:
1093: IoMarkIrpPending(Irp);
1094:
1095: //
1096: // Pass the IRP on to the connected port device (specified by
1097: // the unit ID). The port device driver will process the request.
1098: //
1099:
1100: status = IoCallDriver(
1101: deviceExtension->PortDeviceObjectList[unitId],
1102: Irp
1103: );
1104: } else {
1105:
1106: //
1107: // Complete the request.
1108: //
1109:
1110: Irp->IoStatus.Status = status;
1111: Irp->IoStatus.Information = 0;
1112: IoCompleteRequest(Irp, IO_NO_INCREMENT);
1113: }
1114:
1115: MouPrint((2,"MOUCLASS-MouseClassDeviceControl: exit\n"));
1116:
1117: return(status);
1118:
1119: }
1120:
1121: NTSTATUS
1122: MouseClassFlush(
1123: IN PDEVICE_OBJECT DeviceObject,
1124: IN PIRP Irp
1125: )
1126:
1127: /*++
1128:
1129: Routine Description:
1130:
1131: This routine is the dispatch routine for flush requests. The class
1132: input data queue is reinitialized.
1133:
1134: Arguments:
1135:
1136: DeviceObject - Pointer to class device object.
1137:
1138: Irp - Pointer to the request packet.
1139:
1140: Return Value:
1141:
1142: Status is returned.
1143:
1144: --*/
1145:
1146: {
1147: PDEVICE_EXTENSION deviceExtension;
1148: NTSTATUS status = STATUS_SUCCESS;
1149:
1150: MouPrint((2,"MOUCLASS-MouseClassFlush: enter\n"));
1151:
1152: //
1153: // Get a pointer to the device extension.
1154: //
1155:
1156: deviceExtension = DeviceObject->DeviceExtension;
1157:
1158: //
1159: // Initialize mouse class input data queue.
1160: //
1161:
1162: MouInitializeDataQueue((PVOID)deviceExtension);
1163:
1164: //
1165: // Complete the request and return status.
1166: //
1167:
1168: Irp->IoStatus.Status = status;
1169: Irp->IoStatus.Information = 0;
1170: IoCompleteRequest(Irp, IO_NO_INCREMENT);
1171:
1172: MouPrint((2,"MOUCLASS-MouseClassFlush: exit\n"));
1173:
1174: return(status);
1175:
1176: } // end MouseClassFlush
1177:
1178: NTSTATUS
1179: MouseClassOpenClose(
1180: IN PDEVICE_OBJECT DeviceObject,
1181: IN PIRP Irp
1182: )
1183:
1184: /*++
1185:
1186: Routine Description:
1187:
1188: This routine is the dispatch routine for create/open and close requests.
1189: Open/close requests are completed here.
1190:
1191: Arguments:
1192:
1193: DeviceObject - Pointer to class device object.
1194:
1195: Irp - Pointer to the request packet.
1196:
1197: Return Value:
1198:
1199: Status is returned.
1200:
1201: --*/
1202:
1203: {
1204: PIO_STACK_LOCATION irpSp;
1205: PDEVICE_EXTENSION deviceExtension;
1206: KIRQL oldIrql;
1207: BOOLEAN enableFlag = FALSE;
1208: NTSTATUS status = STATUS_SUCCESS;
1209: PIO_ERROR_LOG_PACKET errorLogEntry;
1210: BOOLEAN SomeEnableDisableSucceeded = FALSE;
1211: ULONG i;
1212:
1213: MouPrint((2,"MOUCLASS-MouseClassOpenClose: enter\n"));
1214:
1215: //
1216: // Get a pointer to the device extension.
1217: //
1218:
1219: deviceExtension = DeviceObject->DeviceExtension;
1220:
1221: //
1222: // Get a pointer to the current parameters for this request. The
1223: // information is contained in the current stack location.
1224: //
1225:
1226: irpSp = IoGetCurrentIrpStackLocation(Irp);
1227:
1228: //
1229: // Case on the function that is being performed by the requestor.
1230: //
1231:
1232: switch (irpSp->MajorFunction) {
1233:
1234: //
1235: // For the create/open operation, send a MOUSE_ENABLE internal
1236: // device control request to the port driver to enable interrupts.
1237: //
1238:
1239: case IRP_MJ_CREATE:
1240:
1241: //
1242: // First, if the requestor is the trusted subsystem (the single
1243: // reader), reset the the cleanup indicator and set the file
1244: // object's FsContext to non-null (MouseClassRead uses
1245: // FsContext to determine if the requestor has sufficient
1246: // privilege to perform the read operation).
1247: //
1248:
1249: if (SeSinglePrivilegeCheck(RtlConvertLongToLargeInteger(
1250: SE_TCB_PRIVILEGE),
1251: Irp->RequestorMode
1252: )) {
1253:
1254: KeAcquireSpinLock(&deviceExtension->SpinLock, &oldIrql);
1255: deviceExtension->CleanupWasInitiated = FALSE;
1256: irpSp->FileObject->FsContext = (PVOID) 1;
1257: KeReleaseSpinLock(&deviceExtension->SpinLock, oldIrql);
1258: }
1259:
1260: enableFlag = TRUE;
1261:
1262: break;
1263:
1264: //
1265: // For the close operation, send a MOUSE_DISABLE internal device
1266: // control request to the port driver to disable interrupts.
1267: //
1268:
1269: case IRP_MJ_CLOSE:
1270:
1271: break;
1272: }
1273:
1274: //
1275: // Enable/disable interrupts via port driver.
1276: //
1277:
1278: for (i = 0; i < deviceExtension->MaximumPortsServiced; i++) {
1279:
1280: status = MouEnableDisablePort(DeviceObject, enableFlag, i);
1281:
1282: if (status != STATUS_SUCCESS) {
1283:
1284: MouPrint((
1285: 0,
1286: "MOUCLASS-MouseClassOpenClose: Could not enable/disable interrupts for port device object @ 0x%x\n",
1287: deviceExtension->PortDeviceObjectList[i]
1288: ));
1289:
1290: //
1291: // Log an error.
1292: //
1293:
1294: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1295: DeviceObject,
1296: sizeof(IO_ERROR_LOG_PACKET)
1297: );
1298:
1299: if (errorLogEntry != NULL) {
1300:
1301: errorLogEntry->ErrorCode =
1302: enableFlag? MOUCLASS_PORT_INTERRUPTS_NOT_ENABLED:
1303: MOUCLASS_PORT_INTERRUPTS_NOT_DISABLED;
1304: errorLogEntry->SequenceNumber = 0;
1305: errorLogEntry->MajorFunctionCode = irpSp->MajorFunction;
1306: errorLogEntry->IoControlCode = 0;
1307: errorLogEntry->RetryCount = 0;
1308: errorLogEntry->UniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 120;
1309: errorLogEntry->FinalStatus = status;
1310:
1311: IoWriteErrorLogEntry(errorLogEntry);
1312: }
1313:
1314: } else {
1315: SomeEnableDisableSucceeded = TRUE;
1316: }
1317: }
1318:
1319: //
1320: // Complete the request and return status.
1321: //
1322: // NOTE: We complete the request successfully if any one of the
1323: // connected port devices successfully handled the request.
1324: // The RIT only knows about one pointing device.
1325: //
1326:
1327: if (SomeEnableDisableSucceeded) {
1328: status = STATUS_SUCCESS;
1329: }
1330:
1331: Irp->IoStatus.Status = status;
1332: Irp->IoStatus.Information = 0;
1333: IoCompleteRequest(Irp, IO_NO_INCREMENT);
1334:
1335: MouPrint((2,"MOUCLASS-MouseClassOpenClose: exit\n"));
1336:
1337: return(status);
1338: }
1339:
1340: NTSTATUS
1341: MouseClassRead(
1342: IN PDEVICE_OBJECT DeviceObject,
1343: IN PIRP Irp
1344: )
1345:
1346: /*++
1347:
1348: Routine Description:
1349:
1350: This routine is the dispatch routine for read requests. Valid read
1351: requests are marked pending, and started via IoStartPacket.
1352:
1353: Arguments:
1354:
1355: DeviceObject - Pointer to class device object.
1356:
1357: Irp - Pointer to the request packet.
1358:
1359: Return Value:
1360:
1361: Status is returned.
1362:
1363: --*/
1364:
1365: {
1366: NTSTATUS status;
1367: PIO_STACK_LOCATION irpSp;
1368:
1369: MouPrint((2,"MOUCLASS-MouseClassRead: enter\n"));
1370:
1371: irpSp = IoGetCurrentIrpStackLocation(Irp);
1372:
1373: //
1374: // Validate the read request parameters. The read length should be an
1375: // integral number of MOUSE_INPUT_DATA structures.
1376: //
1377:
1378:
1379: if (irpSp->Parameters.Read.Length == 0) {
1380: status = STATUS_SUCCESS;
1381: }
1382: else if (irpSp->Parameters.Read.Length % sizeof(MOUSE_INPUT_DATA)) {
1383: status = STATUS_BUFFER_TOO_SMALL;
1384: }
1385: else if (irpSp->FileObject->FsContext) {
1386:
1387: //
1388: // If the file object's FsContext is non-null, then we've already
1389: // done the Read privilege check once before for this thread. Skip
1390: // the privilege check.
1391: //
1392:
1393: status = STATUS_PENDING;
1394: }
1395: else {
1396:
1397: //
1398: // We only allow a trusted subsystem with the appropriate privilege
1399: // level to execute a Read call.
1400: //
1401:
1402: status = STATUS_PRIVILEGE_NOT_HELD;
1403:
1404:
1405: }
1406:
1407: //
1408: // If status is pending, mark the packet pending and start the packet
1409: // in a cancellable state. Otherwise, complete the request.
1410: //
1411:
1412: Irp->IoStatus.Status = status;
1413: Irp->IoStatus.Information = 0;
1414: if (status == STATUS_PENDING) {
1415: IoMarkIrpPending(Irp);
1416: IoStartPacket(DeviceObject, Irp, (PULONG)NULL, MouseClassCancel);
1417: } else {
1418: IoCompleteRequest(Irp, IO_NO_INCREMENT);
1419: }
1420:
1421: MouPrint((2,"MOUCLASS-MouseClassRead: exit\n"));
1422:
1423: return(status);
1424:
1425: }
1426:
1427: VOID
1428: MouseClassServiceCallback(
1429: IN PDEVICE_OBJECT DeviceObject,
1430: IN PMOUSE_INPUT_DATA InputDataStart,
1431: IN PMOUSE_INPUT_DATA InputDataEnd,
1432: IN OUT PULONG InputDataConsumed
1433: )
1434:
1435: /*++
1436:
1437: Routine Description:
1438:
1439: This routine is the class service callback routine. It is
1440: called from the port driver's interrupt service DPC. If there is an
1441: outstanding read request, the request is satisfied from the port input
1442: data queue. Unsolicited mouse input is moved from the port input
1443: data queue to the class input data queue.
1444:
1445: N.B. This routine is entered at DISPATCH_LEVEL IRQL from the port
1446: driver's ISR DPC routine.
1447:
1448: Arguments:
1449:
1450: DeviceObject - Pointer to class device object.
1451:
1452: InputDataStart - Pointer to the start of the data in the port input
1453: data queue.
1454:
1455: InputDataEnd - Points one input data structure past the end of the
1456: valid port input data.
1457:
1458: InputDataConsumed - Pointer to storage in which the number of input
1459: data structures consumed by this call is returned.
1460:
1461: NOTE: Could pull the duplicate code out into a called procedure.
1462:
1463: Return Value:
1464:
1465: None.
1466:
1467: --*/
1468:
1469: {
1470: PDEVICE_EXTENSION deviceExtension;
1471: PIO_STACK_LOCATION irpSp;
1472: PIRP irp;
1473: KIRQL cancelIrql;
1474: ULONG bytesInQueue;
1475: ULONG bytesToMove;
1476: ULONG moveSize;
1477: BOOLEAN satisfiedPendingReadRequest = FALSE;
1478: PIO_ERROR_LOG_PACKET errorLogEntry;
1479:
1480: MouPrint((2,"MOUCLASS-MouseClassServiceCallback: enter\n"));
1481:
1482: deviceExtension = DeviceObject->DeviceExtension;
1483: bytesInQueue = (PCHAR) InputDataEnd - (PCHAR) InputDataStart;
1484: moveSize = 0;
1485: *InputDataConsumed = 0;
1486:
1487: //
1488: // Acquire the spinlock that protects the class device extension
1489: // (so we can look at RequestIsPending synchronously). If there is
1490: // a pending read request, satisfy it.
1491: //
1492: // N.B. We can use KeAcquireSpinLockAtDpcLevel, instead of
1493: // KeAcquireSpinLock, because this routine is already running
1494: // at DISPATCH_IRQL.
1495: //
1496:
1497: KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
1498:
1499: if (deviceExtension->RequestIsPending) {
1500:
1501: //
1502: // Acquire the cancel spinlock, remove the request from the
1503: // cancellable state, and free the cancel spinlock.
1504: //
1505:
1506: IoAcquireCancelSpinLock(&cancelIrql);
1507: irp = DeviceObject->CurrentIrp;
1508: IoSetCancelRoutine(irp, NULL);
1509: DeviceObject->CurrentIrp = NULL;
1510: IoReleaseCancelSpinLock(cancelIrql);
1511:
1512: //
1513: // An outstanding read request exists. Clear the RequestIsPending
1514: // flag to indicate there is no longer an outstanding read request
1515: // pending.
1516: //
1517:
1518: deviceExtension->RequestIsPending = FALSE;
1519:
1520: //
1521: // Copy as much of the input data possible from the port input
1522: // data queue to the SystemBuffer to satisfy the read.
1523: //
1524:
1525: irpSp = IoGetCurrentIrpStackLocation(irp);
1526: bytesToMove = irpSp->Parameters.Read.Length;
1527: moveSize = (bytesInQueue < bytesToMove) ?
1528: bytesInQueue:bytesToMove;
1529: *InputDataConsumed += (moveSize / sizeof(MOUSE_INPUT_DATA));
1530:
1531: MouPrint((
1532: 3,
1533: "MOUCLASS-MouseClassServiceCallback: port queue length 0x%lx, read length 0x%lx\n",
1534: bytesInQueue,
1535: bytesToMove
1536: ));
1537: MouPrint((
1538: 3,
1539: "MOUCLASS-MouseClassServiceCallback: number of bytes to move from port to SystemBuffer 0x%lx\n",
1540: moveSize
1541: ));
1542: MouPrint((
1543: 3,
1544: "MOUCLASS-MouseClassServiceCallback: move bytes from 0x%lx to 0x%lx\n",
1545: (PCHAR) InputDataStart,
1546: irp->AssociatedIrp.SystemBuffer
1547: ));
1548:
1549: RtlMoveMemory(
1550: irp->AssociatedIrp.SystemBuffer,
1551: (PCHAR) InputDataStart,
1552: moveSize
1553: );
1554:
1555: //
1556: // Set the flag so that we start the next packet and complete
1557: // this read request (with STATUS_SUCCESS) prior to return.
1558: //
1559:
1560: irp->IoStatus.Status = STATUS_SUCCESS;
1561: irp->IoStatus.Information = moveSize;
1562: irpSp->Parameters.Read.Length = moveSize;
1563: satisfiedPendingReadRequest = TRUE;
1564:
1565: }
1566:
1567: //
1568: // If there is still data in the port input data queue, move it to the class
1569: // input data queue.
1570: //
1571:
1572: InputDataStart = (PMOUSE_INPUT_DATA) ((PCHAR) InputDataStart + moveSize);
1573: moveSize = bytesInQueue - moveSize;
1574:
1575: MouPrint((
1576: 3,
1577: "MOUCLASS-MouseClassServiceCallback: bytes remaining after move to SystemBuffer 0x%lx\n",
1578: moveSize
1579: ));
1580:
1581: if (moveSize > 0) {
1582:
1583: //
1584: // Move the remaining data from the port input data queue to
1585: // the class input data queue. The move will happen in two
1586: // parts in the case where the class input data buffer wraps.
1587: //
1588:
1589: bytesInQueue =
1590: deviceExtension->MouseAttributes.InputDataQueueLength -
1591: (deviceExtension->InputCount * sizeof(MOUSE_INPUT_DATA));
1592: bytesToMove = moveSize;
1593:
1594: MouPrint((
1595: 3,
1596: "MOUCLASS-MouseClassServiceCallback: unused bytes in class queue 0x%lx, remaining bytes in port queue 0x%lx\n",
1597: bytesInQueue,
1598: bytesToMove
1599: ));
1600:
1601: if (bytesInQueue == 0) {
1602:
1603: //
1604: // Refuse to move any bytes that would cause a class input data
1605: // queue overflow. Just drop the bytes on the floor, and
1606: // log an overrun error.
1607: //
1608:
1609: MouPrint((
1610: 1,
1611: "MOUCLASS-MouseClassServiceCallback: Class input data queue OVERRUN\n"
1612: ));
1613:
1614: if (deviceExtension->OkayToLogOverflow) {
1615:
1616: //
1617: // Log an error.
1618: //
1619:
1620: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1621: DeviceObject,
1622: sizeof(IO_ERROR_LOG_PACKET)
1623: + (2 * sizeof(ULONG))
1624: );
1625:
1626: if (errorLogEntry != NULL) {
1627:
1628: errorLogEntry->ErrorCode = MOUCLASS_MOU_BUFFER_OVERFLOW;
1629: errorLogEntry->DumpDataSize = 2 * sizeof(ULONG);
1630: errorLogEntry->SequenceNumber = 0;
1631: errorLogEntry->MajorFunctionCode = 0;
1632: errorLogEntry->IoControlCode = 0;
1633: errorLogEntry->RetryCount = 0;
1634: errorLogEntry->UniqueErrorValue =
1635: MOUSE_ERROR_VALUE_BASE + 210;
1636: errorLogEntry->FinalStatus = 0;
1637: errorLogEntry->DumpData[0] = bytesToMove;
1638: errorLogEntry->DumpData[1] =
1639: deviceExtension->MouseAttributes.InputDataQueueLength;
1640:
1641: IoWriteErrorLogEntry(errorLogEntry);
1642: }
1643:
1644: deviceExtension->OkayToLogOverflow = FALSE;
1645: }
1646:
1647: } else {
1648:
1649: //
1650: // There is room in the class input data queue, so move
1651: // the remaining port input data to it.
1652: //
1653: // bytesToMove <- MIN(Number of unused bytes in class input data
1654: // queue, Number of bytes remaining in port
1655: // input queue).
1656: // This is the total number of bytes that actually will move from
1657: // the port input data queue to the class input data queue.
1658: //
1659:
1660:
1661: bytesToMove = (bytesInQueue < bytesToMove) ?
1662: bytesInQueue:bytesToMove;
1663:
1664: //
1665: // bytesInQueue <- Number of unused bytes from insertion pointer to
1666: // the end of the class input data queue (i.e., until the buffer
1667: // wraps).
1668: //
1669:
1670: bytesInQueue = ((PCHAR) deviceExtension->InputData +
1671: deviceExtension->MouseAttributes.InputDataQueueLength) -
1672: (PCHAR) deviceExtension->DataIn;
1673: MouPrint((
1674: 3,
1675: "MOUCLASS-MouseClassServiceCallback: total number of bytes to move to class queue 0x%lx\n",
1676: bytesToMove
1677: ));
1678:
1679: MouPrint((
1680: 3,
1681: "MOUCLASS-MouseClassServiceCallback: number of bytes to end of class buffer 0x%lx\n",
1682: bytesInQueue
1683: ));
1684:
1685: //
1686: // moveSize <- Number of bytes to handle in the first move.
1687: //
1688:
1689: moveSize = (bytesToMove < bytesInQueue) ?
1690: bytesToMove:bytesInQueue;
1691: MouPrint((
1692: 3,
1693: "MOUCLASS-MouseClassServiceCallback: number of bytes in first move to class 0x%lx\n",
1694: moveSize
1695: ));
1696:
1697: //
1698: // Do the move from the port data queue to the class data queue.
1699: //
1700:
1701: MouPrint((
1702: 3,
1703: "MOUCLASS-MouseClassServiceCallback: move bytes from 0x%lx to 0x%lx\n",
1704: (PCHAR) InputDataStart,
1705: (PCHAR) deviceExtension->DataIn
1706: ));
1707:
1708: RtlMoveMemory(
1709: (PCHAR) deviceExtension->DataIn,
1710: (PCHAR) InputDataStart,
1711: moveSize
1712: );
1713:
1714: //
1715: // Increment the port data queue pointer and the class input
1716: // data queue insertion pointer. Wrap the insertion pointer,
1717: // if necessary.
1718: //
1719:
1720: InputDataStart = (PMOUSE_INPUT_DATA)
1721: (((PCHAR) InputDataStart) + moveSize);
1722: deviceExtension->DataIn = (PMOUSE_INPUT_DATA)
1723: (((PCHAR) deviceExtension->DataIn) + moveSize);
1724: if ((PCHAR) deviceExtension->DataIn >=
1725: ((PCHAR) deviceExtension->InputData +
1726: deviceExtension->MouseAttributes.InputDataQueueLength)) {
1727: deviceExtension->DataIn = deviceExtension->InputData;
1728: }
1729:
1730: if ((bytesToMove - moveSize) > 0) {
1731:
1732: //
1733: // Special case. The data must wrap in the class input data buffer.
1734: // Copy the rest of the port input data into the beginning of the
1735: // class input data queue.
1736: //
1737:
1738: //
1739: // moveSize <- Number of bytes to handle in the second move.
1740: //
1741:
1742: moveSize = bytesToMove - moveSize;
1743:
1744: //
1745: // Do the move from the port data queue to the class data queue.
1746: //
1747:
1748: MouPrint((
1749: 3,
1750: "MOUCLASS-MouseClassServiceCallback: number of bytes in second move to class 0x%lx\n",
1751: moveSize
1752: ));
1753: MouPrint((
1754: 3,
1755: "MOUCLASS-MouseClassServiceCallback: move bytes from 0x%lx to 0x%lx\n",
1756: (PCHAR) InputDataStart,
1757: (PCHAR) deviceExtension->DataIn
1758: ));
1759:
1760: RtlMoveMemory(
1761: (PCHAR) deviceExtension->DataIn,
1762: (PCHAR) InputDataStart,
1763: moveSize
1764: );
1765:
1766: //
1767: // Update the class input data queue insertion pointer.
1768: //
1769:
1770: deviceExtension->DataIn = (PMOUSE_INPUT_DATA)
1771: (((PCHAR) deviceExtension->DataIn) + moveSize);
1772: }
1773:
1774: //
1775: // Update the input data queue counter.
1776: //
1777:
1778: deviceExtension->InputCount +=
1779: (bytesToMove / sizeof(MOUSE_INPUT_DATA));
1780: *InputDataConsumed += (bytesToMove / sizeof(MOUSE_INPUT_DATA));
1781:
1782: MouPrint((
1783: 3,
1784: "MOUCLASS-MouseClassServiceCallback: changed InputCount to %ld entries in the class queue\n",
1785: deviceExtension->InputCount
1786: ));
1787: MouPrint((
1788: 3,
1789: "MOUCLASS-MouseClassServiceCallback: DataIn 0x%lx, DataOut 0x%lx\n",
1790: deviceExtension->DataIn,
1791: deviceExtension->DataOut
1792: ));
1793: MouPrint((
1794: 3,
1795: "MOUCLASS-MouseClassServiceCallback: Input data items consumed = %d\n",
1796: *InputDataConsumed
1797: ));
1798: }
1799: }
1800:
1801: //
1802: // Release the class input data queue spinlock.
1803: //
1804:
1805: KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
1806:
1807: //
1808: // If we satisfied an outstanding read request, start the next
1809: // packet and complete the request.
1810: //
1811:
1812: if (satisfiedPendingReadRequest) {
1813:
1814: IoStartNextPacket(DeviceObject, TRUE);
1815: IoCompleteRequest(irp, IO_MOUSE_INCREMENT);
1816: }
1817:
1818: MouPrint((2,"MOUCLASS-MouseClassServiceCallback: exit\n"));
1819:
1820: return;
1821:
1822: }
1823:
1824: VOID
1825: MouseClassStartIo(
1826: IN PDEVICE_OBJECT DeviceObject,
1827: IN PIRP Irp
1828: )
1829:
1830: /*++
1831:
1832: Routine Description:
1833:
1834: This routine is the StartIo routine. It is invoked to start a Read
1835: request. If the class input data queue contains input data, the input
1836: data is copied to the SystemBuffer to satisfy the read.
1837:
1838: N.B. Requests enter MouseClassStartIo in a cancellable state. Also,
1839: there is an implicit assumption that only read requests are
1840: queued to the device queue (and handled by StartIo). If this
1841: changes in the future, the MouseClassCleanup routine will
1842: be impacted.
1843:
1844: NOTE: Could pull the duplicate code out into a called procedure.
1845:
1846: Arguments:
1847:
1848: DeviceObject - Pointer to class device object.
1849:
1850: Irp - Pointer to the request packet.
1851:
1852: Return Value:
1853:
1854: None.
1855:
1856: --*/
1857:
1858: {
1859: PDEVICE_EXTENSION deviceExtension;
1860: PIO_STACK_LOCATION irpSp;
1861: KIRQL cancelIrql;
1862: PCHAR destination;
1863: ULONG bytesInQueue;
1864: ULONG bytesToMove;
1865: ULONG moveSize;
1866:
1867: MouPrint((2,"MOUCLASS-MouseClassStartIo: enter\n"));
1868:
1869: deviceExtension = DeviceObject->DeviceExtension;
1870:
1871: //
1872: // Bump the error log sequence number.
1873: //
1874:
1875: deviceExtension->SequenceNumber += 1;
1876:
1877: //
1878: // Acquire the spinlock to protect the input data queue and associated
1879: // pointers. Note that StartIo is already running at DISPATCH_LEVEL
1880: // IRQL, so we can use KeAcquireSpinLockAtDpcLevel instead of
1881: // KeAcquireSpinLock.
1882: //
1883:
1884: KeAcquireSpinLockAtDpcLevel(&deviceExtension->SpinLock);
1885:
1886: //
1887: // Acquire the cancel spinlock and verify that the Irp has not been
1888: // cancelled and that cleanup is not in progress.
1889: //
1890:
1891: IoAcquireCancelSpinLock(&cancelIrql);
1892: if (Irp->Cancel || deviceExtension->CleanupWasInitiated) {
1893: IoReleaseCancelSpinLock(cancelIrql);
1894: KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
1895: return;
1896: }
1897:
1898: MouPrint((
1899: 3,
1900: "MOUCLASS-MouseClassStartIo: DataIn 0x%lx, DataOut 0x%lx\n",
1901: deviceExtension->DataIn, deviceExtension->DataOut
1902: ));
1903:
1904: MouPrint((
1905: 3,
1906: "MOUCLASS-MouseClassStartIo: entries in queue %ld\n",
1907: deviceExtension->InputCount
1908: ));
1909:
1910: //
1911: // If the input data queue is non-empty, satisfy the read request.
1912: // Otherwise, hold the request pending.
1913: //
1914:
1915: if (deviceExtension->InputCount != 0) {
1916:
1917: //
1918: // Copy as much of the input data as possible from the class input
1919: // data queue to the SystemBuffer to satisfy the read. It may be
1920: // necessary to copy the data in two chunks (i.e., if the circular
1921: // queue wraps).
1922: // First, remove the request from the cancellable state, and free the
1923: // cancel spinlock.
1924: //
1925:
1926: IoSetCancelRoutine(Irp, NULL);
1927: DeviceObject->CurrentIrp = NULL;
1928: IoReleaseCancelSpinLock(cancelIrql);
1929:
1930: irpSp = IoGetCurrentIrpStackLocation(Irp);
1931:
1932: //
1933: // bytesToMove <- MIN(Number of filled bytes in class input data queue,
1934: // Requested read length).
1935: //
1936:
1937: bytesInQueue = deviceExtension->InputCount *
1938: sizeof(MOUSE_INPUT_DATA);
1939: bytesToMove = irpSp->Parameters.Read.Length;
1940: MouPrint((
1941: 3,
1942: "MOUCLASS-MouseClassStartIo: queue size 0x%lx, read length 0x%lx\n",
1943: bytesInQueue,
1944: bytesToMove
1945: ));
1946: bytesToMove = (bytesInQueue < bytesToMove) ?
1947: bytesInQueue:bytesToMove;
1948:
1949: //
1950: // moveSize <- MIN(Number of bytes to be moved from the class queue,
1951: // Number of bytes to end of class input data queue).
1952: //
1953:
1954: bytesInQueue = ((PCHAR) deviceExtension->InputData +
1955: deviceExtension->MouseAttributes.InputDataQueueLength) -
1956: (PCHAR) deviceExtension->DataOut;
1957: moveSize = (bytesToMove < bytesInQueue) ?
1958: bytesToMove:bytesInQueue;
1959: MouPrint((
1960: 3,
1961: "MOUCLASS-MouseClassStartIo: bytes to end of queue 0x%lx\n",
1962: bytesInQueue
1963: ));
1964:
1965: //
1966: // Move bytes from the class input data queue to SystemBuffer, until
1967: // the request is satisfied or we wrap the class input data buffer.
1968: //
1969:
1970: destination = Irp->AssociatedIrp.SystemBuffer;
1971: MouPrint((
1972: 3,
1973: "MOUCLASS-MouseClassStartIo: number of bytes in first move 0x%lx\n",
1974: moveSize
1975: ));
1976: MouPrint((
1977: 3,
1978: "MOUCLASS-MouseClassStartIo: move bytes from 0x%lx to 0x%lx\n",
1979: (PCHAR) deviceExtension->DataOut,
1980: destination
1981: ));
1982:
1983: RtlMoveMemory(
1984: destination,
1985: (PCHAR) deviceExtension->DataOut,
1986: moveSize
1987: );
1988: destination += moveSize;
1989:
1990: //
1991: // If the data wraps in the class input data buffer, copy the rest
1992: // of the data from the start of the input data queue
1993: // buffer through the end of the queued data.
1994: //
1995:
1996: if ((bytesToMove - moveSize) > 0) {
1997:
1998: //
1999: // moveSize <- Remaining number bytes to move.
2000: //
2001:
2002: moveSize = bytesToMove - moveSize;
2003:
2004: //
2005: // Move the bytes from the class input data queue to SystemBuffer.
2006: //
2007:
2008: MouPrint((
2009: 3,
2010: "MOUCLASS-MouseClassStartIo: number of bytes in second move 0x%lx\n",
2011: moveSize
2012: ));
2013: MouPrint((
2014: 3,
2015: "MOUCLASS-MouseClassStartIo: move bytes from 0x%lx to 0x%lx\n",
2016: (PCHAR) deviceExtension->InputData,
2017: destination
2018: ));
2019:
2020: RtlMoveMemory(
2021: destination,
2022: (PCHAR) deviceExtension->InputData,
2023: moveSize
2024: );
2025:
2026: //
2027: // Update the class input data queue removal pointer.
2028: //
2029:
2030: deviceExtension->DataOut = (PMOUSE_INPUT_DATA)
2031: (((PCHAR) deviceExtension->InputData) + moveSize);
2032: } else {
2033:
2034: //
2035: // Update the input data queue removal pointer.
2036: //
2037:
2038: deviceExtension->DataOut = (PMOUSE_INPUT_DATA)
2039: (((PCHAR) deviceExtension->DataOut) + moveSize);
2040: }
2041:
2042: //
2043: // Update the class input data queue InputCount.
2044: //
2045:
2046: deviceExtension->InputCount -=
2047: (bytesToMove / sizeof(MOUSE_INPUT_DATA));
2048:
2049: if (deviceExtension->InputCount == 0) {
2050:
2051: //
2052: // Reset the flag that determines whether it is time to log
2053: // queue overflow errors. We don't want to log errors too often.
2054: // Instead, log an error on the first overflow that occurs after
2055: // the ring buffer has been emptied, and then stop logging errors
2056: // until it gets cleared out and overflows again.
2057: //
2058:
2059: MouPrint((
2060: 1,
2061: "MOUCLASS-MouseClassStartIo: Okay to log overflow\n"
2062: ));
2063: deviceExtension->OkayToLogOverflow = TRUE;
2064: }
2065:
2066: MouPrint((
2067: 3,
2068: "MOUCLASS-MouseClassStartIo: new DataIn 0x%lx, DataOut 0x%lx\n",
2069: deviceExtension->DataIn,
2070: deviceExtension->DataOut
2071: ));
2072: MouPrint((
2073: 3,
2074: "MOUCLASS-MouseClassStartIo: new InputCount %ld\n",
2075: deviceExtension->InputCount
2076: ));
2077:
2078: //
2079: // Clear the RequestIsPending flag to indicate this request is
2080: // not held pending.
2081: //
2082:
2083: deviceExtension->RequestIsPending = FALSE;
2084:
2085: //
2086: // Release the class input data queue spinlock.
2087: //
2088:
2089: KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
2090:
2091: //
2092: // Start the next packet, and complete this read request
2093: // with STATUS_SUCCESS.
2094: //
2095:
2096: Irp->IoStatus.Status = STATUS_SUCCESS;
2097: Irp->IoStatus.Information = bytesToMove;
2098: irpSp->Parameters.Read.Length = bytesToMove;
2099:
2100: IoStartNextPacket(DeviceObject, TRUE);
2101: IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
2102:
2103: } else {
2104:
2105: //
2106: // Set the RequestIsPending flag to indicate this request is
2107: // held pending for the callback routine to complete.
2108: //
2109:
2110: deviceExtension->RequestIsPending = TRUE;
2111:
2112: //
2113: // Hold the read request pending. It remains in the cancellable
2114: // state. When new input is received, the class service
2115: // callback routine will eventually complete the request. For now,
2116: // merely free the cancel spinlock and the class input data queue
2117: // spinlock.
2118: //
2119:
2120: IoReleaseCancelSpinLock(cancelIrql);
2121: KeReleaseSpinLockFromDpcLevel(&deviceExtension->SpinLock);
2122: }
2123:
2124: MouPrint((2,"MOUCLASS-MouseClassStartIo: exit\n"));
2125:
2126: return;
2127:
2128: }
2129:
2130: VOID
2131: MouseClassUnload(
2132: IN PDRIVER_OBJECT DriverObject
2133: )
2134:
2135: /*++
2136:
2137: Routine Description:
2138:
2139: This routine is the class driver unload routine.
2140:
2141: NOTE: Not currently implemented.
2142:
2143: Arguments:
2144:
2145: DeviceObject - Pointer to class device object.
2146:
2147: Return Value:
2148:
2149: None.
2150:
2151: --*/
2152:
2153: {
2154: UNREFERENCED_PARAMETER(DriverObject);
2155:
2156: MouPrint((2,"MOUCLASS-MouseClassUnload: enter\n"));
2157: MouPrint((2,"MOUCLASS-MouseClassUnload: exit\n"));
2158:
2159: return;
2160: }
2161:
2162: VOID
2163: MouConfiguration(
2164: IN PDEVICE_EXTENSION DeviceExtension,
2165: IN PUNICODE_STRING RegistryPath,
2166: IN PUNICODE_STRING DeviceName
2167: )
2168:
2169: /*++
2170:
2171: Routine Description:
2172:
2173: This routine stores the configuration information for this device.
2174:
2175: Arguments:
2176:
2177: DeviceExtension - Pointer to the device extension.
2178:
2179: RegistryPath - Pointer to the null-terminated Unicode name of the
2180: registry path for this driver.
2181:
2182: DeviceName - Pointer to the Unicode string that will receive
2183: the port device name.
2184:
2185: Return Value:
2186:
2187: None. As a side-effect, sets fields in DeviceExtension->MouseAttributes.
2188:
2189: --*/
2190:
2191: {
2192: PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
2193: UNICODE_STRING parametersPath;
2194: ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
2195: ULONG defaultMaximumPortsServiced = 1;
2196: ULONG defaultConnectMultiplePorts = 0;
2197: NTSTATUS status = STATUS_SUCCESS;
2198: UNICODE_STRING defaultUnicodeName;
2199: PWSTR path = NULL;
2200: USHORT queriesPlusOne = 5;
2201:
2202: parametersPath.Buffer = NULL;
2203:
2204: //
2205: // Registry path is already null-terminated, so just use it.
2206: //
2207:
2208: path = RegistryPath->Buffer;
2209:
2210: if (NT_SUCCESS(status)) {
2211:
2212: //
2213: // Allocate the Rtl query table.
2214: //
2215:
2216: parameters = ExAllocatePool(
2217: PagedPool,
2218: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2219: );
2220:
2221: if (!parameters) {
2222:
2223: MouPrint((
2224: 1,
2225: "MOUCLASS-MouConfiguration: Couldn't allocate table for Rtl query to parameters for %ws\n",
2226: path
2227: ));
2228:
2229: status = STATUS_UNSUCCESSFUL;
2230:
2231: } else {
2232:
2233: RtlZeroMemory(
2234: parameters,
2235: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2236: );
2237:
2238: //
2239: // Form a path to this driver's Parameters subkey.
2240: //
2241:
2242: RtlInitUnicodeString(
2243: ¶metersPath,
2244: NULL
2245: );
2246:
2247: parametersPath.MaximumLength = RegistryPath->Length +
2248: sizeof(L"\\Parameters");
2249:
2250: parametersPath.Buffer = ExAllocatePool(
2251: PagedPool,
2252: parametersPath.MaximumLength
2253: );
2254:
2255: if (!parametersPath.Buffer) {
2256:
2257: MouPrint((
2258: 1,
2259: "MOUCLASS-MouConfiguration: Couldn't allocate string for path to parameters for %ws\n",
2260: path
2261: ));
2262:
2263: status = STATUS_UNSUCCESSFUL;
2264:
2265: }
2266: }
2267: }
2268:
2269: if (NT_SUCCESS(status)) {
2270:
2271: //
2272: // Form the parameters path.
2273: //
2274:
2275: RtlZeroMemory(
2276: parametersPath.Buffer,
2277: parametersPath.MaximumLength
2278: );
2279: RtlAppendUnicodeToString(
2280: ¶metersPath,
2281: path
2282: );
2283: RtlAppendUnicodeToString(
2284: ¶metersPath,
2285: L"\\Parameters"
2286: );
2287:
2288: MouPrint((
2289: 1,
2290: "MOUCLASS-MouConfiguration: parameters path is %ws\n",
2291: parametersPath.Buffer
2292: ));
2293:
2294: //
2295: // Form the default pointer class device name, in case it is not
2296: // specified in the registry.
2297: //
2298:
2299: RtlInitUnicodeString(
2300: &defaultUnicodeName,
2301: DD_POINTER_CLASS_BASE_NAME_U
2302: );
2303:
2304: //
2305: // Gather all of the "user specified" information from
2306: // the registry.
2307: //
2308:
2309: parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
2310: parameters[0].Name = L"MouseDataQueueSize";
2311: parameters[0].EntryContext =
2312: &DeviceExtension->MouseAttributes.InputDataQueueLength;
2313: parameters[0].DefaultType = REG_DWORD;
2314: parameters[0].DefaultData = &defaultDataQueueSize;
2315: parameters[0].DefaultLength = sizeof(ULONG);
2316:
2317: parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
2318: parameters[1].Name = L"MaximumPortsServiced";
2319: parameters[1].EntryContext =
2320: &DeviceExtension->MaximumPortsServiced;
2321: parameters[1].DefaultType = REG_DWORD;
2322: parameters[1].DefaultData = &defaultMaximumPortsServiced;
2323: parameters[1].DefaultLength = sizeof(ULONG);
2324:
2325: parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
2326: parameters[2].Name = L"PointerDeviceBaseName";
2327: parameters[2].EntryContext = DeviceName;
2328: parameters[2].DefaultType = REG_SZ;
2329: parameters[2].DefaultData = defaultUnicodeName.Buffer;
2330: parameters[2].DefaultLength = 0;
2331:
2332: parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
2333: parameters[3].Name = L"ConnectMultiplePorts";
2334: parameters[3].EntryContext =
2335: &DeviceExtension->ConnectOneClassToOnePort;
2336: parameters[3].DefaultType = REG_DWORD;
2337: parameters[3].DefaultData = &defaultConnectMultiplePorts;
2338: parameters[3].DefaultLength = sizeof(ULONG);
2339:
2340: status = RtlQueryRegistryValues(
2341: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
2342: parametersPath.Buffer,
2343: parameters,
2344: NULL,
2345: NULL
2346: );
2347:
2348: if (!NT_SUCCESS(status)) {
2349: MouPrint((
2350: 1,
2351: "MOUCLASS-MouConfiguration: RtlQueryRegistryValues failed with 0x%x\n",
2352: status
2353: ));
2354: }
2355: }
2356:
2357: if (!NT_SUCCESS(status)) {
2358:
2359: //
2360: // Go ahead and assign driver defaults.
2361: //
2362:
2363: DeviceExtension->MouseAttributes.InputDataQueueLength =
2364: defaultDataQueueSize;
2365: DeviceExtension->MaximumPortsServiced = defaultMaximumPortsServiced;
2366: DeviceExtension->ConnectOneClassToOnePort =
2367: !defaultConnectMultiplePorts;
2368: RtlCopyUnicodeString(DeviceName, &defaultUnicodeName);
2369: }
2370:
2371: MouPrint((
2372: 1,
2373: "MOUCLASS-MouConfiguration: Mouse class base name = %ws\n",
2374: DeviceName->Buffer
2375: ));
2376:
2377: if (DeviceExtension->MouseAttributes.InputDataQueueLength == 0) {
2378:
2379: MouPrint((
2380: 1,
2381: "MOUCLASS-MouConfiguration: overriding MouseInputDataQueueLength = 0x%x\n",
2382: DeviceExtension->MouseAttributes.InputDataQueueLength
2383: ));
2384:
2385: DeviceExtension->MouseAttributes.InputDataQueueLength =
2386: defaultDataQueueSize;
2387: }
2388:
2389: DeviceExtension->MouseAttributes.InputDataQueueLength *=
2390: sizeof(MOUSE_INPUT_DATA);
2391:
2392: MouPrint((
2393: 1,
2394: "MOUCLASS-MouConfiguration: MouseInputDataQueueLength = 0x%x\n",
2395: DeviceExtension->MouseAttributes.InputDataQueueLength
2396: ));
2397:
2398: MouPrint((
2399: 1,
2400: "MOUCLASS-MouConfiguration: MaximumPortsServiced = %d\n",
2401: DeviceExtension->MaximumPortsServiced
2402: ));
2403:
2404: //
2405: // Invert the flag that specifies the type of class/port connections.
2406: // We used it in the RtlQuery call in an inverted fashion.
2407: //
2408:
2409: DeviceExtension->ConnectOneClassToOnePort =
2410: !DeviceExtension->ConnectOneClassToOnePort;
2411:
2412: MouPrint((
2413: 1,
2414: "MOUCLASS-MouConfiguration: Connection Type = %d\n",
2415: DeviceExtension->ConnectOneClassToOnePort
2416: ));
2417:
2418: //
2419: // Free the allocated memory before returning.
2420: //
2421:
2422: if (parametersPath.Buffer)
2423: ExFreePool(parametersPath.Buffer);
2424: if (parameters)
2425: ExFreePool(parameters);
2426:
2427: }
2428:
2429: NTSTATUS
2430: MouConnectToPort(
2431: IN PDEVICE_OBJECT ClassDeviceObject,
2432: IN PUNICODE_STRING FullPortName,
2433: IN ULONG PortIndex
2434: )
2435:
2436: /*++
2437:
2438: Routine Description:
2439:
2440: This routine creates the mouse class device object and connects
2441: to the port device.
2442:
2443:
2444: Arguments:
2445:
2446: ClassDeviceObject - Pointer to the device object for the class device.
2447:
2448: FullPortName - Pointer to the Unicode string that is the full path name
2449: for the port device object.
2450:
2451: PortIndex - The index into the PortDeviceObjectList[] for the
2452: current connection.
2453:
2454: Return Value:
2455:
2456: The function value is the final status from the operation.
2457:
2458: --*/
2459:
2460: {
2461: PDEVICE_EXTENSION deviceExtension = NULL;
2462: NTSTATUS status;
2463: PFILE_OBJECT fileObject = NULL;
2464: PDEVICE_OBJECT portDeviceObject = NULL;
2465: PIO_ERROR_LOG_PACKET errorLogEntry;
2466: ULONG uniqueErrorValue;
2467: NTSTATUS errorCode = STATUS_SUCCESS;
2468:
2469: MouPrint((1,"\n\nMOUCLASS-MouConnectToPort: enter\n"));
2470:
2471: //
2472: // Get a pointer to the port device object.
2473: //
2474:
2475: MouPrint((
2476: 2,
2477: "MOUCLASS-MouConnectToPort: Pointer port name %ws\n",
2478: FullPortName->Buffer
2479: ));
2480:
2481: status = IoGetDeviceObjectPointer(
2482: FullPortName,
2483: FILE_READ_ATTRIBUTES,
2484: &fileObject,
2485: &portDeviceObject
2486: );
2487:
2488: if (status != STATUS_SUCCESS) {
2489: MouPrint((
2490: 1,
2491: "MOUCLASS-MouConnectToPort: Could not get port device object %ws\n",
2492: FullPortName->Buffer
2493: ));
2494:
2495: goto MouConnectToPortExit;
2496: }
2497:
2498: deviceExtension =
2499: (PDEVICE_EXTENSION) ClassDeviceObject->DeviceExtension;
2500: deviceExtension->PortDeviceObjectList[PortIndex] = portDeviceObject;
2501:
2502: //
2503: // Set the IRP stack size (add 1 for the class layer).
2504: //
2505: // NOTE: This is a bit funky for 1:many connections (we end up setting
2506: // StackSize each time through this routine). Note also that
2507: // there is an assumption that the number of layers in the
2508: // class/port driver model is always the same (i.e., if there is
2509: // a layer between the class and the port driver for one device,
2510: // that is true for every device).
2511: //
2512:
2513: ClassDeviceObject->StackSize =
2514: (CCHAR) deviceExtension->PortDeviceObjectList[PortIndex]->StackSize + 1;
2515:
2516: //
2517: // Connect to port device.
2518: //
2519:
2520: status = MouSendConnectRequest(
2521: ClassDeviceObject,
2522: (PVOID)MouseClassServiceCallback,
2523: PortIndex
2524: );
2525:
2526: if (status != STATUS_SUCCESS) {
2527: MouPrint((
2528: 1,
2529: "MOUCLASS-MouConnectToPort: Could not connect to port device %ws\n",
2530: FullPortName->Buffer
2531: ));
2532:
2533: //
2534: // Log an error.
2535: //
2536:
2537: errorCode = MOUCLASS_NO_PORT_CONNECT;
2538: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 30;
2539: goto MouConnectToPortExit;
2540: }
2541:
2542: MouConnectToPortExit:
2543:
2544: if (status != STATUS_SUCCESS) {
2545:
2546: //
2547: // Some part of the initialization failed. Log an error, and
2548: // clean up the resources for the failed part of the initialization.
2549: //
2550:
2551: if (errorCode != STATUS_SUCCESS) {
2552: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
2553: ClassDeviceObject,
2554: sizeof(IO_ERROR_LOG_PACKET)
2555: );
2556:
2557: if (errorLogEntry != NULL) {
2558:
2559: errorLogEntry->ErrorCode = errorCode;
2560: errorLogEntry->SequenceNumber = 0;
2561: errorLogEntry->MajorFunctionCode = 0;
2562: errorLogEntry->IoControlCode = 0;
2563: errorLogEntry->RetryCount = 0;
2564: errorLogEntry->UniqueErrorValue = uniqueErrorValue;
2565: errorLogEntry->FinalStatus = status;
2566:
2567: IoWriteErrorLogEntry(errorLogEntry);
2568: }
2569: }
2570:
2571: if (fileObject) {
2572: ObDereferenceObject(fileObject);
2573: }
2574:
2575: //
2576: // We count on the caller to free the ring buffer and delete
2577: // the class device object.
2578: //
2579: }
2580:
2581: MouPrint((1,"MOUCLASS-MouConnectToPort: exit\n"));
2582:
2583: return(status);
2584:
2585: }
2586:
2587: NTSTATUS
2588: MouCreateClassObject(
2589: IN PDRIVER_OBJECT DriverObject,
2590: IN PDEVICE_EXTENSION TmpDeviceExtension,
2591: IN PUNICODE_STRING RegistryPath,
2592: IN PUNICODE_STRING FullDeviceName,
2593: IN PUNICODE_STRING BaseDeviceName,
2594: IN PDEVICE_OBJECT *ClassDeviceObject
2595: )
2596:
2597: /*++
2598:
2599: Routine Description:
2600:
2601: This routine creates the mouse class device object.
2602:
2603:
2604: Arguments:
2605:
2606: DriverObject - Pointer to driver object created by system.
2607:
2608: TmpDeviceExtension - Pointer to the template device extension.
2609:
2610: RegistryPath - Pointer to the null-terminated Unicode name of the
2611: registry path for this driver.
2612:
2613: FullDeviceName - Pointer to the Unicode string that is the full path name
2614: for the class device object.
2615:
2616: BaseDeviceName - Pointer to the Unicode string that is the base path name
2617: for the class device.
2618:
2619: ClassDeviceObject - Pointer to a pointer to the class device object.
2620:
2621: Return Value:
2622:
2623: The function value is the final status from the operation.
2624:
2625: --*/
2626:
2627: {
2628: PDEVICE_EXTENSION deviceExtension = NULL;
2629: NTSTATUS status;
2630: PIO_ERROR_LOG_PACKET errorLogEntry;
2631: ULONG uniqueErrorValue;
2632: NTSTATUS errorCode = STATUS_SUCCESS;
2633:
2634: MouPrint((1,"\n\nMOUCLASS-MouCreateClassObject: enter\n"));
2635:
2636: //
2637: // Create a non-exclusive device object for the mouse class device.
2638: //
2639:
2640: MouPrint((
2641: 1,
2642: "MOUCLASS-MouCreateClassObject: Creating device object named %ws\n",
2643: FullDeviceName->Buffer
2644: ));
2645:
2646: status = IoCreateDevice(
2647: DriverObject,
2648: sizeof(DEVICE_EXTENSION),
2649: FullDeviceName,
2650: FILE_DEVICE_MOUSE,
2651: 0,
2652: FALSE,
2653: ClassDeviceObject
2654: );
2655:
2656: if (!NT_SUCCESS(status)) {
2657: MouPrint((
2658: 1,
2659: "MOUCLASS-MouCreateClassObject: Could not create class device object = %ws\n",
2660: FullDeviceName->Buffer
2661: ));
2662: goto MouCreateClassObjectExit;
2663:
2664: }
2665:
2666: //
2667: // Do buffered I/O. I.e., the I/O system will copy to/from user data
2668: // from/to a system buffer.
2669: //
2670:
2671: (*ClassDeviceObject)->Flags |= DO_BUFFERED_IO;
2672: deviceExtension =
2673: (PDEVICE_EXTENSION)(*ClassDeviceObject)->DeviceExtension;
2674: *deviceExtension = *TmpDeviceExtension;
2675:
2676: //
2677: // Initialize spin lock for critical sections.
2678: //
2679:
2680: KeInitializeSpinLock(&deviceExtension->SpinLock);
2681:
2682: //
2683: // Initialize mouse class flags to indicate there is no outstanding
2684: // read request pending and cleanup has not been initiated.
2685: //
2686:
2687: deviceExtension->RequestIsPending = FALSE;
2688: deviceExtension->CleanupWasInitiated = FALSE;
2689:
2690: //
2691: // Allocate the ring buffer for the mouse class input data.
2692: //
2693:
2694: deviceExtension->InputData =
2695: ExAllocatePool(
2696: NonPagedPool,
2697: deviceExtension->MouseAttributes.InputDataQueueLength
2698: );
2699:
2700: if (!deviceExtension->InputData) {
2701:
2702: //
2703: // Could not allocate memory for the mouse class data queue.
2704: //
2705:
2706: MouPrint((
2707: 1,
2708: "MOUCLASS-MouCreateClassObject: Could not allocate input data queue for %ws\n",
2709: FullDeviceName->Buffer
2710: ));
2711:
2712: status = STATUS_INSUFFICIENT_RESOURCES;
2713:
2714: //
2715: // Log an error.
2716: //
2717:
2718: errorCode = MOUCLASS_NO_BUFFER_ALLOCATED;
2719: uniqueErrorValue = MOUSE_ERROR_VALUE_BASE + 20;
2720: goto MouCreateClassObjectExit;
2721: }
2722:
2723: //
2724: // Initialize mouse class input data queue.
2725: //
2726:
2727: MouInitializeDataQueue((PVOID)deviceExtension);
2728:
2729: MouCreateClassObjectExit:
2730:
2731: if (status != STATUS_SUCCESS) {
2732:
2733: //
2734: // Some part of the initialization failed. Log an error, and
2735: // clean up the resources for the failed part of the initialization.
2736: //
2737:
2738: if (errorCode != STATUS_SUCCESS) {
2739: errorLogEntry = (PIO_ERROR_LOG_PACKET)
2740: IoAllocateErrorLogEntry(
2741: (*ClassDeviceObject == NULL) ?
2742: (PVOID) DriverObject : (PVOID) *ClassDeviceObject,
2743: sizeof(IO_ERROR_LOG_PACKET)
2744: );
2745:
2746: if (errorLogEntry != NULL) {
2747:
2748: errorLogEntry->ErrorCode = errorCode;
2749: errorLogEntry->SequenceNumber = 0;
2750: errorLogEntry->MajorFunctionCode = 0;
2751: errorLogEntry->IoControlCode = 0;
2752: errorLogEntry->RetryCount = 0;
2753: errorLogEntry->UniqueErrorValue = uniqueErrorValue;
2754: errorLogEntry->FinalStatus = status;
2755:
2756: IoWriteErrorLogEntry(errorLogEntry);
2757: }
2758: }
2759:
2760: if ((deviceExtension) && (deviceExtension->InputData))
2761: ExFreePool(deviceExtension->InputData);
2762: if (*ClassDeviceObject) {
2763: IoDeleteDevice(*ClassDeviceObject);
2764: *ClassDeviceObject = NULL;
2765: }
2766: }
2767:
2768: MouPrint((1,"MOUCLASS-MouCreateClassObject: exit\n"));
2769:
2770: return(status);
2771:
2772: }
2773:
2774: #if DBG
2775:
2776: VOID
2777: MouDebugPrint(
2778: ULONG DebugPrintLevel,
2779: PCCHAR DebugMessage,
2780: ...
2781: )
2782:
2783: /*++
2784:
2785: Routine Description:
2786:
2787: Debug print routine.
2788:
2789: Arguments:
2790:
2791: Debug print level between 0 and 3, with 3 being the most verbose.
2792:
2793: Return Value:
2794:
2795: None.
2796:
2797: --*/
2798:
2799: {
2800: va_list ap;
2801:
2802: va_start(ap, DebugMessage);
2803:
2804: if (DebugPrintLevel <= MouseDebug) {
2805:
2806: char buffer[256];
2807:
2808: (VOID) vsprintf(buffer, DebugMessage, ap);
2809:
2810: DbgPrint(buffer);
2811: }
2812:
2813: va_end(ap);
2814:
2815: }
2816: #endif
2817:
2818: NTSTATUS
2819: MouDeterminePortsServiced(
2820: IN PUNICODE_STRING BasePortName,
2821: IN OUT PULONG NumberPortsServiced
2822: )
2823:
2824: /*++
2825:
2826: Routine Description:
2827:
2828: This routine reads the DEVICEMAP portion of the registry to determine
2829: how many ports the class driver is to service. Depending on the
2830: value of DeviceExtension->ConnectOneClassToOnePort, the class driver
2831: will eventually create one device object per port device serviced, or
2832: one class device object that connects to multiple port device objects.
2833:
2834: Assumptions:
2835:
2836: 1. If the base device name for the class driver is "PointerClass",
2837: ^^^^^
2838: then the port drivers it can service are found under the
2839: "PointerPort" subkey in the DEVICEMAP portion of the registry.
2840: ^^^^
2841:
2842: 2. The port device objects are created with suffixes in strictly
2843: ascending order, starting with suffix 0. E.g.,
2844: \Device\PointerPort0 indicates the first pointer port device,
2845: \Device\PointerPort1 the second, and so on. There are no gaps
2846: in the list.
2847:
2848: 3. If ConnectOneClassToOnePort is non-zero, there is a 1:1
2849: correspondence between class device objects and port device
2850: objects. I.e., \Device\PointerClass0 will connect to
2851: \Device\PointerPort0, \Device\PointerClass1 to
2852: \Device\PointerPort1, and so on.
2853:
2854: 4. If ConnectOneClassToOnePort is zero, there is a 1:many
2855: correspondence between class device objects and port device
2856: objects. I.e., \Device\PointerClass0 will connect to
2857: \Device\PointerPort0, and \Device\PointerPort1, and so on.
2858:
2859:
2860: Note that for Product 1, the Raw Input Thread (Windows USER) will
2861: only deign to open and read from one pointing device. Hence, it is
2862: safe to make simplifying assumptions because the driver is basically
2863: providing much more functionality than the RIT will use.
2864:
2865: Arguments:
2866:
2867: BasePortName - Pointer to the Unicode string that is the base path name
2868: for the port device.
2869:
2870: NumberPortsServiced - Pointer to storage that will receive the
2871: number of ports this class driver should service.
2872:
2873: Return Value:
2874:
2875: The function value is the final status from the operation.
2876:
2877: --*/
2878:
2879: {
2880:
2881: NTSTATUS status;
2882: PRTL_QUERY_REGISTRY_TABLE registryTable = NULL;
2883: USHORT queriesPlusOne = 2;
2884:
2885: //
2886: // Initialize the result.
2887: //
2888:
2889: *NumberPortsServiced = 0;
2890:
2891: //
2892: // Allocate the Rtl query table.
2893: //
2894:
2895: registryTable = ExAllocatePool(
2896: PagedPool,
2897: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2898: );
2899:
2900: if (!registryTable) {
2901:
2902: MouPrint((
2903: 1,
2904: "MOUCLASS-MouDeterminePortsServiced: Couldn't allocate table for Rtl query\n"
2905: ));
2906:
2907: status = STATUS_UNSUCCESSFUL;
2908:
2909: } else {
2910:
2911: RtlZeroMemory(
2912: registryTable,
2913: sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2914: );
2915:
2916: //
2917: // Set things up so that MouDeviceMapQueryCallback will be
2918: // called once for every value in the pointer port section
2919: // of the registry's hardware devicemap.
2920: //
2921:
2922: registryTable[0].QueryRoutine = MouDeviceMapQueryCallback;
2923: registryTable[0].Name = NULL;
2924:
2925: status = RtlQueryRegistryValues(
2926: RTL_REGISTRY_DEVICEMAP | RTL_REGISTRY_OPTIONAL,
2927: BasePortName->Buffer,
2928: registryTable,
2929: NumberPortsServiced,
2930: NULL
2931: );
2932:
2933: if (!NT_SUCCESS(status)) {
2934: MouPrint((
2935: 1,
2936: "MOUCLASS-MouDeterminePortsServiced: RtlQueryRegistryValues failed with 0x%x\n",
2937: status
2938: ));
2939: }
2940:
2941: ExFreePool(registryTable);
2942: }
2943:
2944: return(status);
2945: }
2946:
2947: NTSTATUS
2948: MouDeviceMapQueryCallback(
2949: IN PWSTR ValueName,
2950: IN ULONG ValueType,
2951: IN PVOID ValueData,
2952: IN ULONG ValueLength,
2953: IN PVOID Context,
2954: IN PVOID EntryContext
2955: )
2956:
2957: /*++
2958:
2959: Routine Description:
2960:
2961: This is the callout routine specified in a call to
2962: RtlQueryRegistryValues. It increments the value pointed
2963: to by the Context parameter.
2964:
2965: Arguments:
2966:
2967: ValueName - Unused.
2968:
2969: ValueType - Unused.
2970:
2971: ValueData - Unused.
2972:
2973: ValueLength - Unused.
2974:
2975: Context - Pointer to a count of the number of times this
2976: routine has been called. This is the number of ports
2977: the class driver needs to service.
2978:
2979: EntryContext - Unused.
2980:
2981: Return Value:
2982:
2983: The function value is the final status from the operation.
2984:
2985: --*/
2986:
2987: {
2988: *(PULONG)Context += 1;
2989:
2990: return(STATUS_SUCCESS);
2991: }
2992:
2993: NTSTATUS
2994: MouEnableDisablePort(
2995: IN PDEVICE_OBJECT DeviceObject,
2996: IN BOOLEAN EnableFlag,
2997: IN ULONG PortIndex
2998: )
2999:
3000: /*++
3001:
3002: Routine Description:
3003:
3004: This routine sends an enable or a disable request to the port driver.
3005:
3006: Arguments:
3007:
3008: DeviceObject - Pointer to class device object.
3009:
3010: EnableFlag - If TRUE, send an ENABLE request; otherwise, send DISABLE.
3011:
3012: PortIndex - Index into the PortDeviceObjectList[] for the current
3013: enable/disable request.
3014:
3015: Return Value:
3016:
3017: Status is returned.
3018:
3019: --*/
3020:
3021: {
3022: PIRP irp;
3023: IO_STATUS_BLOCK ioStatus;
3024: NTSTATUS status;
3025: KEVENT event;
3026: PDEVICE_EXTENSION deviceExtension;
3027:
3028: MouPrint((2,"MOUCLASS-MouEnableDisablePort: enter\n"));
3029:
3030: //
3031: // Get a pointer to the device extension.
3032: //
3033:
3034: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
3035:
3036: //
3037: // Create notification event object to be used to signal the
3038: // request completion.
3039: //
3040:
3041: KeInitializeEvent(&event, NotificationEvent, FALSE);
3042:
3043: //
3044: // Build the synchronous request to be sent to the port driver
3045: // to perform the request. Allocate an IRP to issue the port internal
3046: // device control Enable/Disable call.
3047: //
3048:
3049: irp = IoBuildDeviceIoControlRequest(
3050: EnableFlag? IOCTL_INTERNAL_MOUSE_ENABLE:
3051: IOCTL_INTERNAL_MOUSE_DISABLE,
3052: deviceExtension->PortDeviceObjectList[PortIndex],
3053: NULL,
3054: 0,
3055: NULL,
3056: 0,
3057: TRUE,
3058: &event,
3059: &ioStatus
3060: );
3061:
3062: //
3063: // Call the port driver to perform the operation. If the returned status
3064: // is PENDING, wait for the request to complete.
3065: //
3066:
3067: status = IoCallDriver(
3068: deviceExtension->PortDeviceObjectList[PortIndex],
3069: irp
3070: );
3071:
3072: if (status == STATUS_PENDING) {
3073: (VOID) KeWaitForSingleObject(
3074: &event,
3075: Suspended,
3076: KernelMode,
3077: FALSE,
3078: NULL
3079: );
3080: } else {
3081:
3082: //
3083: // Ensure that the proper status value gets picked up.
3084: //
3085:
3086: ioStatus.Status = status;
3087: }
3088:
3089: MouPrint((2,"MOUCLASS-MouEnableDisablePort: exit\n"));
3090:
3091: return(ioStatus.Status);
3092:
3093: }
3094:
3095: VOID
3096: MouInitializeDataQueue (
3097: IN PVOID Context
3098: )
3099:
3100: /*++
3101:
3102: Routine Description:
3103:
3104: This routine initializes the input data queue. IRQL is raised to
3105: DISPATCH_LEVEL to synchronize with StartIo, and the device object
3106: spinlock is acquired.
3107:
3108: Arguments:
3109:
3110: Context - Supplies a pointer to the device extension.
3111:
3112: Return Value:
3113:
3114: None.
3115:
3116: --*/
3117:
3118: {
3119:
3120: KIRQL oldIrql;
3121: PDEVICE_EXTENSION deviceExtension;
3122:
3123: MouPrint((3,"MOUCLASS-MouInitializeDataQueue: enter\n"));
3124:
3125: //
3126: // Get address of device extension.
3127: //
3128:
3129: deviceExtension = (PDEVICE_EXTENSION)Context;
3130:
3131: //
3132: // Acquire the spinlock to protect the input data
3133: // queue and associated pointers.
3134: //
3135:
3136: KeAcquireSpinLock(&deviceExtension->SpinLock, &oldIrql);
3137:
3138: //
3139: // Initialize the input data queue.
3140: //
3141:
3142: deviceExtension->InputCount = 0;
3143: deviceExtension->DataIn = deviceExtension->InputData;
3144: deviceExtension->DataOut = deviceExtension->InputData;
3145:
3146: deviceExtension->OkayToLogOverflow = TRUE;
3147:
3148: //
3149: // Release the spinlock and return to the old IRQL.
3150: //
3151:
3152: KeReleaseSpinLock(&deviceExtension->SpinLock, oldIrql);
3153:
3154: MouPrint((3,"MOUCLASS-MouInitializeDataQueue: exit\n"));
3155:
3156: } // end MouInitializeDataQueue
3157:
3158: NTSTATUS
3159: MouSendConnectRequest(
3160: IN PDEVICE_OBJECT DeviceObject,
3161: IN PVOID ServiceCallback,
3162: IN ULONG PortIndex
3163: )
3164:
3165: /*++
3166:
3167: Routine Description:
3168:
3169: This routine sends a connect request to the port driver.
3170:
3171: Arguments:
3172:
3173: DeviceObject - Pointer to class device object.
3174:
3175: ServiceCallback - Pointer to the class service callback routine.
3176:
3177: PortIndex - The index into the PortDeviceObjectList[] for the current
3178: connect request.
3179:
3180: Return Value:
3181:
3182: Status is returned.
3183:
3184: --*/
3185:
3186: {
3187: PIRP irp;
3188: IO_STATUS_BLOCK ioStatus;
3189: NTSTATUS status;
3190: KEVENT event;
3191: PDEVICE_EXTENSION deviceExtension;
3192: CONNECT_DATA connectData;
3193:
3194: MouPrint((2,"MOUCLASS-MouSendConnectRequest: enter\n"));
3195:
3196: //
3197: // Get a pointer to the device extension.
3198: //
3199:
3200: deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
3201:
3202: //
3203: // Create notification event object to be used to signal the
3204: // request completion.
3205: //
3206:
3207: KeInitializeEvent(&event, NotificationEvent, FALSE);
3208:
3209: //
3210: // Build the synchronous request to be sent to the port driver
3211: // to perform the request. Allocate an IRP to issue the port internal
3212: // device control connect call. The connect parameters are passed in
3213: // the input buffer.
3214: //
3215:
3216: connectData.ClassDeviceObject = DeviceObject;
3217: connectData.ClassService = ServiceCallback;
3218:
3219: irp = IoBuildDeviceIoControlRequest(
3220: IOCTL_INTERNAL_MOUSE_CONNECT,
3221: deviceExtension->PortDeviceObjectList[PortIndex],
3222: &connectData,
3223: sizeof(CONNECT_DATA),
3224: NULL,
3225: 0,
3226: TRUE,
3227: &event,
3228: &ioStatus
3229: );
3230:
3231: //
3232: // Call the port driver to perform the operation. If the returned status
3233: // is PENDING, wait for the request to complete.
3234: //
3235:
3236: status = IoCallDriver(
3237: deviceExtension->PortDeviceObjectList[PortIndex],
3238: irp
3239: );
3240:
3241: if (status == STATUS_PENDING) {
3242: (VOID) KeWaitForSingleObject(
3243: &event,
3244: Suspended,
3245: KernelMode,
3246: FALSE,
3247: NULL
3248: );
3249: } else {
3250:
3251: //
3252: // Ensure that the proper status value gets picked up.
3253: //
3254:
3255: ioStatus.Status = status;
3256: }
3257:
3258: MouPrint((2,"MOUCLASS-MouSendConnectRequest: exit\n"));
3259:
3260: return(ioStatus.Status);
3261:
3262: } // end MouSendConnectRequest()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.