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 } 459