Sync with trunk head (part 1 of 2)
[reactos.git] / 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 PDEVICE_OBJECT LowerDevice = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
31 KEVENT Event;
32 NTSTATUS Status;
33
34 ASSERT(LowerDevice);
35
36 KeInitializeEvent(&Event, NotificationEvent, FALSE);
37 IoCopyCurrentIrpStackLocationToNext(Irp);
38
39 DPRINT("UHCI: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
40 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
41
42 Status = IoCallDriver(LowerDevice, Irp);
43 if (Status == STATUS_PENDING)
44 {
45 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
46 if (NT_SUCCESS(Status))
47 Status = Irp->IoStatus.Status;
48 }
49
50 return Status;
51 }
52
53 NTSTATUS NTAPI
54 ForwardIrpAndForget(
55 IN PDEVICE_OBJECT DeviceObject,
56 IN PIRP Irp)
57 {
58 PDEVICE_OBJECT LowerDevice = ((PHUB_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
59
60 ASSERT(LowerDevice);
61
62 IoSkipCurrentIrpStackLocation(Irp);
63 return IoCallDriver(LowerDevice, Irp);
64 }
65
66 /* I really want PCSZ strings as last arguments because
67 * PnP ids are ANSI-encoded in PnP device string
68 * identification */
69 NTSTATUS
70 UsbhubInitMultiSzString(
71 OUT PUNICODE_STRING Destination,
72 ... /* list of PCSZ */)
73 {
74 va_list args;
75 PCSZ Source;
76 ANSI_STRING AnsiString;
77 UNICODE_STRING UnicodeString;
78 ULONG DestinationSize = 0;
79 NTSTATUS Status = STATUS_SUCCESS;
80
81 ASSERT(Destination);
82
83 /* Calculate length needed for destination unicode string */
84 va_start(args, Destination);
85 Source = va_arg(args, PCSZ);
86 while (Source != NULL)
87 {
88 RtlInitAnsiString(&AnsiString, Source);
89 DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString)
90 + sizeof(WCHAR) /* final NULL */;
91 Source = va_arg(args, PCSZ);
92 }
93 va_end(args);
94 if (DestinationSize == 0)
95 {
96 RtlInitUnicodeString(Destination, NULL);
97 return STATUS_SUCCESS;
98 }
99
100 /* Initialize destination string */
101 DestinationSize += sizeof(WCHAR); // final NULL
102 Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, USB_HUB_TAG);
103 if (!Destination->Buffer)
104 return STATUS_INSUFFICIENT_RESOURCES;
105 Destination->Length = 0;
106 Destination->MaximumLength = (USHORT)DestinationSize;
107
108 /* Copy arguments to destination string */
109 /* Use a temporary unicode string, which buffer is shared with
110 * destination string, to copy arguments */
111 UnicodeString.Length = Destination->Length;
112 UnicodeString.MaximumLength = Destination->MaximumLength;
113 UnicodeString.Buffer = Destination->Buffer;
114 va_start(args, Destination);
115 Source = va_arg(args, PCSZ);
116 while (Source != NULL)
117 {
118 RtlInitAnsiString(&AnsiString, Source);
119 Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
120 if (!NT_SUCCESS(Status))
121 {
122 ExFreePoolWithTag(Destination->Buffer, USB_HUB_TAG);
123 break;
124 }
125 Destination->Length += UnicodeString.Length + sizeof(WCHAR);
126 UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR);
127 UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1;
128 UnicodeString.Length = 0;
129 Source = va_arg(args, PCSZ);
130 }
131 va_end(args);
132 if (NT_SUCCESS(Status))
133 {
134 /* Finish multi-sz string */
135 Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0';
136 Destination->Length += sizeof(WCHAR);
137 }
138 return Status;
139 }
140
141 NTSTATUS
142 UsbhubDuplicateUnicodeString(
143 OUT PUNICODE_STRING Destination,
144 IN PUNICODE_STRING Source,
145 IN POOL_TYPE PoolType)
146 {
147 ASSERT(Destination);
148
149 if (Source == NULL)
150 {
151 RtlInitUnicodeString(Destination, NULL);
152 return STATUS_SUCCESS;
153 }
154
155 Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength);
156 if (Destination->Buffer == NULL)
157 {
158 return STATUS_INSUFFICIENT_RESOURCES;
159 }
160
161 Destination->MaximumLength = Source->MaximumLength;
162 Destination->Length = Source->Length;
163 RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength);
164
165 return STATUS_SUCCESS;
166 }