[NTFS] - Add some fixes and improvements to attribute.c from CR-123:
[reactos.git] / drivers / usb / usbport / ioctl.c
1 /*
2 * PROJECT: ReactOS USB Port Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBPort I/O control functions
5 * COPYRIGHT: Copyright 2017 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbport.h"
9
10 //#define NDEBUG
11 #include <debug.h>
12
13 VOID
14 NTAPI
15 USBPORT_UserGetHcName(IN PDEVICE_OBJECT FdoDevice,
16 IN PUSBUSER_CONTROLLER_UNICODE_NAME ControllerName,
17 IN PUSB_UNICODE_NAME UnicodeName)
18 {
19 PUSBPORT_DEVICE_EXTENSION FdoExtension;
20 ULONG Length;
21 NTSTATUS Status;
22 ULONG ResultLength;
23
24 DPRINT("USBPORT_UserGetHcName: ... \n");
25
26 FdoExtension = FdoDevice->DeviceExtension;
27
28 Length = ControllerName->Header.RequestBufferLength -
29 sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
30
31 RtlZeroMemory(UnicodeName, Length);
32
33 Status = IoGetDeviceProperty(FdoExtension->CommonExtension.LowerPdoDevice,
34 DevicePropertyDriverKeyName,
35 Length,
36 UnicodeName->String,
37 &ResultLength);
38
39 if (!NT_SUCCESS(Status))
40 {
41 if (Status == STATUS_BUFFER_TOO_SMALL)
42 {
43 ControllerName->Header.UsbUserStatusCode = UsbUserBufferTooSmall;
44 }
45 else
46 {
47 ControllerName->Header.UsbUserStatusCode = UsbUserInvalidParameter;
48 }
49 }
50 else
51 {
52 ControllerName->Header.UsbUserStatusCode = UsbUserSuccess;
53 UnicodeName->Length = ResultLength + sizeof(UNICODE_NULL);
54 }
55
56 ControllerName->Header.ActualBufferLength = sizeof(USBUSER_CONTROLLER_UNICODE_NAME) +
57 ResultLength;
58 }
59
60 NTSTATUS
61 NTAPI
62 USBPORT_GetSymbolicName(IN PDEVICE_OBJECT RootHubPdo,
63 IN PUNICODE_STRING DestinationString)
64 {
65 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
66 PUNICODE_STRING RootHubName;
67 PWCHAR Buffer;
68 SIZE_T LengthName;
69 SIZE_T Length;
70 PWSTR SourceString;
71 WCHAR Character;
72
73 DPRINT("USBPORT_GetSymbolicName: ... \n");
74
75 PdoExtension = RootHubPdo->DeviceExtension;
76 RootHubName = &PdoExtension->CommonExtension.SymbolicLinkName;
77 Buffer = RootHubName->Buffer;
78
79 if (!Buffer)
80 {
81 return STATUS_UNSUCCESSFUL;
82 }
83
84 LengthName = RootHubName->Length;
85
86 SourceString = ExAllocatePoolWithTag(PagedPool, LengthName, USB_PORT_TAG);
87
88 if (!SourceString)
89 {
90 RtlInitUnicodeString(DestinationString, NULL);
91 return STATUS_INSUFFICIENT_RESOURCES;
92 }
93
94 RtlZeroMemory(SourceString, LengthName);
95
96 if (*Buffer == L'\\')
97 {
98 Buffer += 1;
99
100 if (*Buffer == L'\\')
101 {
102 Buffer += 1;
103 goto Exit;
104 }
105
106 Character = *Buffer;
107
108 do
109 {
110 if (Character == UNICODE_NULL)
111 {
112 break;
113 }
114
115 Buffer += 1;
116 Character = *Buffer;
117 }
118 while (*Buffer != L'\\');
119
120 if (*Buffer == L'\\')
121 {
122 Buffer += 1;
123 }
124
125 Exit:
126 Length = (ULONG_PTR)Buffer - (ULONG_PTR)RootHubName->Buffer;
127 }
128 else
129 {
130 Length = 0;
131 }
132
133 RtlCopyMemory(SourceString,
134 (PVOID)((ULONG_PTR)RootHubName->Buffer + Length),
135 RootHubName->Length - Length);
136
137 RtlInitUnicodeString(DestinationString, SourceString);
138
139 DPRINT("USBPORT_RegisterDeviceInterface: DestinationString - %wZ\n",
140 DestinationString);
141
142 return STATUS_SUCCESS;
143 }
144
145 VOID
146 NTAPI
147 USBPORT_UserGetRootHubName(IN PDEVICE_OBJECT FdoDevice,
148 IN PUSBUSER_CONTROLLER_UNICODE_NAME RootHubName,
149 IN PUSB_UNICODE_NAME UnicodeName)
150 {
151 PUSBPORT_DEVICE_EXTENSION FdoExtension;
152 UNICODE_STRING UnicodeString;
153 ULONG Length;
154 ULONG ResultLength = 0;
155 NTSTATUS Status;
156
157 DPRINT("USBPORT_UserGetRootHubName: ... \n");
158
159 FdoExtension = FdoDevice->DeviceExtension;
160
161 Length = RootHubName->Header.RequestBufferLength -
162 sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
163
164 RtlZeroMemory(UnicodeName, Length);
165
166 Status = USBPORT_GetSymbolicName(FdoExtension->RootHubPdo, &UnicodeString);
167
168 if (NT_SUCCESS(Status))
169 {
170 ResultLength = UnicodeString.Length;
171
172 if (UnicodeString.Length > Length)
173 {
174 UnicodeString.Length = Length;
175 Status = STATUS_BUFFER_TOO_SMALL;
176 }
177
178 if (UnicodeString.Length)
179 {
180 RtlCopyMemory(UnicodeName->String,
181 UnicodeString.Buffer,
182 UnicodeString.Length);
183 }
184
185 RtlFreeUnicodeString(&UnicodeString);
186 }
187
188 if (!NT_SUCCESS(Status))
189 {
190 if (Status == STATUS_BUFFER_TOO_SMALL)
191 {
192 RootHubName->Header.UsbUserStatusCode = UsbUserBufferTooSmall;
193 }
194 else
195 {
196 RootHubName->Header.UsbUserStatusCode = UsbUserInvalidParameter;
197 }
198 }
199 else
200 {
201 RootHubName->Header.UsbUserStatusCode = UsbUserSuccess;
202 UnicodeName->Length = ResultLength + sizeof(UNICODE_NULL);
203 }
204
205 RootHubName->Header.ActualBufferLength = sizeof(USBUSER_CONTROLLER_UNICODE_NAME) +
206 ResultLength;
207 }
208
209 NTSTATUS
210 NTAPI
211 USBPORT_GetUnicodeName(IN PDEVICE_OBJECT FdoDevice,
212 IN PIRP Irp,
213 IN PULONG Information)
214 {
215 PUSB_HCD_DRIVERKEY_NAME DriverKey;
216 PIO_STACK_LOCATION IoStack;
217 ULONG OutputBufferLength;
218 ULONG IoControlCode;
219 ULONG Length;
220 PUSBUSER_CONTROLLER_UNICODE_NAME ControllerName;
221 PUSB_UNICODE_NAME UnicodeName;
222 ULONG ActualLength;
223
224 DPRINT("USBPORT_GetUnicodeName: ... \n");
225
226 *Information = 0;
227 DriverKey = Irp->AssociatedIrp.SystemBuffer;
228
229 IoStack = IoGetCurrentIrpStackLocation(Irp);
230 OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
231 IoControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
232
233 if (OutputBufferLength < sizeof(USB_UNICODE_NAME))
234 {
235 return STATUS_BUFFER_TOO_SMALL;
236 }
237
238 Length = sizeof(USBUSER_CONTROLLER_UNICODE_NAME);
239
240 while (TRUE)
241 {
242 ControllerName = ExAllocatePoolWithTag(PagedPool,
243 Length,
244 USB_PORT_TAG);
245
246 if (!ControllerName)
247 {
248 return STATUS_INSUFFICIENT_RESOURCES;
249 }
250
251 RtlZeroMemory(ControllerName, Length);
252
253 ControllerName->Header.RequestBufferLength = Length;
254 UnicodeName = &ControllerName->UnicodeName;
255
256 if (IoControlCode == IOCTL_GET_HCD_DRIVERKEY_NAME)
257 {
258 ControllerName->Header.UsbUserRequest = USBUSER_GET_CONTROLLER_DRIVER_KEY;
259 USBPORT_UserGetHcName(FdoDevice, ControllerName, UnicodeName);
260 }
261 else
262 {
263 ControllerName->Header.UsbUserRequest = USBUSER_GET_ROOTHUB_SYMBOLIC_NAME;
264 USBPORT_UserGetRootHubName(FdoDevice, ControllerName, UnicodeName);
265 }
266
267 if (ControllerName->Header.UsbUserStatusCode != UsbUserBufferTooSmall)
268 {
269 break;
270 }
271
272 Length = ControllerName->Header.ActualBufferLength;
273
274 ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
275 }
276
277 if (ControllerName->Header.UsbUserStatusCode != UsbUserSuccess)
278 {
279 return STATUS_UNSUCCESSFUL;
280 }
281
282 ActualLength = sizeof(ULONG) + ControllerName->UnicodeName.Length;
283
284 DriverKey->ActualLength = ActualLength;
285
286 if (OutputBufferLength < ActualLength)
287 {
288 DriverKey->DriverKeyName[0] = UNICODE_NULL;
289 *Information = sizeof(USB_UNICODE_NAME);
290 }
291 else
292 {
293 RtlCopyMemory(DriverKey->DriverKeyName,
294 ControllerName->UnicodeName.String,
295 ControllerName->UnicodeName.Length);
296
297 *Information = DriverKey->ActualLength;
298 }
299
300 ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
301
302 return STATUS_SUCCESS;
303 }
304
305 NTSTATUS
306 NTAPI
307 USBPORT_PdoDeviceControl(IN PDEVICE_OBJECT PdoDevice,
308 IN PIRP Irp)
309 {
310 DPRINT1("USBPORT_PdoDeviceControl: UNIMPLEMENTED. FIXME. \n");
311 return 0;
312 }
313
314 NTSTATUS
315 NTAPI
316 USBPORT_PdoInternalDeviceControl(IN PDEVICE_OBJECT PdoDevice,
317 IN PIRP Irp)
318 {
319 PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
320 PIO_STACK_LOCATION IoStack;
321 ULONG IoCtl;
322 NTSTATUS Status;
323
324 PdoExtension = PdoDevice->DeviceExtension;
325 IoStack = IoGetCurrentIrpStackLocation(Irp);
326 IoCtl = IoStack->Parameters.DeviceIoControl.IoControlCode;
327
328 DPRINT("USBPORT_PdoInternalDeviceControl: PdoDevice - %p, Irp - %p, IoCtl - %x\n",
329 PdoDevice,
330 Irp,
331 IoCtl);
332
333 if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_URB)
334 {
335 return USBPORT_HandleSubmitURB(PdoDevice, Irp, URB_FROM_IRP(Irp));
336 }
337
338 if (IoCtl == IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO)
339 {
340 DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
341
342 if (IoStack->Parameters.Others.Argument1)
343 *(PVOID *)IoStack->Parameters.Others.Argument1 = PdoDevice;
344
345 if (IoStack->Parameters.Others.Argument2)
346 *(PVOID *)IoStack->Parameters.Others.Argument2 = PdoDevice;
347
348 Status = STATUS_SUCCESS;
349 goto Exit;
350 }
351
352 if (IoCtl == IOCTL_INTERNAL_USB_GET_HUB_COUNT)
353 {
354 DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
355
356 if (IoStack->Parameters.Others.Argument1)
357 {
358 ++*(PULONG)IoStack->Parameters.Others.Argument1;
359 }
360
361 Status = STATUS_SUCCESS;
362 goto Exit;
363 }
364
365 if (IoCtl == IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE)
366 {
367 DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
368
369 if (IoStack->Parameters.Others.Argument1)
370 {
371 *(PVOID *)IoStack->Parameters.Others.Argument1 = &PdoExtension->DeviceHandle;
372 }
373
374 Status = STATUS_SUCCESS;
375 goto Exit;
376 }
377
378 if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION)
379 {
380 DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
381 return USBPORT_IdleNotification(PdoDevice, Irp);
382 }
383
384 DPRINT("USBPORT_PdoInternalDeviceControl: INVALID INTERNAL DEVICE CONTROL\n");
385 Status = STATUS_INVALID_DEVICE_REQUEST;
386
387 Exit:
388 Irp->IoStatus.Status = Status;
389 IoCompleteRequest(Irp, IO_NO_INCREMENT);
390 return Status;
391 }
392
393 NTSTATUS
394 NTAPI
395 USBPORT_FdoDeviceControl(IN PDEVICE_OBJECT FdoDevice,
396 IN PIRP Irp)
397 {
398 PUSBPORT_DEVICE_EXTENSION FdoExtension;
399 PIO_STACK_LOCATION IoStack;
400 ULONG ControlCode;
401 NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
402 ULONG_PTR Information = 0;
403
404 DPRINT("USBPORT_FdoDeviceControl: Irp - %p\n", Irp);
405
406 FdoExtension = FdoDevice->DeviceExtension;
407
408 IoStack = IoGetCurrentIrpStackLocation(Irp);
409 ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
410
411 switch (ControlCode)
412 {
413 case IOCTL_USB_DIAGNOSTIC_MODE_ON:
414 DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_ON\n");
415 FdoExtension->Flags |= USBPORT_FLAG_DIAGNOSTIC_MODE;
416 break;
417
418 case IOCTL_USB_DIAGNOSTIC_MODE_OFF:
419 DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_OFF\n");
420 FdoExtension->Flags &= ~USBPORT_FLAG_DIAGNOSTIC_MODE;
421 break;
422
423 case IOCTL_USB_GET_NODE_INFORMATION:
424 DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_GET_NODE_INFORMATION\n");
425 Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
426 break;
427
428 case IOCTL_GET_HCD_DRIVERKEY_NAME:
429 DPRINT1("USBPORT_FdoDeviceControl: IOCTL_GET_HCD_DRIVERKEY_NAME\n");
430 Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
431 break;
432
433 case IOCTL_USB_USER_REQUEST:
434 DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_USER_REQUEST UNIMPLEMENTED. FIXME\n");
435 break;
436
437 default:
438 DPRINT1("USBPORT_FdoDeviceControl: Not supported IoControlCode - %x\n",
439 ControlCode);
440 Status = STATUS_INVALID_DEVICE_REQUEST;
441 break;
442 }
443
444 Irp->IoStatus.Status = Status;
445 Irp->IoStatus.Information = Information;
446 IoCompleteRequest(Irp, IO_NO_INCREMENT);
447
448 return Status;
449 }
450
451 NTSTATUS
452 NTAPI
453 USBPORT_FdoInternalDeviceControl(IN PDEVICE_OBJECT FdoDevice,
454 IN PIRP Irp)
455 {
456 DPRINT1("USBPORT_FdoInternalDeviceControl: UNIMPLEMENTED. FIXME. \n");
457 return 0;
458 }