xref: /reactos/drivers/usb/usbport/ioctl.c (revision 80774a2f)
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         ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
280         return STATUS_UNSUCCESSFUL;
281     }
282 
283     ActualLength = sizeof(ULONG) + ControllerName->UnicodeName.Length;
284 
285     DriverKey->ActualLength = ActualLength;
286 
287     if (OutputBufferLength < ActualLength)
288     {
289         DriverKey->DriverKeyName[0] = UNICODE_NULL;
290         *Information = sizeof(USB_UNICODE_NAME);
291     }
292     else
293     {
294         RtlCopyMemory(DriverKey->DriverKeyName,
295                       ControllerName->UnicodeName.String,
296                       ControllerName->UnicodeName.Length);
297 
298         *Information = DriverKey->ActualLength;
299     }
300 
301     ExFreePoolWithTag(ControllerName, USB_PORT_TAG);
302 
303     return STATUS_SUCCESS;
304 }
305 
306 NTSTATUS
307 NTAPI
308 USBPORT_PdoDeviceControl(IN PDEVICE_OBJECT PdoDevice,
309                          IN PIRP Irp)
310 {
311     DPRINT1("USBPORT_PdoDeviceControl: UNIMPLEMENTED. FIXME. \n");
312     return 0;
313 }
314 
315 NTSTATUS
316 NTAPI
317 USBPORT_PdoInternalDeviceControl(IN PDEVICE_OBJECT PdoDevice,
318                                  IN PIRP Irp)
319 {
320     PUSBPORT_RHDEVICE_EXTENSION PdoExtension;
321     PIO_STACK_LOCATION IoStack;
322     ULONG IoCtl;
323     NTSTATUS Status;
324 
325     PdoExtension = PdoDevice->DeviceExtension;
326     IoStack = IoGetCurrentIrpStackLocation(Irp);
327     IoCtl = IoStack->Parameters.DeviceIoControl.IoControlCode;
328 
329     DPRINT("USBPORT_PdoInternalDeviceControl: PdoDevice - %p, Irp - %p, IoCtl - %x\n",
330            PdoDevice,
331            Irp,
332            IoCtl);
333 
334     if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_URB)
335     {
336         return USBPORT_HandleSubmitURB(PdoDevice, Irp, URB_FROM_IRP(Irp));
337     }
338 
339     if (IoCtl == IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO)
340     {
341         DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
342 
343         if (IoStack->Parameters.Others.Argument1)
344             *(PVOID *)IoStack->Parameters.Others.Argument1 = PdoDevice;
345 
346         if (IoStack->Parameters.Others.Argument2)
347             *(PVOID *)IoStack->Parameters.Others.Argument2 = PdoDevice;
348 
349         Status = STATUS_SUCCESS;
350         goto Exit;
351     }
352 
353     if (IoCtl == IOCTL_INTERNAL_USB_GET_HUB_COUNT)
354     {
355         DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
356 
357         if (IoStack->Parameters.Others.Argument1)
358         {
359             ++*(PULONG)IoStack->Parameters.Others.Argument1;
360         }
361 
362         Status = STATUS_SUCCESS;
363         goto Exit;
364     }
365 
366     if (IoCtl == IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE)
367     {
368         DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
369 
370         if (IoStack->Parameters.Others.Argument1)
371         {
372             *(PVOID *)IoStack->Parameters.Others.Argument1 = &PdoExtension->DeviceHandle;
373         }
374 
375         Status = STATUS_SUCCESS;
376         goto Exit;
377     }
378 
379     if (IoCtl == IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION)
380     {
381         DPRINT("USBPORT_PdoInternalDeviceControl: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
382         return USBPORT_IdleNotification(PdoDevice, Irp);
383     }
384 
385     DPRINT("USBPORT_PdoInternalDeviceControl: INVALID INTERNAL DEVICE CONTROL\n");
386     Status = STATUS_INVALID_DEVICE_REQUEST;
387 
388 Exit:
389     Irp->IoStatus.Status = Status;
390     IoCompleteRequest(Irp, IO_NO_INCREMENT);
391     return Status;
392 }
393 
394 NTSTATUS
395 NTAPI
396 USBPORT_FdoDeviceControl(IN PDEVICE_OBJECT FdoDevice,
397                          IN PIRP Irp)
398 {
399     PUSBPORT_DEVICE_EXTENSION FdoExtension;
400     PIO_STACK_LOCATION IoStack;
401     ULONG ControlCode;
402     NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
403     ULONG_PTR Information = 0;
404 
405     DPRINT("USBPORT_FdoDeviceControl: Irp - %p\n", Irp);
406 
407     FdoExtension = FdoDevice->DeviceExtension;
408 
409     IoStack = IoGetCurrentIrpStackLocation(Irp);
410     ControlCode = IoStack->Parameters.DeviceIoControl.IoControlCode;
411 
412     switch (ControlCode)
413     {
414         case IOCTL_USB_DIAGNOSTIC_MODE_ON:
415             DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_ON\n");
416             FdoExtension->Flags |= USBPORT_FLAG_DIAGNOSTIC_MODE;
417             break;
418 
419         case IOCTL_USB_DIAGNOSTIC_MODE_OFF:
420             DPRINT("USBPORT_FdoDeviceControl: IOCTL_USB_DIAGNOSTIC_MODE_OFF\n");
421             FdoExtension->Flags &= ~USBPORT_FLAG_DIAGNOSTIC_MODE;
422             break;
423 
424         case IOCTL_USB_GET_NODE_INFORMATION:
425             DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_GET_NODE_INFORMATION\n");
426             Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
427             break;
428 
429         case IOCTL_GET_HCD_DRIVERKEY_NAME:
430             DPRINT1("USBPORT_FdoDeviceControl: IOCTL_GET_HCD_DRIVERKEY_NAME\n");
431             Status = USBPORT_GetUnicodeName(FdoDevice, Irp, &Information);
432             break;
433 
434         case IOCTL_USB_USER_REQUEST:
435             DPRINT1("USBPORT_FdoDeviceControl: IOCTL_USB_USER_REQUEST UNIMPLEMENTED. FIXME\n");
436             break;
437 
438         default:
439             DPRINT1("USBPORT_FdoDeviceControl: Not supported IoControlCode - %x\n",
440                     ControlCode);
441             Status = STATUS_INVALID_DEVICE_REQUEST;
442             break;
443     }
444 
445     Irp->IoStatus.Status = Status;
446     Irp->IoStatus.Information = Information;
447     IoCompleteRequest(Irp, IO_NO_INCREMENT);
448 
449     return Status;
450 }
451 
452 NTSTATUS
453 NTAPI
454 USBPORT_FdoInternalDeviceControl(IN PDEVICE_OBJECT FdoDevice,
455                                  IN PIRP Irp)
456 {
457     DPRINT1("USBPORT_FdoInternalDeviceControl: UNIMPLEMENTED. FIXME. \n");
458     return 0;
459 }
460