1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Mouse class driver 4 * FILE: drivers/input/mouclass/misc.c 5 * PURPOSE: Miscellaneous operations 6 * 7 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.org) 8 */ 9 10 #include "mouclass.h" 11 12 #include <debug.h> 13 14 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion; 15 16 static NTSTATUS NTAPI 17 ForwardIrpAndWaitCompletion( 18 IN PDEVICE_OBJECT DeviceObject, 19 IN PIRP Irp, 20 IN PVOID Context) 21 { 22 if (Irp->PendingReturned) 23 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); 24 return STATUS_MORE_PROCESSING_REQUIRED; 25 } 26 27 NTSTATUS 28 ForwardIrpAndWait( 29 IN PDEVICE_OBJECT DeviceObject, 30 IN PIRP Irp) 31 { 32 PDEVICE_OBJECT LowerDevice; 33 KEVENT Event; 34 NTSTATUS Status; 35 36 ASSERT(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO); 37 LowerDevice = ((PPORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 38 39 KeInitializeEvent(&Event, NotificationEvent, FALSE); 40 IoCopyCurrentIrpStackLocationToNext(Irp); 41 42 TRACE_(CLASS_NAME, "Calling lower device %p\n", LowerDevice); 43 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE); 44 45 Status = IoCallDriver(LowerDevice, Irp); 46 if (Status == STATUS_PENDING) 47 { 48 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL); 49 if (NT_SUCCESS(Status)) 50 Status = Irp->IoStatus.Status; 51 } 52 53 return Status; 54 } 55 56 NTSTATUS NTAPI 57 ForwardIrpAndForget( 58 IN PDEVICE_OBJECT DeviceObject, 59 IN PIRP Irp) 60 { 61 PDEVICE_OBJECT LowerDevice; 62 63 ASSERT(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO); 64 LowerDevice = ((PPORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 65 66 IoSkipCurrentIrpStackLocation(Irp); 67 return IoCallDriver(LowerDevice, Irp); 68 } 69 70 NTSTATUS 71 DuplicateUnicodeString( 72 IN ULONG Flags, 73 IN PCUNICODE_STRING SourceString, 74 OUT PUNICODE_STRING DestinationString) 75 { 76 if (SourceString == NULL || DestinationString == NULL 77 || SourceString->Length > SourceString->MaximumLength 78 || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) 79 || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4) 80 { 81 return STATUS_INVALID_PARAMETER; 82 } 83 84 85 if ((SourceString->Length == 0) 86 && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 87 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 88 { 89 DestinationString->Length = 0; 90 DestinationString->MaximumLength = 0; 91 DestinationString->Buffer = NULL; 92 } 93 else 94 { 95 USHORT DestMaxLength = SourceString->Length; 96 97 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 98 DestMaxLength += sizeof(UNICODE_NULL); 99 100 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, CLASS_TAG); 101 if (DestinationString->Buffer == NULL) 102 return STATUS_NO_MEMORY; 103 104 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 105 DestinationString->Length = SourceString->Length; 106 DestinationString->MaximumLength = DestMaxLength; 107 108 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 109 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 110 } 111 112 return STATUS_SUCCESS; 113 } 114