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