1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Serial enumerator driver 4 * FILE: drivers/dd/serenum/misc.c 5 * PURPOSE: Miscellaneous operations 6 * 7 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.com) 8 */ 9 10 #include "serenum.h" 11 12 #include <debug.h> 13 14 /* I really want PCSZ strings as last arguments because 15 * PnP ids are ANSI-encoded in PnP device string 16 * identification */ 17 NTSTATUS 18 SerenumInitMultiSzString( 19 OUT PUNICODE_STRING Destination, 20 ... /* list of PCSZ */) 21 { 22 va_list args; 23 PCSZ Source; 24 ANSI_STRING AnsiString; 25 UNICODE_STRING UnicodeString; 26 ULONG DestinationSize = 0; 27 NTSTATUS Status = STATUS_SUCCESS; 28 29 ASSERT(Destination); 30 31 /* Calculate length needed for destination unicode string */ 32 va_start(args, Destination); 33 Source = va_arg(args, PCSZ); 34 while (Source != NULL) 35 { 36 RtlInitAnsiString(&AnsiString, Source); 37 DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString) 38 + sizeof(WCHAR) /* final NULL */; 39 Source = va_arg(args, PCSZ); 40 } 41 va_end(args); 42 if (DestinationSize == 0) 43 { 44 RtlInitUnicodeString(Destination, NULL); 45 return STATUS_SUCCESS; 46 } 47 48 /* Initialize destination string */ 49 DestinationSize += sizeof(WCHAR); // final NULL 50 Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, SERENUM_TAG); 51 if (!Destination->Buffer) 52 return STATUS_INSUFFICIENT_RESOURCES; 53 Destination->Length = 0; 54 Destination->MaximumLength = (USHORT)DestinationSize; 55 56 /* Copy arguments to destination string */ 57 /* Use a temporary unicode string, which buffer is shared with 58 * destination string, to copy arguments */ 59 UnicodeString.Length = Destination->Length; 60 UnicodeString.MaximumLength = Destination->MaximumLength; 61 UnicodeString.Buffer = Destination->Buffer; 62 va_start(args, Destination); 63 Source = va_arg(args, PCSZ); 64 while (Source != NULL) 65 { 66 RtlInitAnsiString(&AnsiString, Source); 67 Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); 68 if (!NT_SUCCESS(Status)) 69 { 70 ExFreePoolWithTag(Destination->Buffer, SERENUM_TAG); 71 break; 72 } 73 Destination->Length += UnicodeString.Length + sizeof(WCHAR); 74 UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR); 75 UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1; 76 UnicodeString.Length = 0; 77 Source = va_arg(args, PCSZ); 78 } 79 va_end(args); 80 if (NT_SUCCESS(Status)) 81 { 82 /* Finish multi-sz string */ 83 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0'; 84 Destination->Length += sizeof(WCHAR); 85 } 86 return Status; 87 } 88 89 NTSTATUS NTAPI 90 ForwardIrpToLowerDeviceAndForget( 91 IN PDEVICE_OBJECT DeviceObject, 92 IN PIRP Irp) 93 { 94 PFDO_DEVICE_EXTENSION DeviceExtension; 95 PDEVICE_OBJECT LowerDevice; 96 97 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 98 ASSERT(DeviceExtension->Common.IsFDO); 99 100 LowerDevice = DeviceExtension->LowerDevice; 101 ASSERT(LowerDevice); 102 TRACE_(SERENUM, "Calling lower device 0x%p\n", LowerDevice); 103 IoSkipCurrentIrpStackLocation(Irp); 104 return IoCallDriver(LowerDevice, Irp); 105 } 106 107 NTSTATUS NTAPI 108 ForwardIrpToAttachedFdoAndForget( 109 IN PDEVICE_OBJECT DeviceObject, 110 IN PIRP Irp) 111 { 112 PPDO_DEVICE_EXTENSION DeviceExtension; 113 PDEVICE_OBJECT Fdo; 114 115 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 116 ASSERT(!DeviceExtension->Common.IsFDO); 117 118 Fdo = DeviceExtension->AttachedFdo; 119 ASSERT(Fdo); 120 TRACE_(SERENUM, "Calling attached Fdo 0x%p\n", Fdo); 121 IoSkipCurrentIrpStackLocation(Irp); 122 return IoCallDriver(Fdo, Irp); 123 } 124 125 NTSTATUS NTAPI 126 ForwardIrpAndForget( 127 IN PDEVICE_OBJECT DeviceObject, 128 IN PIRP Irp) 129 { 130 PDEVICE_OBJECT LowerDevice; 131 132 ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO); 133 LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice; 134 ASSERT(LowerDevice); 135 136 IoSkipCurrentIrpStackLocation(Irp); 137 return IoCallDriver(LowerDevice, Irp); 138 } 139 140 NTSTATUS 141 DuplicateUnicodeString( 142 IN ULONG Flags, 143 IN PCUNICODE_STRING SourceString, 144 OUT PUNICODE_STRING DestinationString) 145 { 146 if (SourceString == NULL || DestinationString == NULL 147 || SourceString->Length > SourceString->MaximumLength 148 || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) 149 || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4) 150 { 151 return STATUS_INVALID_PARAMETER; 152 } 153 154 155 if ((SourceString->Length == 0) 156 && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 157 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 158 { 159 DestinationString->Length = 0; 160 DestinationString->MaximumLength = 0; 161 DestinationString->Buffer = NULL; 162 } 163 else 164 { 165 USHORT DestMaxLength = SourceString->Length; 166 167 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 168 DestMaxLength += sizeof(UNICODE_NULL); 169 170 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, SERENUM_TAG); 171 if (DestinationString->Buffer == NULL) 172 return STATUS_NO_MEMORY; 173 174 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 175 DestinationString->Length = SourceString->Length; 176 DestinationString->MaximumLength = DestMaxLength; 177 178 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 179 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 180 } 181 182 return STATUS_SUCCESS; 183 } 184