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

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

Generated on Sat May 26 2012 04:26:31 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.