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
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
14 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion
;
16 /* I really want PCSZ strings as last arguments because
17 * PnP ids are ANSI-encoded in PnP device string
20 SerenumInitMultiSzString(
21 OUT PUNICODE_STRING Destination
,
22 ... /* list of PCSZ */)
26 ANSI_STRING AnsiString
;
27 UNICODE_STRING UnicodeString
;
28 ULONG DestinationSize
= 0;
29 NTSTATUS Status
= STATUS_SUCCESS
;
33 /* Calculate length needed for destination unicode string */
34 va_start(args
, Destination
);
35 Source
= va_arg(args
, PCSZ
);
36 while (Source
!= NULL
)
38 RtlInitAnsiString(&AnsiString
, Source
);
39 DestinationSize
+= RtlAnsiStringToUnicodeSize(&AnsiString
)
40 + sizeof(WCHAR
) /* final NULL */;
41 Source
= va_arg(args
, PCSZ
);
44 if (DestinationSize
== 0)
46 RtlInitUnicodeString(Destination
, NULL
);
47 return STATUS_SUCCESS
;
50 /* Initialize destination string */
51 DestinationSize
+= sizeof(WCHAR
); // final NULL
52 Destination
->Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, DestinationSize
, SERENUM_TAG
);
53 if (!Destination
->Buffer
)
54 return STATUS_INSUFFICIENT_RESOURCES
;
55 Destination
->Length
= 0;
56 Destination
->MaximumLength
= (USHORT
)DestinationSize
;
58 /* Copy arguments to destination string */
59 /* Use a temporary unicode string, which buffer is shared with
60 * destination string, to copy arguments */
61 UnicodeString
.Length
= Destination
->Length
;
62 UnicodeString
.MaximumLength
= Destination
->MaximumLength
;
63 UnicodeString
.Buffer
= Destination
->Buffer
;
64 va_start(args
, Destination
);
65 Source
= va_arg(args
, PCSZ
);
66 while (Source
!= NULL
)
68 RtlInitAnsiString(&AnsiString
, Source
);
69 Status
= RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, FALSE
);
70 if (!NT_SUCCESS(Status
))
72 ExFreePoolWithTag(Destination
->Buffer
, SERENUM_TAG
);
75 Destination
->Length
+= UnicodeString
.Length
+ sizeof(WCHAR
);
76 UnicodeString
.MaximumLength
-= UnicodeString
.Length
+ sizeof(WCHAR
);
77 UnicodeString
.Buffer
+= UnicodeString
.Length
/ sizeof(WCHAR
) + 1;
78 UnicodeString
.Length
= 0;
79 Source
= va_arg(args
, PCSZ
);
82 if (NT_SUCCESS(Status
))
84 /* Finish multi-sz string */
85 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = L
'\0';
86 Destination
->Length
+= sizeof(WCHAR
);
92 ForwardIrpAndWaitCompletion(
93 IN PDEVICE_OBJECT DeviceObject
,
97 if (Irp
->PendingReturned
)
98 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
99 return STATUS_MORE_PROCESSING_REQUIRED
;
104 IN PDEVICE_OBJECT DeviceObject
,
107 PDEVICE_OBJECT LowerDevice
;
111 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
112 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
116 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
117 IoCopyCurrentIrpStackLocationToNext(Irp
);
119 TRACE_(SERENUM
, "Calling lower device %p\n", LowerDevice
);
120 IoSetCompletionRoutine(Irp
, ForwardIrpAndWaitCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
122 Status
= IoCallDriver(LowerDevice
, Irp
);
123 if (Status
== STATUS_PENDING
)
125 Status
= KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
126 if (NT_SUCCESS(Status
))
127 Status
= Irp
->IoStatus
.Status
;
134 ForwardIrpToLowerDeviceAndForget(
135 IN PDEVICE_OBJECT DeviceObject
,
138 PFDO_DEVICE_EXTENSION DeviceExtension
;
139 PDEVICE_OBJECT LowerDevice
;
141 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
142 ASSERT(DeviceExtension
->Common
.IsFDO
);
144 LowerDevice
= DeviceExtension
->LowerDevice
;
146 TRACE_(SERENUM
, "Calling lower device 0x%p\n", LowerDevice
);
147 IoSkipCurrentIrpStackLocation(Irp
);
148 return IoCallDriver(LowerDevice
, Irp
);
152 ForwardIrpToAttachedFdoAndForget(
153 IN PDEVICE_OBJECT DeviceObject
,
156 PPDO_DEVICE_EXTENSION DeviceExtension
;
159 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
160 ASSERT(!DeviceExtension
->Common
.IsFDO
);
162 Fdo
= DeviceExtension
->AttachedFdo
;
164 TRACE_(SERENUM
, "Calling attached Fdo 0x%p\n", Fdo
);
165 IoSkipCurrentIrpStackLocation(Irp
);
166 return IoCallDriver(Fdo
, Irp
);
171 IN PDEVICE_OBJECT DeviceObject
,
174 PDEVICE_OBJECT LowerDevice
;
176 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
177 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
180 IoSkipCurrentIrpStackLocation(Irp
);
181 return IoCallDriver(LowerDevice
, Irp
);
185 DuplicateUnicodeString(
187 IN PCUNICODE_STRING SourceString
,
188 OUT PUNICODE_STRING DestinationString
)
190 if (SourceString
== NULL
|| DestinationString
== NULL
191 || SourceString
->Length
> SourceString
->MaximumLength
192 || (SourceString
->Length
== 0 && SourceString
->MaximumLength
> 0 && SourceString
->Buffer
== NULL
)
193 || Flags
== RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
|| Flags
>= 4)
195 return STATUS_INVALID_PARAMETER
;
199 if ((SourceString
->Length
== 0)
200 && (Flags
!= (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
|
201 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
)))
203 DestinationString
->Length
= 0;
204 DestinationString
->MaximumLength
= 0;
205 DestinationString
->Buffer
= NULL
;
209 USHORT DestMaxLength
= SourceString
->Length
;
211 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
212 DestMaxLength
+= sizeof(UNICODE_NULL
);
214 DestinationString
->Buffer
= ExAllocatePoolWithTag(PagedPool
, DestMaxLength
, SERENUM_TAG
);
215 if (DestinationString
->Buffer
== NULL
)
216 return STATUS_NO_MEMORY
;
218 RtlCopyMemory(DestinationString
->Buffer
, SourceString
->Buffer
, SourceString
->Length
);
219 DestinationString
->Length
= SourceString
->Length
;
220 DestinationString
->MaximumLength
= DestMaxLength
;
222 if (Flags
& RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
)
223 DestinationString
->Buffer
[DestinationString
->Length
/ sizeof(WCHAR
)] = 0;
226 return STATUS_SUCCESS
;