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