Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmouclass.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
1.7.6.1
|