- Merge the remaining portion of the wlan-bringup branch
[reactos.git] / reactos / drivers / usb / usbhub / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: USB hub driver
4 * FILE: drivers/usb/cromwell/hub/misc.c
5 * PURPOSE: Misceallenous operations
6 *
7 * PROGRAMMERS: Herv� Poussineau (hpoussin@reactos.com),
8 */
9
10 #define NDEBUG
11 #include "usbhub.h"
12 #include <stdarg.h>
13
14 NTSTATUS NTAPI
15 ForwardIrpAndWaitCompletion(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN PIRP Irp,
18 IN PVOID Context)
19 {
20 if (Irp->PendingReturned)
21 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
22 return STATUS_MORE_PROCESSING_REQUIRED;
23 }
24
25 NTSTATUS
26 ForwardIrpAndWait(
27 IN PDEVICE_OBJECT DeviceObject,
28 IN PIRP Irp)
29 {
30 KEVENT Event;
31 NTSTATUS Status;
32
33 KeInitializeEvent(&Event, NotificationEvent, FALSE);
34 IoCopyCurrentIrpStackLocationToNext(Irp);
35
36 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
37
38 Status = IoCallDriver(DeviceObject, Irp);
39 if (Status == STATUS_PENDING)
40 {
41 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
42 if (NT_SUCCESS(Status))
43 Status = Irp->IoStatus.Status;
44 }
45
46 return Status;
47 }
48
49 NTSTATUS NTAPI
50 ForwardIrpAndForget(
51 IN PDEVICE_OBJECT DeviceObject,
52 IN PIRP Irp)
53 {
54 PDEVICE_OBJECT LowerDevice = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
55
56 ASSERT(LowerDevice);
57
58 IoSkipCurrentIrpStackLocation(Irp);
59 return IoCallDriver(LowerDevice, Irp);
60 }
61
62 /* I really want PCSZ strings as last arguments because
63 * PnP ids are ANSI-encoded in PnP device string
64 * identification */
65 NTSTATUS
66 UsbhubInitMultiSzString(
67 OUT PUNICODE_STRING Destination,
68 ... /* list of PCSZ */)
69 {
70 va_list args;
71 PCSZ Source;
72 ANSI_STRING AnsiString;
73 UNICODE_STRING UnicodeString;
74 ULONG DestinationSize = 0;
75 NTSTATUS Status = STATUS_SUCCESS;
76
77 ASSERT(Destination);
78
79 /* Calculate length needed for destination unicode string */
80 va_start(args, Destination);
81 Source = va_arg(args, PCSZ);
82 while (Source != NULL)
83 {
84 RtlInitAnsiString(&AnsiString, Source);
85 DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString)
86 + sizeof(WCHAR) /* final NULL */;
87 Source = va_arg(args, PCSZ);
88 }
89 va_end(args);
90 if (DestinationSize == 0)
91 {
92 RtlInitUnicodeString(Destination, NULL);
93 return STATUS_SUCCESS;
94 }
95
96 /* Initialize destination string */
97 DestinationSize += sizeof(WCHAR); // final NULL
98 Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, USB_HUB_TAG);
99 if (!Destination->Buffer)
100 return STATUS_INSUFFICIENT_RESOURCES;
101 Destination->Length = 0;
102 Destination->MaximumLength = (USHORT)DestinationSize;
103
104 /* Copy arguments to destination string */
105 /* Use a temporary unicode string, which buffer is shared with
106 * destination string, to copy arguments */
107 UnicodeString.Length = Destination->Length;
108 UnicodeString.MaximumLength = Destination->MaximumLength;
109 UnicodeString.Buffer = Destination->Buffer;
110 va_start(args, Destination);
111 Source = va_arg(args, PCSZ);
112 while (Source != NULL)
113 {
114 RtlInitAnsiString(&AnsiString, Source);
115 Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
116 if (!NT_SUCCESS(Status))
117 {
118 ExFreePoolWithTag(Destination->Buffer, USB_HUB_TAG);
119 break;
120 }
121 Destination->Length += UnicodeString.Length + sizeof(WCHAR);
122 UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR);
123 UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1;
124 UnicodeString.Length = 0;
125 Source = va_arg(args, PCSZ);
126 }
127 va_end(args);
128 if (NT_SUCCESS(Status))
129 {
130 /* Finish multi-sz string */
131 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0';
132 Destination->Length += sizeof(WCHAR);
133 }
134 return Status;
135 }
136
137 NTSTATUS
138 UsbhubDuplicateUnicodeString(
139 OUT PUNICODE_STRING Destination,
140 IN PUNICODE_STRING Source,
141 IN POOL_TYPE PoolType)
142 {
143 ASSERT(Destination);
144
145 if (Source == NULL)
146 {
147 RtlInitUnicodeString(Destination, NULL);
148 return STATUS_SUCCESS;
149 }
150
151 Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength);
152 if (Destination->Buffer == NULL)
153 {
154 return STATUS_INSUFFICIENT_RESOURCES;
155 }
156
157 Destination->MaximumLength = Source->MaximumLength;
158 Destination->Length = Source->Length;
159 RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength);
160
161 return STATUS_SUCCESS;
162 }