ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kbdclass.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Keyboard class driver
00004  * FILE:            drivers/kbdclass/kbdclass.c
00005  * PURPOSE:         Keyboard class driver
00006  *
00007  * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
00008  */
00009 
00010 #define INITGUID
00011 #include "kbdclass.h"
00012 
00013 static DRIVER_UNLOAD DriverUnload;
00014 static DRIVER_DISPATCH ClassCreate;
00015 static DRIVER_DISPATCH ClassClose;
00016 static DRIVER_DISPATCH ClassCleanup;
00017 static DRIVER_DISPATCH ClassRead;
00018 static DRIVER_DISPATCH ClassDeviceControl;
00019 static DRIVER_DISPATCH IrpStub;
00020 static DRIVER_ADD_DEVICE ClassAddDevice;
00021 static DRIVER_STARTIO ClassStartIo;
00022 static DRIVER_CANCEL ClassCancelRoutine;
00023 static NTSTATUS
00024 HandleReadIrp(
00025     IN PDEVICE_OBJECT DeviceObject,
00026     IN PIRP Irp,
00027     BOOLEAN IsInStartIo);
00028 
00029 static VOID NTAPI
00030 DriverUnload(IN PDRIVER_OBJECT DriverObject)
00031 {
00032     // nothing to do here yet
00033 }
00034 
00035 static NTSTATUS NTAPI
00036 ClassCreate(
00037     IN PDEVICE_OBJECT DeviceObject,
00038     IN PIRP Irp)
00039 {
00040     TRACE_(CLASS_NAME, "IRP_MJ_CREATE\n");
00041 
00042     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00043         return ForwardIrpAndForget(DeviceObject, Irp);
00044 
00045     /* FIXME: open all associated Port devices */
00046     Irp->IoStatus.Status = STATUS_SUCCESS;
00047     Irp->IoStatus.Information = 0;
00048     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00049     return STATUS_SUCCESS;
00050 }
00051 
00052 static NTSTATUS NTAPI
00053 ClassClose(
00054     IN PDEVICE_OBJECT DeviceObject,
00055     IN PIRP Irp)
00056 {
00057     TRACE_(CLASS_NAME, "IRP_MJ_CLOSE\n");
00058 
00059     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00060         return ForwardIrpAndForget(DeviceObject, Irp);
00061 
00062     /* FIXME: close all associated Port devices */
00063     Irp->IoStatus.Status = STATUS_SUCCESS;
00064     Irp->IoStatus.Information = 0;
00065     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00066     return STATUS_SUCCESS;
00067 }
00068 
00069 static NTSTATUS NTAPI
00070 ClassCleanup(
00071     IN PDEVICE_OBJECT DeviceObject,
00072     IN PIRP Irp)
00073 {
00074     TRACE_(CLASS_NAME, "IRP_MJ_CLEANUP\n");
00075 
00076     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00077         return ForwardIrpAndForget(DeviceObject, Irp);
00078 
00079     /* FIXME: cleanup all associated Port devices */
00080     Irp->IoStatus.Status = STATUS_SUCCESS;
00081     Irp->IoStatus.Information = 0;
00082     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00083     return STATUS_SUCCESS;
00084 }
00085 
00086 static NTSTATUS NTAPI
00087 ClassRead(
00088     IN PDEVICE_OBJECT DeviceObject,
00089     IN PIRP Irp)
00090 {
00091     PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00092     KIRQL OldIrql;
00093     NTSTATUS Status;
00094 
00095     TRACE_(CLASS_NAME, "IRP_MJ_READ\n");
00096 
00097     ASSERT(DeviceExtension->Common.IsClassDO);
00098 
00099     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00100         return ForwardIrpAndForget(DeviceObject, Irp);
00101 
00102     if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length < sizeof(KEYBOARD_INPUT_DATA))
00103     {
00104         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
00105         Irp->IoStatus.Information = 0;
00106         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00107 
00108         return STATUS_BUFFER_TOO_SMALL;
00109     }
00110 
00111     KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
00112     Status = HandleReadIrp(DeviceObject, Irp, FALSE);
00113     KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
00114     return Status;
00115 }
00116 
00117 static NTSTATUS NTAPI
00118 ClassDeviceControl(
00119     IN PDEVICE_OBJECT DeviceObject,
00120     IN PIRP Irp)
00121 {
00122     //PCLASS_DEVICE_EXTENSION DeviceExtension;
00123     NTSTATUS Status = STATUS_NOT_SUPPORTED;
00124 
00125     TRACE_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL\n");
00126 
00127     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00128         return ForwardIrpAndForget(DeviceObject, Irp);
00129 
00130     //DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
00131 
00132     switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
00133     {
00134         case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
00135         case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
00136         case IOCTL_KEYBOARD_QUERY_INDICATORS:
00137         case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
00138         {
00139             /* FIXME: We hope that all devices will return the same result.
00140              * Ask only the first one */
00141             PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
00142             if (Head->Flink != Head)
00143             {
00144                 /* We have at least one device */
00145                 PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
00146                 IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
00147                 IoSkipCurrentIrpStackLocation(Irp);
00148                 return IoCallDriver(DevExt->DeviceObject, Irp);
00149             }
00150             break;
00151         }
00152         case IOCTL_KEYBOARD_SET_INDICATORS:
00153         case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */
00154         {
00155             /* Send it to all associated Port devices */
00156             PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
00157             PLIST_ENTRY Entry = Head->Flink;
00158             Status = STATUS_SUCCESS;
00159             while (Entry != Head)
00160             {
00161                 PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry);
00162                 NTSTATUS IntermediateStatus;
00163 
00164                 IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
00165                 IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp);
00166                 if (!NT_SUCCESS(IntermediateStatus))
00167                     Status = IntermediateStatus;
00168                 Entry = Entry->Flink;
00169             }
00170             break;
00171         }
00172         default:
00173             WARN_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
00174                 IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
00175             ASSERT(FALSE);
00176             break;
00177     }
00178 
00179     Irp->IoStatus.Status = Status;
00180     Irp->IoStatus.Information = 0;
00181     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00182 
00183     return Status;
00184 }
00185 
00186 static NTSTATUS NTAPI
00187 IrpStub(
00188     IN PDEVICE_OBJECT DeviceObject,
00189     IN PIRP Irp)
00190 {
00191     NTSTATUS Status = STATUS_NOT_SUPPORTED;
00192 
00193     if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
00194     {
00195         /* Forward some IRPs to lower device */
00196         switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
00197         {
00198             case IRP_MJ_PNP:
00199             case IRP_MJ_INTERNAL_DEVICE_CONTROL:
00200                 return ForwardIrpAndForget(DeviceObject, Irp);
00201             default:
00202             {
00203                 ERR_(CLASS_NAME, "Port DO stub for major function 0x%lx\n",
00204                     IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
00205                 ASSERT(FALSE);
00206             }
00207         }
00208     }
00209     else
00210     {
00211         ERR_(CLASS_NAME, "Class DO stub for major function 0x%lx\n",
00212             IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
00213         ASSERT(FALSE);
00214     }
00215 
00216     Irp->IoStatus.Status = Status;
00217     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00218     return Status;
00219 }
00220 
00221 static NTSTATUS
00222 ReadRegistryEntries(
00223     IN PUNICODE_STRING RegistryPath,
00224     IN PCLASS_DRIVER_EXTENSION DriverExtension)
00225 {
00226     UNICODE_STRING ParametersRegistryKey;
00227     RTL_QUERY_REGISTRY_TABLE Parameters[4];
00228     NTSTATUS Status;
00229 
00230     /* HACK: We don't support multiple devices with this disabled */
00231     ULONG DefaultConnectMultiplePorts = 1;
00232     ULONG DefaultDataQueueSize = 0x64;
00233     PCWSTR DefaultDeviceBaseName = L"KeyboardClass";
00234 
00235     ParametersRegistryKey.Length = 0;
00236     ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
00237     ParametersRegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool, ParametersRegistryKey.MaximumLength, CLASS_TAG);
00238     if (!ParametersRegistryKey.Buffer)
00239     {
00240         WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n");
00241         return STATUS_NO_MEMORY;
00242     }
00243     RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
00244     RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
00245     ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;
00246 
00247     RtlZeroMemory(Parameters, sizeof(Parameters));
00248 
00249     Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
00250     Parameters[0].Name = L"ConnectMultiplePorts";
00251     Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts;
00252     Parameters[0].DefaultType = REG_DWORD;
00253     Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
00254     Parameters[0].DefaultLength = sizeof(ULONG);
00255 
00256     Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
00257     Parameters[1].Name = L"KeyboardDataQueueSize";
00258     Parameters[1].EntryContext = &DriverExtension->DataQueueSize;
00259     Parameters[1].DefaultType = REG_DWORD;
00260     Parameters[1].DefaultData = &DefaultDataQueueSize;
00261     Parameters[1].DefaultLength = sizeof(ULONG);
00262 
00263     Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
00264     Parameters[2].Name = L"KeyboardDeviceBaseName";
00265     Parameters[2].EntryContext = &DriverExtension->DeviceBaseName;
00266     Parameters[2].DefaultType = REG_SZ;
00267     Parameters[2].DefaultData = (PVOID)DefaultDeviceBaseName;
00268     Parameters[2].DefaultLength = 0;
00269 
00270     Status = RtlQueryRegistryValues(
00271         RTL_REGISTRY_ABSOLUTE,
00272         ParametersRegistryKey.Buffer,
00273         Parameters,
00274         NULL,
00275         NULL);
00276 
00277     if (NT_SUCCESS(Status))
00278     {
00279         /* Check values */
00280         if (DriverExtension->ConnectMultiplePorts != 0
00281             && DriverExtension->ConnectMultiplePorts != 1)
00282         {
00283             DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
00284         }
00285         if (DriverExtension->DataQueueSize == 0)
00286         {
00287             DriverExtension->DataQueueSize = DefaultDataQueueSize;
00288         }
00289     }
00290     else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00291     {
00292         /* Registry path doesn't exist. Set defaults */
00293         DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
00294         DriverExtension->DataQueueSize = DefaultDataQueueSize;
00295         if (RtlCreateUnicodeString(&DriverExtension->DeviceBaseName, DefaultDeviceBaseName))
00296             Status = STATUS_SUCCESS;
00297         else
00298             Status = STATUS_NO_MEMORY;
00299     }
00300 
00301     ExFreePoolWithTag(ParametersRegistryKey.Buffer, CLASS_TAG);
00302     return Status;
00303 }
00304 
00305 static NTSTATUS
00306 CreateClassDeviceObject(
00307     IN PDRIVER_OBJECT DriverObject,
00308     OUT PDEVICE_OBJECT *ClassDO OPTIONAL)
00309 {
00310     PCLASS_DRIVER_EXTENSION DriverExtension;
00311     ULONG DeviceId = 0;
00312     ULONG PrefixLength;
00313     UNICODE_STRING DeviceNameU;
00314     PWSTR DeviceIdW = NULL; /* Pointer into DeviceNameU.Buffer */
00315     PDEVICE_OBJECT Fdo;
00316     PCLASS_DEVICE_EXTENSION DeviceExtension;
00317     NTSTATUS Status;
00318 
00319     TRACE_(CLASS_NAME, "CreateClassDeviceObject(0x%p)\n", DriverObject);
00320 
00321     /* Create new device object */
00322     DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
00323     DeviceNameU.Length = 0;
00324     DeviceNameU.MaximumLength =
00325         wcslen(L"\\Device\\") * sizeof(WCHAR)    /* "\Device\" */
00326         + DriverExtension->DeviceBaseName.Length /* "KeyboardClass" */
00327         + 4 * sizeof(WCHAR)                      /* Id between 0 and 9999 */
00328         + sizeof(UNICODE_NULL);                  /* Final NULL char */
00329     DeviceNameU.Buffer = ExAllocatePoolWithTag(PagedPool, DeviceNameU.MaximumLength, CLASS_TAG);
00330     if (!DeviceNameU.Buffer)
00331     {
00332         WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n");
00333         return STATUS_NO_MEMORY;
00334     }
00335     Status = RtlAppendUnicodeToString(&DeviceNameU, L"\\Device\\");
00336     if (!NT_SUCCESS(Status))
00337     {
00338         WARN_(CLASS_NAME, "RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
00339         goto cleanup;
00340     }
00341     Status = RtlAppendUnicodeStringToString(&DeviceNameU, &DriverExtension->DeviceBaseName);
00342     if (!NT_SUCCESS(Status))
00343     {
00344         WARN_(CLASS_NAME, "RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
00345         goto cleanup;
00346     }
00347     PrefixLength = DeviceNameU.MaximumLength - 4 * sizeof(WCHAR) - sizeof(UNICODE_NULL);
00348     DeviceIdW = &DeviceNameU.Buffer[PrefixLength / sizeof(WCHAR)];
00349     while (DeviceId < 9999)
00350     {
00351         DeviceNameU.Length = (USHORT)(PrefixLength + swprintf(DeviceIdW, L"%lu", DeviceId) * sizeof(WCHAR));
00352         Status = IoCreateDevice(
00353             DriverObject,
00354             sizeof(CLASS_DEVICE_EXTENSION),
00355             &DeviceNameU,
00356             FILE_DEVICE_KEYBOARD,
00357             FILE_DEVICE_SECURE_OPEN,
00358             FALSE,
00359             &Fdo);
00360         if (NT_SUCCESS(Status))
00361             goto cleanup;
00362         else if (Status != STATUS_OBJECT_NAME_COLLISION)
00363         {
00364             WARN_(CLASS_NAME, "IoCreateDevice() failed with status 0x%08lx\n", Status);
00365             goto cleanup;
00366         }
00367         DeviceId++;
00368     }
00369     WARN_(CLASS_NAME, "Too many devices starting with '\\Device\\%wZ'\n", &DriverExtension->DeviceBaseName);
00370     Status = STATUS_TOO_MANY_NAMES;
00371 cleanup:
00372     if (!NT_SUCCESS(Status))
00373     {
00374         ExFreePoolWithTag(DeviceNameU.Buffer, CLASS_TAG);
00375         return Status;
00376     }
00377 
00378     DeviceExtension = (PCLASS_DEVICE_EXTENSION)Fdo->DeviceExtension;
00379     RtlZeroMemory(DeviceExtension, sizeof(CLASS_DEVICE_EXTENSION));
00380     DeviceExtension->Common.IsClassDO = TRUE;
00381     DeviceExtension->DriverExtension = DriverExtension;
00382     InitializeListHead(&DeviceExtension->ListHead);
00383     KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
00384     KeInitializeSpinLock(&DeviceExtension->SpinLock);
00385     DeviceExtension->InputCount = 0;
00386     DeviceExtension->PortData = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA), CLASS_TAG);
00387     if (!DeviceExtension->PortData)
00388     {
00389         ExFreePoolWithTag(DeviceNameU.Buffer, CLASS_TAG);
00390         return STATUS_NO_MEMORY;
00391     }
00392     DeviceExtension->DeviceName = DeviceNameU.Buffer;
00393     Fdo->Flags |= DO_POWER_PAGABLE;
00394     Fdo->Flags |= DO_BUFFERED_IO; /* FIXME: Why is it needed for 1st stage setup? */
00395     Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
00396 
00397     /* Add entry entry to HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
00398     RtlWriteRegistryValue(
00399         RTL_REGISTRY_DEVICEMAP,
00400         DriverExtension->DeviceBaseName.Buffer,
00401         DeviceExtension->DeviceName,
00402         REG_SZ,
00403         DriverExtension->RegistryPath.Buffer,
00404         DriverExtension->RegistryPath.MaximumLength);
00405 
00406     if (ClassDO)
00407         *ClassDO = Fdo;
00408 
00409     return STATUS_SUCCESS;
00410 }
00411 
00412 static NTSTATUS
00413 FillEntries(
00414     IN PDEVICE_OBJECT ClassDeviceObject,
00415     IN PIRP Irp,
00416     IN PKEYBOARD_INPUT_DATA DataStart,
00417     IN SIZE_T NumberOfEntries)
00418 {
00419     NTSTATUS Status = STATUS_SUCCESS;
00420 
00421     if (ClassDeviceObject->Flags & DO_BUFFERED_IO)
00422     {
00423         RtlCopyMemory(
00424             Irp->AssociatedIrp.SystemBuffer,
00425             DataStart,
00426             NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
00427     }
00428     else if (ClassDeviceObject->Flags & DO_DIRECT_IO)
00429     {
00430         PVOID DestAddress = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
00431         if (DestAddress)
00432         {
00433             RtlCopyMemory(
00434                 DestAddress,
00435                 DataStart,
00436                 NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
00437         }
00438         else
00439             Status = STATUS_UNSUCCESSFUL;
00440     }
00441     else
00442     {
00443         _SEH2_TRY
00444         {
00445             RtlCopyMemory(
00446                 Irp->UserBuffer,
00447                 DataStart,
00448                 NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA));
00449         }
00450         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00451         {
00452             Status = _SEH2_GetExceptionCode();
00453         }
00454         _SEH2_END;
00455     }
00456 
00457     return Status;
00458 }
00459 
00460 static BOOLEAN NTAPI
00461 ClassCallback(
00462     IN PDEVICE_OBJECT ClassDeviceObject,
00463     IN OUT PKEYBOARD_INPUT_DATA DataStart,
00464     IN PKEYBOARD_INPUT_DATA DataEnd,
00465     IN OUT PULONG ConsumedCount)
00466 {
00467     PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
00468     KIRQL OldIrql;
00469     SIZE_T InputCount = DataEnd - DataStart;
00470     SIZE_T ReadSize;
00471 
00472     TRACE_(CLASS_NAME, "ClassCallback()\n");
00473 
00474     ASSERT(ClassDeviceExtension->Common.IsClassDO);
00475 
00476     KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
00477     if (InputCount > 0)
00478     {
00479         if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize)
00480         {
00481             /*
00482              * We're exceeding the buffer, and data will be thrown away...
00483              * FIXME: What could we do, as we are at DISPATCH_LEVEL?
00484              */
00485             ReadSize = ClassDeviceExtension->DriverExtension->DataQueueSize - ClassDeviceExtension->InputCount;
00486         }
00487         else
00488             ReadSize = InputCount;
00489 
00490         /*
00491          * Move the input data from the port data queue to our class data
00492          * queue.
00493          */
00494         RtlCopyMemory(
00495             &ClassDeviceExtension->PortData[ClassDeviceExtension->InputCount],
00496             (PCHAR)DataStart,
00497             sizeof(KEYBOARD_INPUT_DATA) * ReadSize);
00498 
00499         /* Move the counter up */
00500         ClassDeviceExtension->InputCount += ReadSize;
00501 
00502         (*ConsumedCount) += (ULONG)ReadSize;
00503 
00504         /* Complete pending IRP (if any) */
00505         if (ClassDeviceExtension->PendingIrp)
00506             HandleReadIrp(ClassDeviceObject, ClassDeviceExtension->PendingIrp, FALSE);
00507     }
00508     KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
00509 
00510     TRACE_(CLASS_NAME, "Leaving ClassCallback()\n");
00511     return TRUE;
00512 }
00513 
00514 /* Send IOCTL_INTERNAL_*_CONNECT to port */
00515 static NTSTATUS
00516 ConnectPortDriver(
00517     IN PDEVICE_OBJECT PortDO,
00518     IN PDEVICE_OBJECT ClassDO)
00519 {
00520     KEVENT Event;
00521     PIRP Irp;
00522     IO_STATUS_BLOCK IoStatus;
00523     CONNECT_DATA ConnectData;
00524     NTSTATUS Status;
00525 
00526     TRACE_(CLASS_NAME, "Connecting PortDO %p to ClassDO %p\n", PortDO, ClassDO);
00527 
00528     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00529 
00530     ConnectData.ClassDeviceObject = ClassDO;
00531     ConnectData.ClassService      = ClassCallback;
00532 
00533     Irp = IoBuildDeviceIoControlRequest(
00534         IOCTL_INTERNAL_KEYBOARD_CONNECT,
00535         PortDO,
00536         &ConnectData, sizeof(CONNECT_DATA),
00537         NULL, 0,
00538         TRUE, &Event, &IoStatus);
00539     if (!Irp)
00540         return STATUS_INSUFFICIENT_RESOURCES;
00541 
00542     Status = IoCallDriver(PortDO, Irp);
00543 
00544     if (Status == STATUS_PENDING)
00545         KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
00546     else
00547         IoStatus.Status = Status;
00548 
00549     if (NT_SUCCESS(IoStatus.Status))
00550     {
00551         ObReferenceObject(PortDO);
00552         ExInterlockedInsertTailList(
00553             &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListHead,
00554             &((PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension)->ListEntry,
00555             &((PCLASS_DEVICE_EXTENSION)ClassDO->DeviceExtension)->ListSpinLock);
00556         if (ClassDO->StackSize <= PortDO->StackSize)
00557         {
00558             /* Increase the stack size, in case we have to
00559              * forward some IRPs to the port device object
00560              */
00561             ClassDO->StackSize = PortDO->StackSize + 1;
00562         }
00563     }
00564 
00565     return IoStatus.Status;
00566 }
00567 
00568 /* Send IOCTL_INTERNAL_*_DISCONNECT to port + destroy the Port DO */
00569 static VOID
00570 DestroyPortDriver(
00571     IN PDEVICE_OBJECT PortDO)
00572 {
00573     PPORT_DEVICE_EXTENSION DeviceExtension;
00574     PCLASS_DEVICE_EXTENSION ClassDeviceExtension;
00575     PCLASS_DRIVER_EXTENSION DriverExtension;
00576     KEVENT Event;
00577     PIRP Irp;
00578     IO_STATUS_BLOCK IoStatus;
00579     KIRQL OldIrql;
00580     NTSTATUS Status;
00581 
00582     TRACE_(CLASS_NAME, "Destroying PortDO %p\n", PortDO);
00583 
00584     DeviceExtension = (PPORT_DEVICE_EXTENSION)PortDO->DeviceExtension;
00585     ClassDeviceExtension = DeviceExtension->ClassDO->DeviceExtension;
00586     DriverExtension = IoGetDriverObjectExtension(PortDO->DriverObject, PortDO->DriverObject);
00587 
00588     /* Send IOCTL_INTERNAL_*_DISCONNECT */
00589     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00590     Irp = IoBuildDeviceIoControlRequest(
00591         IOCTL_INTERNAL_KEYBOARD_DISCONNECT,
00592         PortDO,
00593         NULL, 0,
00594         NULL, 0,
00595         TRUE, &Event, &IoStatus);
00596     if (Irp)
00597     {
00598         Status = IoCallDriver(PortDO, Irp);
00599         if (Status == STATUS_PENDING)
00600             KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
00601     }
00602 
00603     /* Remove from ClassDeviceExtension->ListHead list */
00604     KeAcquireSpinLock(&ClassDeviceExtension->ListSpinLock, &OldIrql);
00605     RemoveHeadList(DeviceExtension->ListEntry.Blink);
00606     KeReleaseSpinLock(&ClassDeviceExtension->ListSpinLock, OldIrql);
00607 
00608     /* Remove entry from HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\[DeviceBaseName] */
00609     RtlDeleteRegistryValue(
00610         RTL_REGISTRY_DEVICEMAP,
00611         DriverExtension->DeviceBaseName.Buffer,
00612         ClassDeviceExtension->DeviceName);
00613 
00614     if (DeviceExtension->LowerDevice)
00615         IoDetachDevice(DeviceExtension->LowerDevice);
00616     ObDereferenceObject(PortDO);
00617 
00618     if (!DriverExtension->ConnectMultiplePorts && DeviceExtension->ClassDO)
00619     {
00620         ExFreePoolWithTag(ClassDeviceExtension->PortData, CLASS_TAG);
00621         ExFreePoolWithTag((PVOID)ClassDeviceExtension->DeviceName, CLASS_TAG);
00622         IoDeleteDevice(DeviceExtension->ClassDO);
00623     }
00624 
00625     IoDeleteDevice(PortDO);
00626 }
00627 
00628 static NTSTATUS NTAPI
00629 ClassAddDevice(
00630     IN PDRIVER_OBJECT DriverObject,
00631     IN PDEVICE_OBJECT Pdo)
00632 {
00633     PCLASS_DRIVER_EXTENSION DriverExtension;
00634     PDEVICE_OBJECT Fdo = NULL;
00635     PPORT_DEVICE_EXTENSION DeviceExtension = NULL;
00636     NTSTATUS Status;
00637 
00638     TRACE_(CLASS_NAME, "ClassAddDevice called. Pdo = 0x%p\n", Pdo);
00639 
00640     DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
00641 
00642     if (Pdo == NULL)
00643         /* We may get a NULL Pdo at the first call as we're a legacy driver. Ignore it */
00644         return STATUS_SUCCESS;
00645 
00646     /* Create new device object */
00647     Status = IoCreateDevice(
00648         DriverObject,
00649         sizeof(PORT_DEVICE_EXTENSION),
00650         NULL,
00651         Pdo->DeviceType,
00652         Pdo->Characteristics & FILE_DEVICE_SECURE_OPEN ? FILE_DEVICE_SECURE_OPEN : 0,
00653         FALSE,
00654         &Fdo);
00655     if (!NT_SUCCESS(Status))
00656     {
00657         WARN_(CLASS_NAME, "IoCreateDevice() failed with status 0x%08lx\n", Status);
00658         goto cleanup;
00659     }
00660     IoSetStartIoAttributes(Fdo, TRUE, TRUE);
00661 
00662     DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
00663     RtlZeroMemory(DeviceExtension, sizeof(PORT_DEVICE_EXTENSION));
00664     DeviceExtension->Common.IsClassDO = FALSE;
00665     DeviceExtension->DeviceObject = Fdo;
00666     DeviceExtension->PnpState = dsStopped;
00667     Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
00668     if (!NT_SUCCESS(Status))
00669     {
00670         WARN_(CLASS_NAME, "IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
00671         goto cleanup;
00672     }
00673     if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE)
00674         Fdo->Flags |= DO_POWER_PAGABLE;
00675     if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
00676         Fdo->Flags |= DO_BUFFERED_IO;
00677     if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
00678         Fdo->Flags |= DO_DIRECT_IO;
00679 
00680     if (DriverExtension->ConnectMultiplePorts)
00681         DeviceExtension->ClassDO = DriverExtension->MainClassDeviceObject;
00682     else
00683     {
00684         /* We need a new class device object for this Fdo */
00685         Status = CreateClassDeviceObject(
00686             DriverObject,
00687             &DeviceExtension->ClassDO);
00688         if (!NT_SUCCESS(Status))
00689         {
00690             WARN_(CLASS_NAME, "CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
00691             goto cleanup;
00692         }
00693     }
00694     Status = ConnectPortDriver(Fdo, DeviceExtension->ClassDO);
00695     if (!NT_SUCCESS(Status))
00696     {
00697         WARN_(CLASS_NAME, "ConnectPortDriver() failed with status 0x%08lx\n", Status);
00698         goto cleanup;
00699     }
00700     Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
00701 
00702     /* Register interface ; ignore the error (if any) as having
00703      * a registred interface is not so important... */
00704     Status = IoRegisterDeviceInterface(
00705         Pdo,
00706         &GUID_DEVINTERFACE_KEYBOARD,
00707         NULL,
00708         &DeviceExtension->InterfaceName);
00709     if (!NT_SUCCESS(Status))
00710         DeviceExtension->InterfaceName.Length = 0;
00711 
00712     return STATUS_SUCCESS;
00713 
00714 cleanup:
00715     if (Fdo)
00716         DestroyPortDriver(Fdo);
00717     return Status;
00718 }
00719 
00720 static VOID NTAPI
00721 ClassCancelRoutine(
00722     IN PDEVICE_OBJECT DeviceObject,
00723     IN PIRP Irp)
00724 {
00725     PCLASS_DEVICE_EXTENSION ClassDeviceExtension = DeviceObject->DeviceExtension;
00726     KIRQL OldIrql;
00727     BOOLEAN wasQueued = FALSE;
00728 
00729     TRACE_(CLASS_NAME, "ClassCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
00730 
00731     ASSERT(ClassDeviceExtension->Common.IsClassDO);
00732 
00733     IoReleaseCancelSpinLock(Irp->CancelIrql);
00734 
00735     KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
00736 
00737     if (ClassDeviceExtension->PendingIrp == Irp)
00738     {
00739         ClassDeviceExtension->PendingIrp = NULL;
00740         wasQueued = TRUE;
00741     }
00742     KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
00743 
00744     if (wasQueued)
00745     {
00746         Irp->IoStatus.Status = STATUS_CANCELLED;
00747         Irp->IoStatus.Information = 0;
00748         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00749     }
00750     else
00751     {
00752         DPRINT1("Cancelled IRP is not pending. Race condition?\n");
00753     }
00754 }
00755 
00756 static NTSTATUS
00757 HandleReadIrp(
00758     IN PDEVICE_OBJECT DeviceObject,
00759     IN PIRP Irp,
00760     BOOLEAN IsInStartIo)
00761 {
00762     PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00763     NTSTATUS Status;
00764     KIRQL OldIrql;
00765 
00766     TRACE_(CLASS_NAME, "HandleReadIrp(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
00767 
00768     ASSERT(DeviceExtension->Common.IsClassDO);
00769 
00770     if (DeviceExtension->InputCount > 0)
00771     {
00772         SIZE_T NumberOfEntries;
00773 
00774         NumberOfEntries = MIN(
00775             DeviceExtension->InputCount,
00776             IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
00777 
00778         Status = FillEntries(
00779             DeviceObject,
00780             Irp,
00781             DeviceExtension->PortData,
00782             NumberOfEntries);
00783 
00784         if (NT_SUCCESS(Status))
00785         {
00786             if (DeviceExtension->InputCount > NumberOfEntries)
00787             {
00788                 RtlMoveMemory(
00789                     &DeviceExtension->PortData[0],
00790                     &DeviceExtension->PortData[NumberOfEntries],
00791                     (DeviceExtension->InputCount - NumberOfEntries) * sizeof(KEYBOARD_INPUT_DATA));
00792             }
00793 
00794             DeviceExtension->InputCount -= NumberOfEntries;
00795 
00796             Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
00797         }
00798 
00799         /* Go to next packet and complete this request */
00800         Irp->IoStatus.Status = Status;
00801 
00802         (VOID)IoSetCancelRoutine(Irp, NULL);
00803         IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
00804         DeviceExtension->PendingIrp = NULL;
00805     }
00806     else
00807     {
00808         IoAcquireCancelSpinLock(&OldIrql);
00809         if (Irp->Cancel)
00810         {
00811             DeviceExtension->PendingIrp = NULL;
00812             Status = STATUS_CANCELLED;
00813         }
00814         else
00815         {
00816             IoMarkIrpPending(Irp);
00817             DeviceExtension->PendingIrp = Irp;
00818             (VOID)IoSetCancelRoutine(Irp, ClassCancelRoutine);
00819             Status = STATUS_PENDING;
00820         }
00821         IoReleaseCancelSpinLock(OldIrql);
00822     }
00823     return Status;
00824 }
00825 
00826 static NTSTATUS NTAPI
00827 ClassPnp(
00828     IN PDEVICE_OBJECT DeviceObject,
00829     IN PIRP Irp)
00830 {
00831     PPORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00832     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
00833     OBJECT_ATTRIBUTES ObjectAttributes;
00834     IO_STATUS_BLOCK Iosb;
00835     NTSTATUS Status;
00836     
00837     switch (IrpSp->MinorFunction)
00838     {
00839         case IRP_MN_START_DEVICE:
00840             Status = ForwardIrpAndWait(DeviceObject, Irp);
00841             if (NT_SUCCESS(Status))
00842             {
00843                 InitializeObjectAttributes(&ObjectAttributes,
00844                                            &DeviceExtension->InterfaceName,
00845                                            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
00846                                            NULL,
00847                                            NULL);
00848 
00849                 Status = ZwOpenFile(&DeviceExtension->FileHandle,
00850                                     FILE_READ_DATA,
00851                                     &ObjectAttributes,
00852                                     &Iosb,
00853                                     0,
00854                                     0);
00855                 if (!NT_SUCCESS(Status))
00856                     DeviceExtension->FileHandle = NULL;
00857             }
00858             else
00859                 DeviceExtension->FileHandle = NULL;
00860             Irp->IoStatus.Status = Status;
00861             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00862             return Status;
00863             
00864         case IRP_MN_REMOVE_DEVICE:
00865         case IRP_MN_STOP_DEVICE:
00866             if (DeviceExtension->FileHandle)
00867             {
00868                 ZwClose(DeviceExtension->FileHandle);
00869                 DeviceExtension->FileHandle = NULL;
00870             }
00871             Status = STATUS_SUCCESS;
00872             break;
00873 
00874         default:
00875             Status = Irp->IoStatus.Status;
00876             break;
00877     }
00878 
00879     Irp->IoStatus.Status = Status;
00880     if (NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED)
00881     {
00882         IoSkipCurrentIrpStackLocation(Irp);
00883         return IoCallDriver(DeviceExtension->LowerDevice, Irp);
00884     }
00885     else
00886     {
00887         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00888         return Status;
00889     }
00890 }
00891 
00892 static VOID NTAPI
00893 ClassStartIo(
00894     IN PDEVICE_OBJECT DeviceObject,
00895     IN PIRP Irp)
00896 {
00897     PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
00898     KIRQL OldIrql;
00899 
00900     TRACE_(CLASS_NAME, "ClassStartIo(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
00901 
00902     ASSERT(DeviceExtension->Common.IsClassDO);
00903 
00904     KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
00905     HandleReadIrp(DeviceObject, Irp, TRUE);
00906     KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
00907 }
00908 
00909 static VOID NTAPI
00910 SearchForLegacyDrivers(
00911     IN PDRIVER_OBJECT DriverObject,
00912     IN PVOID Context, /* PCLASS_DRIVER_EXTENSION */
00913     IN ULONG Count)
00914 {
00915     UNICODE_STRING DeviceMapKeyU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP");
00916     PCLASS_DRIVER_EXTENSION DriverExtension;
00917     UNICODE_STRING PortBaseName = { 0, 0, NULL };
00918     PKEY_VALUE_BASIC_INFORMATION KeyValueInformation = NULL;
00919     OBJECT_ATTRIBUTES ObjectAttributes;
00920     HANDLE hDeviceMapKey = (HANDLE)-1;
00921     HANDLE hPortKey = (HANDLE)-1;
00922     ULONG Index = 0;
00923     ULONG Size, ResultLength;
00924     NTSTATUS Status;
00925 
00926     TRACE_(CLASS_NAME, "SearchForLegacyDrivers(%p %p %lu)\n",
00927         DriverObject, Context, Count);
00928 
00929     if (Count != 1)
00930         return;
00931     DriverExtension = (PCLASS_DRIVER_EXTENSION)Context;
00932 
00933     /* Create port base name, by replacing Class by Port at the end of the class base name */
00934     Status = DuplicateUnicodeString(
00935         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
00936         &DriverExtension->DeviceBaseName,
00937         &PortBaseName);
00938     if (!NT_SUCCESS(Status))
00939     {
00940         WARN_(CLASS_NAME, "DuplicateUnicodeString() failed with status 0x%08lx\n", Status);
00941         goto cleanup;
00942     }
00943     PortBaseName.Length -= (sizeof(L"Class") - sizeof(UNICODE_NULL));
00944     RtlAppendUnicodeToString(&PortBaseName, L"Port");
00945 
00946     /* Allocate memory */
00947     Size = sizeof(KEY_VALUE_BASIC_INFORMATION) + MAX_PATH;
00948     KeyValueInformation = ExAllocatePoolWithTag(PagedPool, Size, CLASS_TAG);
00949     if (!KeyValueInformation)
00950     {
00951         WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n");
00952         Status = STATUS_NO_MEMORY;
00953         goto cleanup;
00954     }
00955 
00956     /* Open HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP */
00957     InitializeObjectAttributes(&ObjectAttributes, &DeviceMapKeyU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
00958     Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes);
00959     if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00960     {
00961         INFO_(CLASS_NAME, "HKLM\\HARDWARE\\DEVICEMAP is non-existent\n");
00962         Status = STATUS_SUCCESS;
00963         goto cleanup;
00964     }
00965     else if (!NT_SUCCESS(Status))
00966     {
00967         WARN_(CLASS_NAME, "ZwOpenKey() failed with status 0x%08lx\n", Status);
00968         goto cleanup;
00969     }
00970 
00971     /* Open sub key */
00972     InitializeObjectAttributes(&ObjectAttributes, &PortBaseName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceMapKey, NULL);
00973     Status = ZwOpenKey(&hPortKey, KEY_QUERY_VALUE, &ObjectAttributes);
00974     if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00975     {
00976         INFO_(CLASS_NAME, "HKLM\\HARDWARE\\DEVICEMAP\\%wZ is non-existent\n", &PortBaseName);
00977         Status = STATUS_SUCCESS;
00978         goto cleanup;
00979     }
00980     else if (!NT_SUCCESS(Status))
00981     {
00982         WARN_(CLASS_NAME, "ZwOpenKey() failed with status 0x%08lx\n", Status);
00983         goto cleanup;
00984     }
00985 
00986     /* Read each value name */
00987     while (ZwEnumerateValueKey(hPortKey, Index++, KeyValueBasicInformation, KeyValueInformation, Size, &ResultLength) == STATUS_SUCCESS)
00988     {
00989         UNICODE_STRING PortName;
00990         PDEVICE_OBJECT PortDeviceObject = NULL;
00991         PFILE_OBJECT FileObject = NULL;
00992 
00993         PortName.Length = PortName.MaximumLength = (USHORT)KeyValueInformation->NameLength;
00994         PortName.Buffer = KeyValueInformation->Name;
00995 
00996         /* Open the device object pointer */
00997         Status = IoGetDeviceObjectPointer(&PortName, FILE_READ_ATTRIBUTES, &FileObject, &PortDeviceObject);
00998         if (!NT_SUCCESS(Status))
00999         {
01000             WARN_(CLASS_NAME, "IoGetDeviceObjectPointer(%wZ) failed with status 0x%08lx\n", &PortName, Status);
01001             continue;
01002         }
01003         INFO_(CLASS_NAME, "Legacy driver found\n");
01004 
01005         Status = ClassAddDevice(DriverObject, PortDeviceObject);
01006         if (!NT_SUCCESS(Status))
01007         {
01008             /* FIXME: Log the error */
01009             WARN_(CLASS_NAME, "ClassAddDevice() failed with status 0x%08lx\n", Status);
01010         }
01011 
01012         ObDereferenceObject(FileObject);
01013     }
01014 
01015 cleanup:
01016     if (KeyValueInformation != NULL)
01017         ExFreePoolWithTag(KeyValueInformation, CLASS_TAG);
01018     if (hDeviceMapKey != (HANDLE)-1)
01019         ZwClose(hDeviceMapKey);
01020     if (hPortKey != (HANDLE)-1)
01021         ZwClose(hPortKey);
01022 }
01023 
01024 /*
01025  * Standard DriverEntry method.
01026  */
01027 NTSTATUS NTAPI
01028 DriverEntry(
01029     IN PDRIVER_OBJECT DriverObject,
01030     IN PUNICODE_STRING RegistryPath)
01031 {
01032     PCLASS_DRIVER_EXTENSION DriverExtension;
01033     ULONG i;
01034     NTSTATUS Status;
01035 
01036     Status = IoAllocateDriverObjectExtension(
01037         DriverObject,
01038         DriverObject,
01039         sizeof(CLASS_DRIVER_EXTENSION),
01040         (PVOID*)&DriverExtension);
01041     if (!NT_SUCCESS(Status))
01042     {
01043         WARN_(CLASS_NAME, "IoAllocateDriverObjectExtension() failed with status 0x%08lx\n", Status);
01044         return Status;
01045     }
01046     RtlZeroMemory(DriverExtension, sizeof(CLASS_DRIVER_EXTENSION));
01047 
01048     Status = DuplicateUnicodeString(
01049         RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
01050         RegistryPath,
01051         &DriverExtension->RegistryPath);
01052     if (!NT_SUCCESS(Status))
01053     {
01054         WARN_(CLASS_NAME, "DuplicateUnicodeString() failed with status 0x%08lx\n", Status);
01055         return Status;
01056     }
01057 
01058     Status = ReadRegistryEntries(RegistryPath, DriverExtension);
01059     if (!NT_SUCCESS(Status))
01060     {
01061         WARN_(CLASS_NAME, "ReadRegistryEntries() failed with status 0x%08lx\n", Status);
01062         return Status;
01063     }
01064 
01065     if (DriverExtension->ConnectMultiplePorts == 1)
01066     {
01067         Status = CreateClassDeviceObject(
01068             DriverObject,
01069             &DriverExtension->MainClassDeviceObject);
01070         if (!NT_SUCCESS(Status))
01071         {
01072             WARN_(CLASS_NAME, "CreateClassDeviceObject() failed with status 0x%08lx\n", Status);
01073             return Status;
01074         }
01075     }
01076 
01077     DriverObject->DriverExtension->AddDevice = ClassAddDevice;
01078     DriverObject->DriverUnload = DriverUnload;
01079 
01080     for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
01081         DriverObject->MajorFunction[i] = IrpStub;
01082 
01083     DriverObject->MajorFunction[IRP_MJ_CREATE]         = ClassCreate;
01084     DriverObject->MajorFunction[IRP_MJ_CLOSE]          = ClassClose;
01085     DriverObject->MajorFunction[IRP_MJ_CLEANUP]        = ClassCleanup;
01086     DriverObject->MajorFunction[IRP_MJ_READ]           = ClassRead;
01087     DriverObject->MajorFunction[IRP_MJ_PNP]            = ClassPnp;
01088     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ClassDeviceControl;
01089     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ForwardIrpAndForget;
01090     DriverObject->DriverStartIo                        = ClassStartIo;
01091 
01092     /* We will detect the legacy devices later */
01093     IoRegisterDriverReinitialization(
01094         DriverObject,
01095         SearchForLegacyDrivers,
01096         DriverExtension);
01097 
01098     return STATUS_SUCCESS;
01099 }

Generated on Sun May 27 2012 04:27:50 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.