2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Serial enumerator driver
4 * FILE: drivers/dd/serenum/misc.c
5 * PURPOSE: Misceallenous operations
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
12 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion
;
14 /* I really want PCSZ strings as last arguments because
15 * PnP ids are ANSI-encoded in PnP device string
18 SerenumInitMultiSzString(
19 OUT PUNICODE_STRING Destination
,
20 ... /* list of PCSZ */)
24 ANSI_STRING AnsiString
;
25 UNICODE_STRING UnicodeString
;
26 ULONG DestinationSize
= 0;
27 NTSTATUS Status
= STATUS_SUCCESS
;
31 /* Calculate length needed for destination unicode string */
32 va_start(args
, Destination
);
33 Source
= va_arg(args
, PCSZ
);
34 while (Source
!= NULL
)
36 RtlInitAnsiString(&AnsiString
, Source
);
37 DestinationSize
+= RtlAnsiStringToUnicodeSize(&AnsiString
)
38 + sizeof(WCHAR
) /* final NULL */;
39 Source
= va_arg(args
, PCSZ
);
42 if (DestinationSize
== 0)
44 RtlInitUnicodeString(Destination
, NULL
);
45 return STATUS_SUCCESS
;
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
;
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
)
66 RtlInitAnsiString(&AnsiString
, Source
);
67 Status
= RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, FALSE
);
68 if (!NT_SUCCESS(Status
))
70 ExFreePoolWithTag(Destination
->Buffer
, SERENUM_TAG
);
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
);
80 if (NT_SUCCESS(Status
))
82 /* Finish multi-sz string */
83 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = L
'\0';
84 Destination
->Length
+= sizeof(WCHAR
);
90 ForwardIrpAndWaitCompletion(
91 IN PDEVICE_OBJECT DeviceObject
,
95 if (Irp
->PendingReturned
)
96 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
97 return STATUS_MORE_PROCESSING_REQUIRED
;
102 IN PDEVICE_OBJECT DeviceObject
,
105 PDEVICE_OBJECT LowerDevice
;
109 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
110 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
114 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
115 IoCopyCurrentIrpStackLocationToNext(Irp
);
117 TRACE_(SERENUM
, "Calling lower device %p\n", LowerDevice
);
118 IoSetCompletionRoutine(Irp
, ForwardIrpAndWaitCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
120 Status
= IoCallDriver(LowerDevice
, Irp
);
121 if (Status
== STATUS_PENDING
)
123 Status
= KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
124 if (NT_SUCCESS(Status
))
125 Status
= Irp
->IoStatus
.Status
;
132 ForwardIrpToLowerDeviceAndForget(
133 IN PDEVICE_OBJECT DeviceObject
,
136 PFDO_DEVICE_EXTENSION DeviceExtension
;
137 PDEVICE_OBJECT LowerDevice
;
139 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
140 ASSERT(DeviceExtension
->Common
.IsFDO
);
142 LowerDevice
= DeviceExtension
->LowerDevice
;
144 TRACE_(SERENUM
, "Calling lower device 0x%p\n", LowerDevice
);
145 IoSkipCurrentIrpStackLocation(Irp
);
146 return IoCallDriver(LowerDevice
, Irp
);
150 ForwardIrpToAttachedFdoAndForget(
151 IN PDEVICE_OBJECT DeviceObject
,
154 PPDO_DEVICE_EXTENSION DeviceExtension
;
157 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
158 ASSERT(!DeviceExtension
->Common
.IsFDO
);
160 Fdo
= DeviceExtension
->AttachedFdo
;
162 TRACE_(SERENUM
, "Calling attached Fdo 0x%p\n", Fdo
);
163 IoSkipCurrentIrpStackLocation(Irp
);
164 return IoCallDriver(Fdo
, Irp
);
169 IN PDEVICE_OBJECT DeviceObject
,
172 PDEVICE_OBJECT LowerDevice
;
174 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
175 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
178 IoSkipCurrentIrpStackLocation(Irp
);
179 return IoCallDriver(LowerDevice
, Irp
);
183 DuplicateUnicodeString(
185 IN PCUNICODE_STRING SourceString
,
186 OUT PUNICODE_STRING DestinationString
)
188 if (SourceString
== NULL
|| DestinationString
== NULL
189 || SourceString
->Length
> SourceString
->MaximumLength
190 || (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
)
191 || Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4)
193 return STATUS_INVALID_PARAMETER
;
197 if ((SourceString
->Length
== 0)
198 && (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
199 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
201 DestinationString
->Length
= 0;
202 DestinationString
->MaximumLength
= 0;
203 DestinationString
->Buffer
= NULL
;
207 USHORT DestMaxLength
= SourceString
->Length
;
209 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
210 DestMaxLength
+= sizeof(UNICODE_NULL
);
212 DestinationString
->Buffer
= ExAllocatePoolWithTag(PagedPool
, DestMaxLength
, SERENUM_TAG
);
213 if (DestinationString
->Buffer
== NULL
)
214 return STATUS_NO_MEMORY
;
216 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
217 DestinationString
->Length
= SourceString
->Length
;
218 DestinationString
->MaximumLength
= DestMaxLength
;
220 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
221 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
224 return STATUS_SUCCESS
;