3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Serial enumerator driver
5 * FILE: drivers/dd/serenum/misc.c
6 * PURPOSE: Misceallenous operations
8 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
16 SerenumDuplicateUnicodeString(
17 OUT PUNICODE_STRING Destination
,
18 IN PUNICODE_STRING Source
,
19 IN POOL_TYPE PoolType
)
25 RtlInitUnicodeString(Destination
, NULL
);
26 return STATUS_SUCCESS
;
29 Destination
->Buffer
= ExAllocatePool(PoolType
, Source
->MaximumLength
);
30 if (Destination
->Buffer
== NULL
)
32 return STATUS_INSUFFICIENT_RESOURCES
;
35 Destination
->MaximumLength
= Source
->MaximumLength
;
36 Destination
->Length
= Source
->Length
;
37 RtlCopyMemory(Destination
->Buffer
, Source
->Buffer
, Source
->MaximumLength
);
39 return STATUS_SUCCESS
;
42 /* I really want ANSI strings as last arguments because
43 * PnP ids are ANSI-encoded in PnP device string
46 SerenumInitMultiSzString(
47 OUT PUNICODE_STRING Destination
,
48 ... /* list of PCSZ */)
52 ANSI_STRING AnsiString
;
53 UNICODE_STRING UnicodeString
;
54 ULONG DestinationSize
= 0;
55 NTSTATUS Status
= STATUS_SUCCESS
;
59 /* Calculate length needed for destination unicode string */
60 va_start(args
, Destination
);
61 Source
= va_arg(args
, PCSZ
);
62 while (Source
!= NULL
)
64 RtlInitAnsiString(&AnsiString
, Source
);
65 DestinationSize
+= RtlAnsiStringToUnicodeSize(&AnsiString
)
66 + sizeof(WCHAR
) /* final NULL */;
67 Source
= va_arg(args
, PCSZ
);
70 if (DestinationSize
== 0)
72 RtlInitUnicodeString(Destination
, NULL
);
73 return STATUS_SUCCESS
;
76 /* Initialize destination string */
77 DestinationSize
+= sizeof(WCHAR
); // final NULL
78 Destination
->Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, DestinationSize
, SERENUM_TAG
);
79 if (!Destination
->Buffer
)
80 return STATUS_INSUFFICIENT_RESOURCES
;
81 Destination
->Length
= 0;
82 Destination
->MaximumLength
= (USHORT
)DestinationSize
;
84 /* Copy arguments to destination string */
85 /* Use a temporary unicode string, which buffer is shared with
86 * destination string, to copy arguments */
87 UnicodeString
.Length
= Destination
->Length
;
88 UnicodeString
.MaximumLength
= Destination
->MaximumLength
;
89 UnicodeString
.Buffer
= Destination
->Buffer
;
90 va_start(args
, Destination
);
91 Source
= va_arg(args
, PCSZ
);
92 while (Source
!= NULL
)
94 RtlInitAnsiString(&AnsiString
, Source
);
95 Status
= RtlAnsiStringToUnicodeString(&UnicodeString
, &AnsiString
, FALSE
);
96 if (!NT_SUCCESS(Status
))
98 ExFreePoolWithTag(Destination
->Buffer
, SERENUM_TAG
);
101 Destination
->Length
+= UnicodeString
.Length
+ sizeof(WCHAR
);
102 UnicodeString
.MaximumLength
-= UnicodeString
.Length
+ sizeof(WCHAR
);
103 UnicodeString
.Buffer
+= UnicodeString
.Length
/ sizeof(WCHAR
) + 1;
104 UnicodeString
.Length
= 0;
105 Source
= va_arg(args
, PCSZ
);
108 if (NT_SUCCESS(Status
))
110 /* Finish multi-sz string */
111 Destination
->Buffer
[Destination
->Length
/ sizeof(WCHAR
)] = L
'\0';
112 Destination
->Length
+= sizeof(WCHAR
);
118 ForwardIrpAndWaitCompletion(
119 IN PDEVICE_OBJECT DeviceObject
,
123 if (Irp
->PendingReturned
)
124 KeSetEvent((PKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
125 return STATUS_MORE_PROCESSING_REQUIRED
;
130 IN PDEVICE_OBJECT DeviceObject
,
133 PDEVICE_OBJECT LowerDevice
;
137 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
138 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
142 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
143 IoCopyCurrentIrpStackLocationToNext(Irp
);
145 DPRINT("Serenum: Calling lower device %p [%wZ]\n", LowerDevice
, &LowerDevice
->DriverObject
->DriverName
);
146 IoSetCompletionRoutine(Irp
, ForwardIrpAndWaitCompletion
, &Event
, TRUE
, TRUE
, TRUE
);
148 Status
= IoCallDriver(LowerDevice
, Irp
);
149 if (Status
== STATUS_PENDING
)
151 Status
= KeWaitForSingleObject(&Event
, Suspended
, KernelMode
, FALSE
, NULL
);
152 if (NT_SUCCESS(Status
))
153 Status
= Irp
->IoStatus
.Status
;
160 ForwardIrpToLowerDeviceAndForget(
161 IN PDEVICE_OBJECT DeviceObject
,
164 PFDO_DEVICE_EXTENSION DeviceExtension
;
165 PDEVICE_OBJECT LowerDevice
;
167 DeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
168 ASSERT(DeviceExtension
->Common
.IsFDO
);
170 LowerDevice
= DeviceExtension
->LowerDevice
;
172 DPRINT("Serenum: calling lower device 0x%p [%wZ]\n",
173 LowerDevice
, &LowerDevice
->DriverObject
->DriverName
);
174 IoSkipCurrentIrpStackLocation(Irp
);
175 return IoCallDriver(LowerDevice
, Irp
);
179 ForwardIrpToAttachedFdoAndForget(
180 IN PDEVICE_OBJECT DeviceObject
,
183 PPDO_DEVICE_EXTENSION DeviceExtension
;
186 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
187 ASSERT(!DeviceExtension
->Common
.IsFDO
);
189 Fdo
= DeviceExtension
->AttachedFdo
;
191 DPRINT("Serenum: calling attached Fdo 0x%p [%wZ]\n",
192 Fdo
, &Fdo
->DriverObject
->DriverName
);
193 IoSkipCurrentIrpStackLocation(Irp
);
194 return IoCallDriver(Fdo
, Irp
);
199 IN PDEVICE_OBJECT DeviceObject
,
202 PDEVICE_OBJECT LowerDevice
;
204 ASSERT(((PCOMMON_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->IsFDO
);
205 LowerDevice
= ((PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
)->LowerDevice
;
208 IoSkipCurrentIrpStackLocation(Irp
);
209 return IoCallDriver(LowerDevice
, Irp
);