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