03ef526ad17a797073d29404a5cceff5bf5531d3
[reactos.git] / reactos / drivers / bus / serenum / misc.c
1 /* $Id:
2 *
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
7 *
8 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
9 */
10
11 #define NDEBUG
12 #include "serenum.h"
13 #include <stdarg.h>
14
15 NTSTATUS
16 SerenumDuplicateUnicodeString(
17 OUT PUNICODE_STRING Destination,
18 IN PUNICODE_STRING Source,
19 IN POOL_TYPE PoolType)
20 {
21 ASSERT(Destination);
22
23 if (Source == NULL)
24 {
25 RtlInitUnicodeString(Destination, NULL);
26 return STATUS_SUCCESS;
27 }
28
29 Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength);
30 if (Destination->Buffer == NULL)
31 {
32 return STATUS_INSUFFICIENT_RESOURCES;
33 }
34
35 Destination->MaximumLength = Source->MaximumLength;
36 Destination->Length = Source->Length;
37 RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength);
38
39 return STATUS_SUCCESS;
40 }
41
42 /* I really want ANSI strings as last arguments because
43 * PnP ids are ANSI-encoded in PnP device string
44 * identification */
45 NTSTATUS
46 SerenumInitMultiSzString(
47 OUT PUNICODE_STRING Destination,
48 ... /* list of PCSZ */)
49 {
50 va_list args;
51 PCSZ Source;
52 ANSI_STRING AnsiString;
53 UNICODE_STRING UnicodeString;
54 ULONG DestinationSize = 0;
55 NTSTATUS Status = STATUS_SUCCESS;
56
57 ASSERT(Destination);
58
59 /* Calculate length needed for destination unicode string */
60 va_start(args, Destination);
61 Source = va_arg(args, PCSZ);
62 while (Source != NULL)
63 {
64 RtlInitAnsiString(&AnsiString, Source);
65 DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString)
66 + sizeof(WCHAR) /* final NULL */;
67 Source = va_arg(args, PCSZ);
68 }
69 va_end(args);
70 if (DestinationSize == 0)
71 {
72 RtlInitUnicodeString(Destination, NULL);
73 return STATUS_SUCCESS;
74 }
75
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;
83
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)
93 {
94 RtlInitAnsiString(&AnsiString, Source);
95 Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
96 if (!NT_SUCCESS(Status))
97 {
98 ExFreePoolWithTag(Destination->Buffer, SERENUM_TAG);
99 break;
100 }
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);
106 }
107 va_end(args);
108 if (NT_SUCCESS(Status))
109 {
110 /* Finish multi-sz string */
111 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0';
112 Destination->Length += sizeof(WCHAR);
113 }
114 return Status;
115 }
116
117 NTSTATUS STDCALL
118 ForwardIrpAndWaitCompletion(
119 IN PDEVICE_OBJECT DeviceObject,
120 IN PIRP Irp,
121 IN PVOID Context)
122 {
123 if (Irp->PendingReturned)
124 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
125 return STATUS_MORE_PROCESSING_REQUIRED;
126 }
127
128 NTSTATUS
129 ForwardIrpAndWait(
130 IN PDEVICE_OBJECT DeviceObject,
131 IN PIRP Irp)
132 {
133 PDEVICE_OBJECT LowerDevice;
134 KEVENT Event;
135 NTSTATUS Status;
136
137 ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
138 LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
139
140 ASSERT(LowerDevice);
141
142 KeInitializeEvent(&Event, NotificationEvent, FALSE);
143 IoCopyCurrentIrpStackLocationToNext(Irp);
144
145 DPRINT("Serenum: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
146 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
147
148 Status = IoCallDriver(LowerDevice, Irp);
149 if (Status == STATUS_PENDING)
150 {
151 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
152 if (NT_SUCCESS(Status))
153 Status = Irp->IoStatus.Status;
154 }
155
156 return Status;
157 }
158
159 NTSTATUS STDCALL
160 ForwardIrpToLowerDeviceAndForget(
161 IN PDEVICE_OBJECT DeviceObject,
162 IN PIRP Irp)
163 {
164 PFDO_DEVICE_EXTENSION DeviceExtension;
165 PDEVICE_OBJECT LowerDevice;
166
167 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
168 ASSERT(DeviceExtension->Common.IsFDO);
169
170 LowerDevice = DeviceExtension->LowerDevice;
171 ASSERT(LowerDevice);
172 DPRINT("Serenum: calling lower device 0x%p [%wZ]\n",
173 LowerDevice, &LowerDevice->DriverObject->DriverName);
174 IoSkipCurrentIrpStackLocation(Irp);
175 return IoCallDriver(LowerDevice, Irp);
176 }
177
178 NTSTATUS STDCALL
179 ForwardIrpToAttachedFdoAndForget(
180 IN PDEVICE_OBJECT DeviceObject,
181 IN PIRP Irp)
182 {
183 PPDO_DEVICE_EXTENSION DeviceExtension;
184 PDEVICE_OBJECT Fdo;
185
186 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
187 ASSERT(!DeviceExtension->Common.IsFDO);
188
189 Fdo = DeviceExtension->AttachedFdo;
190 ASSERT(Fdo);
191 DPRINT("Serenum: calling attached Fdo 0x%p [%wZ]\n",
192 Fdo, &Fdo->DriverObject->DriverName);
193 IoSkipCurrentIrpStackLocation(Irp);
194 return IoCallDriver(Fdo, Irp);
195 }
196
197 NTSTATUS STDCALL
198 ForwardIrpAndForget(
199 IN PDEVICE_OBJECT DeviceObject,
200 IN PIRP Irp)
201 {
202 PDEVICE_OBJECT LowerDevice;
203
204 ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
205 LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
206 ASSERT(LowerDevice);
207
208 IoSkipCurrentIrpStackLocation(Irp);
209 return IoCallDriver(LowerDevice, Irp);
210 }