Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1588 lines
53 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 2001
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Environment:
  7. kernel mode only
  8. Notes:
  9. Revision History:
  10. --*/
  11. #include <stdio.h>
  12. #include <stddef.h>
  13. #include <wdm.h>
  14. #include <usbscan.h>
  15. #include "usbd_api.h"
  16. #include "private.h"
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE, USDeviceControl)
  19. #pragma alloc_text(PAGE, USReadWriteRegisters)
  20. #pragma alloc_text(PAGE, USCancelPipe)
  21. #pragma alloc_text(PAGE, USAbortResetPipe)
  22. #endif
  23. #ifdef _WIN64
  24. BOOLEAN
  25. IoIs32bitProcess(
  26. IN PIRP Irp
  27. );
  28. #endif // _WIN64
  29. NTSTATUS
  30. USDeviceControl(
  31. IN PDEVICE_OBJECT pDeviceObject,
  32. IN PIRP pIrp
  33. )
  34. /*++
  35. Routine Description:
  36. Arguments:
  37. pDeviceObject - Device object for a device.
  38. pIrp - DEVICE IOCTL irp
  39. Return Value:
  40. NT Status - STATUS_SUCCESS
  41. --*/
  42. {
  43. PIO_STACK_LOCATION pIrpStack;
  44. PIO_STACK_LOCATION pNextIrpStack;
  45. PFILE_OBJECT fileObject;
  46. PUSBSCAN_FILE_CONTEXT pFileContext;
  47. ULONG IoControlCode;
  48. PUSBSCAN_DEVICE_EXTENSION pde;
  49. NTSTATUS Status;
  50. PDRV_VERSION pVersion;
  51. PDEVICE_DESCRIPTOR pDesc;
  52. PUSBSCAN_GET_DESCRIPTOR pGetDesc;
  53. PUSBSCAN_PIPE_CONFIGURATION pPipeConfig;
  54. PVOID pBuffer;
  55. IO_BLOCK LocalIoBlock;
  56. IO_BLOCK_EX LocalIoBlockEx;
  57. PIO_BLOCK pIoBlock;
  58. PIO_BLOCK_EX pIoBlockEx;
  59. ULONG InLength;
  60. ULONG OutLength;
  61. BOOLEAN fRead = FALSE;
  62. BOOLEAN fAbort = TRUE;
  63. ULONG i;
  64. PURB pUrb;
  65. PAGED_CODE();
  66. DebugTrace(TRACE_PROC_ENTER,("USDeviceControl: Enter.. - \n"));
  67. //
  68. // Indicates I/O processing increase.
  69. //
  70. USIncrementIoCount( pDeviceObject );
  71. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  72. if (FALSE == pde -> AcceptingRequests) {
  73. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! IOCTL issued after device stopped/removed!\n"));
  74. Status = STATUS_DELETE_PENDING;
  75. pIrp -> IoStatus.Status = Status;
  76. pIrp -> IoStatus.Information = 0;
  77. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  78. goto USDeviceControl_return;
  79. }
  80. //
  81. // Check device power state.
  82. //
  83. if (PowerDeviceD0 != pde -> CurrentDevicePowerState) {
  84. DebugTrace(TRACE_WARNING,("USDeviceControl: WARNING!! Device is suspended.\n"));
  85. Status = STATUS_DELETE_PENDING;
  86. pIrp -> IoStatus.Status = Status;
  87. pIrp -> IoStatus.Information = 0;
  88. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  89. goto USDeviceControl_return;
  90. }
  91. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  92. pNextIrpStack = IoGetNextIrpStackLocation( pIrp );
  93. IoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
  94. InLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  95. OutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  96. pBuffer = pIrp -> AssociatedIrp.SystemBuffer;
  97. fileObject = pIrpStack->FileObject;
  98. pFileContext = fileObject->FsContext;
  99. DebugTrace(TRACE_STATUS,("USDeviceControl: Control code 0x%x = ", IoControlCode));
  100. switch (IoControlCode) {
  101. case IOCTL_GET_VERSION:
  102. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_VERSION\n"));
  103. if (OutLength < sizeof(DRV_VERSION) ) {
  104. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Buffer(0x%x) too small(<0x%x)\n", OutLength, sizeof(DRV_VERSION)));
  105. DEBUG_BREAKPOINT();
  106. Status = STATUS_INVALID_PARAMETER;
  107. break;
  108. }
  109. pVersion = (PDRV_VERSION)pBuffer;
  110. pVersion->major = 1;
  111. pVersion->minor = 0;
  112. pVersion->internal = 0;
  113. pIrp -> IoStatus.Information = sizeof(DRV_VERSION);
  114. Status = STATUS_SUCCESS;
  115. break;
  116. case IOCTL_CANCEL_IO:
  117. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_CANCEL_IO\n"));
  118. fAbort = TRUE;
  119. //
  120. // Falling through to the next case, this is intentional. We want to reset pipe when
  121. // cancel requested
  122. //
  123. case IOCTL_RESET_PIPE:
  124. if(IOCTL_RESET_PIPE == IoControlCode){
  125. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_RESET_PIPE\n"));
  126. fAbort = FALSE;
  127. }
  128. //
  129. // Validate buffer size
  130. //
  131. if (InLength < sizeof(PIPE_TYPE) ) {
  132. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Pipe type buffer (0x%x bytes) too small\n" ,InLength));
  133. Status = STATUS_INVALID_PARAMETER;
  134. break;
  135. }
  136. Status = USCancelPipe(pDeviceObject,
  137. pIrp,
  138. *(PIPE_TYPE*)pBuffer,
  139. fAbort);
  140. break;
  141. case IOCTL_WAIT_ON_DEVICE_EVENT:
  142. {
  143. ULONG Index;
  144. ULONG Timeout;
  145. PULONG pTimeout;
  146. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_WAIT_ON_DEVICE_EVENT\n"));
  147. Index = USGetPipeIndexToUse(pDeviceObject,
  148. pIrp,
  149. pde -> IndexInterrupt);
  150. if (OutLength < pde -> PipeInfo[Index].MaximumPacketSize) {
  151. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! User buffer(0x%x) too small(<)\n"
  152. , OutLength
  153. , pde -> PipeInfo[Index].MaximumPacketSize));
  154. Status = STATUS_INVALID_PARAMETER;
  155. break;
  156. }
  157. //
  158. // Copy timeout value from file context.
  159. //
  160. Timeout = pFileContext->TimeoutEvent;
  161. //
  162. // If timeout value is 0, then never timeout.
  163. //
  164. if(0 == Timeout){
  165. pTimeout = NULL;
  166. } else {
  167. DebugTrace(TRACE_STATUS,("USDeviceControl: Timeout is set to 0x%x sec.\n", Timeout));
  168. pTimeout = &Timeout;
  169. }
  170. Status = USTransfer(pDeviceObject,
  171. pIrp,
  172. Index,
  173. pIrp -> AssociatedIrp.SystemBuffer,
  174. NULL,
  175. pde -> PipeInfo[Index].MaximumPacketSize,
  176. pTimeout);
  177. //
  178. // IRP should be completed in USTransfer or its completion routine.
  179. //
  180. goto USDeviceControl_return;
  181. }
  182. case IOCTL_READ_REGISTERS:
  183. fRead = TRUE;
  184. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_READ_REGISTERS\n"));
  185. case IOCTL_WRITE_REGISTERS:{
  186. if (IOCTL_WRITE_REGISTERS == IoControlCode) {
  187. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_WRITE_REGISTERS\n"));
  188. fRead = FALSE;
  189. }
  190. #ifdef _WIN64
  191. if(IoIs32bitProcess(pIrp)){
  192. PIO_BLOCK_32 pIoBlock32;
  193. if (InLength < sizeof(IO_BLOCK_32) ) {
  194. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  195. , InLength,
  196. sizeof(IO_BLOCK_32)));
  197. Status = STATUS_INVALID_PARAMETER;
  198. break;
  199. }
  200. //
  201. // Copy all parameters from 32bit structure.
  202. //
  203. pIoBlock32 = (PIO_BLOCK_32)pBuffer;
  204. pIoBlock = &LocalIoBlock;
  205. pIoBlock -> uOffset = pIoBlock32 -> uOffset;
  206. pIoBlock -> uLength = pIoBlock32 -> uLength;
  207. pIoBlock -> pbyData = pIoBlock32 -> pbyData;
  208. pIoBlock -> uIndex = pIoBlock32 -> uIndex;
  209. } else { // if(IoIs32bitProcess(pIrp))
  210. #endif // _WIN64
  211. if (InLength < sizeof(IO_BLOCK) ) {
  212. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input buffer size(0x%x<0x%x)\n"
  213. , InLength,
  214. sizeof(IO_BLOCK)));
  215. Status = STATUS_INVALID_PARAMETER;
  216. break;
  217. }
  218. pIoBlock = (PIO_BLOCK)pBuffer;
  219. #ifdef _WIN64
  220. } // if(IoIs32bitProcess(pIrp))
  221. #endif // _WIN64
  222. if(TRUE == fRead){
  223. //
  224. // Check the size of Output buffer.
  225. //
  226. if (OutLength < pIoBlock -> uLength) {
  227. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) too small(<0x%x)\n"
  228. , OutLength
  229. , pIoBlock -> uLength));
  230. Status = STATUS_INVALID_PARAMETER;
  231. break;
  232. } // if (OutLength < pIoBlock -> uLength)
  233. } // if(TRUE == fRead)
  234. pIrp -> IoStatus.Information = pIoBlock -> uLength;
  235. //
  236. // Caller gives us a pointer, embedded into IOCTL buffer. If call is made from
  237. // user-mode , we need to validate that given pointer is readable.
  238. //
  239. if (pIrp->RequestorMode != KernelMode) {
  240. try {
  241. ProbeForRead(pIoBlock->pbyData,
  242. pIoBlock -> uLength,
  243. sizeof(UCHAR));
  244. } except(EXCEPTION_EXECUTE_HANDLER) {
  245. DebugTrace(TRACE_ERROR,("USDeviceControl: Read/Write registers buffer pointer is invalid\n"));
  246. DEBUG_BREAKPOINT();
  247. Status = GetExceptionCode();
  248. pIrp -> IoStatus.Information = 0;
  249. break;
  250. } // except
  251. } // !kernelmode
  252. //
  253. // Now go to worker function
  254. //
  255. Status = USReadWriteRegisters(pDeviceObject,
  256. pIoBlock,
  257. fRead,
  258. InLength);
  259. if (STATUS_SUCCESS != Status) {
  260. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USReadWriteRegisters failed\n"));
  261. DEBUG_BREAKPOINT();
  262. pIrp -> IoStatus.Information = 0;
  263. }
  264. break;
  265. } // case IOCTL_WRITE_REGISTERS:
  266. case IOCTL_GET_CHANNEL_ALIGN_RQST:
  267. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_CHANNEL_ALIGN_REQUEST\n"));
  268. if (OutLength < sizeof(CHANNEL_INFO) ) {
  269. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Buffer(0x%x) too small(<0x%x)\n"
  270. , OutLength
  271. ,sizeof(CHANNEL_INFO)));
  272. Status = STATUS_INVALID_PARAMETER;
  273. break;
  274. }
  275. pIoBlock = (PIO_BLOCK)pBuffer;
  276. RtlZeroMemory((PCHANNEL_INFO)pIoBlock, sizeof(CHANNEL_INFO));
  277. for (i = 0; i < pde -> NumberOfPipes; i++) {
  278. //
  279. // Have to check which pipe to use
  280. //
  281. ULONG Index;
  282. Index = USGetPipeIndexToUse(pDeviceObject,
  283. pIrp,
  284. i);
  285. switch (pde -> PipeInfo[Index].PipeType) {
  286. case USB_ENDPOINT_TYPE_INTERRUPT:
  287. ((PCHANNEL_INFO)pIoBlock)->EventChannelSize = pde -> PipeInfo[Index].MaximumPacketSize;
  288. break;
  289. case USB_ENDPOINT_TYPE_BULK:
  290. if (pde -> pEndpointDescriptor[Index].bEndpointAddress & BULKIN_FLAG) {
  291. ((PCHANNEL_INFO)pIoBlock) -> uReadDataAlignment = pde -> PipeInfo[Index].MaximumPacketSize;
  292. } else {
  293. ((PCHANNEL_INFO)pIoBlock) -> uWriteDataAlignment = pde -> PipeInfo[Index].MaximumPacketSize;
  294. }
  295. break;
  296. }
  297. }
  298. pIrp -> IoStatus.Information = sizeof(CHANNEL_INFO);
  299. Status = STATUS_SUCCESS;
  300. break;
  301. case IOCTL_GET_DEVICE_DESCRIPTOR:
  302. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_DEVICE_DESCRIPTOR\n"));
  303. if (OutLength < sizeof(DEVICE_DESCRIPTOR)) {
  304. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) is too small(<0x%x)\n"
  305. , OutLength
  306. , sizeof(DEVICE_DESCRIPTOR)));
  307. Status = STATUS_INVALID_PARAMETER_6;
  308. break;
  309. }
  310. pDesc = (PDEVICE_DESCRIPTOR)pBuffer;
  311. pDesc -> usVendorId = pde -> pDeviceDescriptor -> idVendor;
  312. pDesc -> usProductId = pde -> pDeviceDescriptor -> idProduct;
  313. pDesc -> usBcdDevice = pde -> pDeviceDescriptor -> bcdDevice;
  314. DebugTrace(TRACE_STATUS,("USDeviceControl: Vendor ID:%d\n", pDesc -> usVendorId));
  315. DebugTrace(TRACE_STATUS,("USDeviceControl: Product ID:%d\n", pDesc -> usProductId));
  316. DebugTrace(TRACE_STATUS,("USDeviceControl: BcdDevice:%d\n", pDesc -> usBcdDevice));
  317. pIrp -> IoStatus.Information = sizeof(DEVICE_DESCRIPTOR);
  318. Status = STATUS_SUCCESS;
  319. break;
  320. case IOCTL_GET_USB_DESCRIPTOR:
  321. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_USB_DESCRIPTOR\n"));
  322. if (OutLength < sizeof(USBSCAN_GET_DESCRIPTOR)) {
  323. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Out buffer(0x%x) is too small(<0x%x)\n"
  324. , OutLength
  325. , sizeof(USBSCAN_GET_DESCRIPTOR)));
  326. Status = STATUS_INVALID_PARAMETER_6;
  327. break;
  328. }
  329. pGetDesc = (PUSBSCAN_GET_DESCRIPTOR)pBuffer;
  330. pUrb = USAllocatePool(NonPagedPool,
  331. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  332. if (NULL == pUrb) {
  333. DebugTrace(TRACE_CRITICAL,("USDeviceControl: ERROR!! Can't allocate control descriptor URB.\n"));
  334. DEBUG_BREAKPOINT();
  335. Status = STATUS_INSUFFICIENT_RESOURCES;
  336. break;
  337. }
  338. #ifdef DEBUG
  339. switch(pGetDesc -> DescriptorType){
  340. case USB_DEVICE_DESCRIPTOR_TYPE:
  341. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_DEVICE_DESCRIPTOR_TYPE\n"));
  342. break;
  343. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  344. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_CONFIGURATION_DESCRIPTOR_TYPE\n"));
  345. break;
  346. case USB_STRING_DESCRIPTOR_TYPE:
  347. DebugTrace(TRACE_STATUS,("USDeviceControl: USB_STRING_DESCRIPTOR_TYPE\n"));
  348. break;
  349. default:
  350. DebugTrace(TRACE_WARNING,("USDeviceControl: WARNING!! 0x%x = Undefined.\n", pGetDesc -> DescriptorType));
  351. Status = STATUS_INVALID_PARAMETER_3;
  352. USFreePool(pUrb);
  353. pUrb = NULL;
  354. pIrp -> IoStatus.Information = 0;
  355. goto USDeviceControl_return;
  356. }
  357. DebugTrace(TRACE_STATUS, ("USDeviceControl: Index :%d\n",pGetDesc -> Index));
  358. DebugTrace(TRACE_STATUS, ("USDeviceControl: LanguageID :%d\n", pGetDesc -> LanguageId));
  359. #endif //DEBUG
  360. UsbBuildGetDescriptorRequest(pUrb,
  361. (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  362. pGetDesc -> DescriptorType,
  363. pGetDesc -> Index,
  364. pGetDesc -> LanguageId,
  365. pBuffer,
  366. NULL,
  367. OutLength,
  368. NULL);
  369. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  370. #ifdef DEBUG
  371. if ( (STATUS_SUCCESS == Status)
  372. // && (USB_DEVICE_DESCRIPTOR_TYPE == pGetDesc -> DescriptorType)
  373. )
  374. {
  375. PUSB_DEVICE_DESCRIPTOR pDeviceDescriptor;
  376. pDeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)pBuffer;
  377. DebugTrace(TRACE_STATUS,("USDeviceControl: Device Descriptor = %x, len %x\n",
  378. pDeviceDescriptor,
  379. pUrb->UrbControlDescriptorRequest.TransferBufferLength));
  380. DebugTrace(TRACE_STATUS,("USDeviceControl: USBSCAN Device Descriptor:\n"));
  381. DebugTrace(TRACE_STATUS,("USDeviceControl: -------------------------\n"));
  382. DebugTrace(TRACE_STATUS,("USDeviceControl: bLength %d\n", pDeviceDescriptor->bLength));
  383. DebugTrace(TRACE_STATUS,("USDeviceControl: bDescriptorType 0x%x\n", pDeviceDescriptor->bDescriptorType));
  384. DebugTrace(TRACE_STATUS,("USDeviceControl: bcdUSB 0x%x\n", pDeviceDescriptor->bcdUSB));
  385. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceClass 0x%x\n", pDeviceDescriptor->bDeviceClass));
  386. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceSubClass 0x%x\n", pDeviceDescriptor->bDeviceSubClass));
  387. DebugTrace(TRACE_STATUS,("USDeviceControl: bDeviceProtocol 0x%x\n", pDeviceDescriptor->bDeviceProtocol));
  388. DebugTrace(TRACE_STATUS,("USDeviceControl: bMaxPacketSize0 0x%x\n", pDeviceDescriptor->bMaxPacketSize0));
  389. DebugTrace(TRACE_STATUS,("USDeviceControl: idVendor 0x%x\n", pDeviceDescriptor->idVendor));
  390. DebugTrace(TRACE_STATUS,("USDeviceControl: idProduct 0x%x\n", pDeviceDescriptor->idProduct));
  391. DebugTrace(TRACE_STATUS,("USDeviceControl: bcdDevice 0x%x\n", pDeviceDescriptor->bcdDevice));
  392. DebugTrace(TRACE_STATUS,("USDeviceControl: iManufacturer 0x%x\n", pDeviceDescriptor->iManufacturer));
  393. DebugTrace(TRACE_STATUS,("USDeviceControl: iProduct 0x%x\n", pDeviceDescriptor->iProduct));
  394. DebugTrace(TRACE_STATUS,("USDeviceControl: iSerialNumber 0x%x\n", pDeviceDescriptor->iSerialNumber));
  395. DebugTrace(TRACE_STATUS,("USDeviceControl: bNumConfigurations 0x%x\n", pDeviceDescriptor->bNumConfigurations));
  396. } else {
  397. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR! Status = %d\n", Status));
  398. }
  399. #endif //DEBUG
  400. USFreePool(pUrb);
  401. pUrb = NULL;
  402. pIrp -> IoStatus.Information = ((PUSB_DEVICE_DESCRIPTOR)pBuffer)->bLength;
  403. break;
  404. case IOCTL_SEND_USB_REQUEST:
  405. {
  406. //
  407. // Generic pass-through mechanism for USB vendor requests.
  408. //
  409. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SEND_USB_REQUEST\n"));
  410. //
  411. // Validate length parameters.
  412. //
  413. #ifdef _WIN64
  414. if(IoIs32bitProcess(pIrp)){
  415. PIO_BLOCK_EX_32 pIoBlockEx32;
  416. if (InLength < sizeof(IO_BLOCK_EX_32) ) {
  417. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  418. , InLength,
  419. sizeof(IO_BLOCK_EX_32)));
  420. Status = STATUS_INVALID_PARAMETER;
  421. break;
  422. }
  423. //
  424. // Copy all parameters from 32bit structure.
  425. //
  426. pIoBlockEx32 = (PIO_BLOCK_EX_32)pBuffer;
  427. pIoBlockEx = &LocalIoBlockEx;
  428. pIoBlockEx -> uOffset = pIoBlockEx32 -> uOffset;
  429. pIoBlockEx -> uLength = pIoBlockEx32 -> uLength;
  430. pIoBlockEx -> pbyData = pIoBlockEx32 -> pbyData;
  431. pIoBlockEx -> uIndex = pIoBlockEx32 -> uIndex;
  432. pIoBlockEx -> bRequest = pIoBlockEx32 -> bRequest;
  433. pIoBlockEx -> bmRequestType = pIoBlockEx32 -> bmRequestType;
  434. pIoBlockEx -> fTransferDirectionIn = pIoBlockEx32 -> fTransferDirectionIn;
  435. } else { // if(IoIs32bitProcess(pIrp))
  436. #endif // _WIN64
  437. if (InLength < sizeof(IO_BLOCK_EX) ) {
  438. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! I/O buffer(0x%x) too small(<0x%x)\n"
  439. , InLength
  440. , sizeof(IO_BLOCK_EX)));
  441. Status = STATUS_INVALID_PARAMETER;
  442. break;
  443. }
  444. pIoBlockEx = (PIO_BLOCK_EX)pBuffer;
  445. #ifdef _WIN64
  446. } // if(IoIs32bitProcess(pIrp))
  447. #endif // _WIN64
  448. if (pIoBlockEx->fTransferDirectionIn) {
  449. //
  450. // Check output buffer length is valid.
  451. //
  452. if (OutLength < pIoBlockEx -> uLength) {
  453. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! OutLength too small\n"));
  454. DEBUG_BREAKPOINT();
  455. Status = STATUS_INVALID_PARAMETER;
  456. pIrp -> IoStatus.Information = 0;
  457. break;
  458. }
  459. pIrp -> IoStatus.Information = pIoBlockEx -> uLength;
  460. } else {
  461. //
  462. // No output to the caller.
  463. //
  464. pIrp -> IoStatus.Information = 0;
  465. }
  466. //
  467. // Validate user buffer.
  468. //
  469. if (pIrp->RequestorMode != KernelMode) {
  470. try {
  471. ProbeForRead(pIoBlockEx->pbyData,
  472. pIoBlockEx->uLength,
  473. sizeof(UCHAR));
  474. } except(EXCEPTION_EXECUTE_HANDLER) {
  475. DebugTrace(TRACE_ERROR,("USDeviceControl: User buffer pointer is invalid\n"));
  476. Status = GetExceptionCode();
  477. pIrp -> IoStatus.Information = 0;
  478. break;
  479. } // except
  480. } // !kernelmode
  481. //
  482. // Now go to worker function
  483. //
  484. Status = USPassThruUSBRequest(pDeviceObject,
  485. (PIO_BLOCK_EX)pBuffer,
  486. InLength,
  487. OutLength
  488. );
  489. if (STATUS_SUCCESS != Status) {
  490. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USPassThruUSBRequest failed\n"));
  491. DEBUG_BREAKPOINT();
  492. pIrp -> IoStatus.Information = 0;
  493. }
  494. break;
  495. } // case IOCTL_SEND_USB_REQUEST:
  496. case IOCTL_SEND_USB_REQUEST_PTP:
  497. {
  498. //
  499. // Generic pass-through mechanism for USB vendor requests.
  500. //
  501. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SEND_USB_REQUEST_PTP\n"));
  502. //
  503. // Validate length parameters.
  504. //
  505. #ifdef _WIN64
  506. if(IoIs32bitProcess(pIrp)){
  507. PIO_BLOCK_EX_32 pIoBlockEx32;
  508. if (InLength < sizeof(IO_BLOCK_EX_32) ) {
  509. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input 32bit buffer size(0x%x<0x%x)\n"
  510. , InLength,
  511. sizeof(IO_BLOCK_EX_32)));
  512. Status = STATUS_INVALID_PARAMETER;
  513. break;
  514. }
  515. //
  516. // Copy all parameters from 32bit structure.
  517. //
  518. pIoBlockEx32 = (PIO_BLOCK_EX_32)pBuffer;
  519. pIoBlockEx = &LocalIoBlockEx;
  520. pIoBlockEx -> uOffset = pIoBlockEx32 -> uOffset;
  521. pIoBlockEx -> uLength = pIoBlockEx32 -> uLength;
  522. pIoBlockEx -> pbyData = pIoBlockEx32 -> pbyData;
  523. pIoBlockEx -> uIndex = pIoBlockEx32 -> uIndex;
  524. pIoBlockEx -> bRequest = pIoBlockEx32 -> bRequest;
  525. pIoBlockEx -> bmRequestType = pIoBlockEx32 -> bmRequestType;
  526. pIoBlockEx -> fTransferDirectionIn = pIoBlockEx32 -> fTransferDirectionIn;
  527. } else { // if(IoIs32bitProcess(pIrp))
  528. #endif // _WIN64
  529. if (InLength < sizeof(IO_BLOCK_EX) ) {
  530. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! I/O buffer(0x%x) too small(<0x%x)\n"
  531. , InLength
  532. , sizeof(IO_BLOCK_EX)));
  533. Status = STATUS_INVALID_PARAMETER;
  534. break;
  535. }
  536. pIoBlockEx = (PIO_BLOCK_EX)pBuffer;
  537. #ifdef _WIN64
  538. } // if(IoIs32bitProcess(pIrp))
  539. #endif // _WIN64
  540. if (pIoBlockEx->fTransferDirectionIn) {
  541. //
  542. // Check output buffer length is valid.
  543. //
  544. if (OutLength < pIoBlockEx -> uLength) {
  545. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! OutLength too small\n"));
  546. DEBUG_BREAKPOINT();
  547. Status = STATUS_INVALID_PARAMETER;
  548. pIrp -> IoStatus.Information = 0;
  549. break;
  550. }
  551. pIrp -> IoStatus.Information = pIoBlockEx -> uLength;
  552. } else {
  553. //
  554. // No output to the caller.
  555. //
  556. pIrp -> IoStatus.Information = 0;
  557. }
  558. //
  559. // Validate user buffer.
  560. //
  561. if (pIrp->RequestorMode != KernelMode) {
  562. try {
  563. ProbeForRead(pIoBlockEx->pbyData,
  564. pIoBlockEx->uLength,
  565. sizeof(UCHAR));
  566. } except(EXCEPTION_EXECUTE_HANDLER) {
  567. DebugTrace(TRACE_ERROR,("USDeviceControl: User buffer pointer is invalid\n"));
  568. Status = GetExceptionCode();
  569. pIrp -> IoStatus.Information = 0;
  570. break;
  571. } // except
  572. } // !kernelmode
  573. //
  574. // Now go to worker function
  575. //
  576. Status = USPassThruUSBRequestPTP(pDeviceObject,
  577. (PIO_BLOCK_EX)pBuffer,
  578. InLength,
  579. OutLength);
  580. if (STATUS_SUCCESS != Status) {
  581. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! USPassThruUSBRequestPTP failed\n"));
  582. DEBUG_BREAKPOINT();
  583. pIrp -> IoStatus.Information = 0;
  584. }
  585. break;
  586. } // case IOCTL_SEND_USB_REQUEST_PTP:
  587. case IOCTL_GET_PIPE_CONFIGURATION:
  588. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_GET_PIPE_CONFIGURATION\n"));
  589. //
  590. // Check output buffer length
  591. //
  592. if (OutLength < sizeof(USBSCAN_PIPE_CONFIGURATION)) {
  593. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! GetPipeConfig buffer(0x%x) too small(<0x%x)\n"
  594. , OutLength
  595. , sizeof(USBSCAN_PIPE_CONFIGURATION)));
  596. Status = STATUS_INVALID_PARAMETER_6;
  597. break;
  598. }
  599. //
  600. // Copy Pipe configuration to user buffer.
  601. //
  602. pPipeConfig = (PUSBSCAN_PIPE_CONFIGURATION)pBuffer;
  603. RtlZeroMemory(pPipeConfig, sizeof(USBSCAN_PIPE_CONFIGURATION));
  604. pPipeConfig->NumberOfPipes = pde->NumberOfPipes;
  605. for(i=0; i < pPipeConfig->NumberOfPipes; i++){
  606. pPipeConfig->PipeInfo[i].MaximumPacketSize = pde->PipeInfo[i].MaximumPacketSize;
  607. pPipeConfig->PipeInfo[i].EndpointAddress = pde->PipeInfo[i].EndpointAddress;
  608. pPipeConfig->PipeInfo[i].Interval = pde->PipeInfo[i].Interval;
  609. pPipeConfig->PipeInfo[i].PipeType = pde->PipeInfo[i].PipeType;
  610. }
  611. pIrp -> IoStatus.Information = sizeof(USBSCAN_PIPE_CONFIGURATION);
  612. Status = STATUS_SUCCESS;
  613. break;
  614. case IOCTL_SET_TIMEOUT:
  615. DebugTrace(TRACE_STATUS,("USDeviceControl: IOCTL_SET_TIMEOUT\n"));
  616. //
  617. // Make sure input buffer size is big enough.
  618. //
  619. if(sizeof(USBSCAN_TIMEOUT) > InLength){
  620. //
  621. // Incorrect Input buffer size.
  622. //
  623. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Invalid input buffer size\n"));
  624. Status = STATUS_INVALID_PARAMETER;
  625. break;
  626. }
  627. //
  628. // Copy timeout value.
  629. //
  630. pFileContext -> TimeoutRead = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutRead;
  631. pFileContext -> TimeoutWrite = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutWrite;
  632. pFileContext -> TimeoutEvent = ((PUSBSCAN_TIMEOUT)pBuffer) -> TimeoutEvent;
  633. pIrp -> IoStatus.Information = 0;
  634. Status = STATUS_SUCCESS;
  635. break;
  636. default:
  637. DebugTrace(TRACE_ERROR,("USDeviceControl: ERROR!! Unsupported IOCTL\n"));
  638. Status = STATUS_NOT_SUPPORTED;
  639. break;
  640. }
  641. pIrp -> IoStatus.Status = Status;
  642. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  643. USDeviceControl_return:
  644. USDecrementIoCount(pDeviceObject);
  645. DebugTrace(TRACE_PROC_LEAVE,("USDeviceControl: Leaving.. Status = 0x%x\n", Status));
  646. return Status;
  647. } // end USDeviceControl()
  648. NTSTATUS
  649. USReadWriteRegisters(
  650. IN PDEVICE_OBJECT pDeviceObject,
  651. IN PIO_BLOCK pIoBlock,
  652. IN BOOLEAN fRead,
  653. IN ULONG IoBlockSize
  654. )
  655. /*++
  656. Routine Description:
  657. Arguments:
  658. Return Value:
  659. --*/
  660. {
  661. NTSTATUS Status;
  662. PUSBSCAN_DEVICE_EXTENSION pde;
  663. PURB pUrb;
  664. ULONG siz;
  665. UCHAR Request;
  666. PVOID pBuffer = NULL;
  667. //USHORT uIndex;
  668. unsigned uIndex;
  669. PAGED_CODE();
  670. DebugTrace(TRACE_PROC_ENTER,("USReadWriteRegisters: Enter..\n"));
  671. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  672. //
  673. // Allocate URB
  674. //
  675. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  676. pUrb = USAllocatePool(NonPagedPool, siz);
  677. if (NULL == pUrb) {
  678. DebugTrace(TRACE_CRITICAL,("USReadWriteRegisters: ERROR!! cannot allocated URB\n"));
  679. DEBUG_BREAKPOINT();
  680. Status = STATUS_INSUFFICIENT_RESOURCES;
  681. goto USReadWriteRegisters_return;
  682. }
  683. RtlZeroMemory(pUrb, siz);
  684. //
  685. // Setup URB
  686. //
  687. Request = REGISTER_AREA;
  688. if (pIoBlock -> uLength > 1) {
  689. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: ULength > 1, turning on automatic increment\n"));
  690. Request |= OPCODE_SEQ_TRANSFER; // automatic address increment after the read
  691. } else {
  692. Request |= OPCODE_SINGLE_ADDR_TRANSFER; // no address increment after the read
  693. }
  694. //
  695. // Reading registers will read into pIoBlock itself.
  696. //
  697. pBuffer = pIoBlock;
  698. //
  699. // If we are writing registers, then we need to make a copy of the
  700. // register block into a non-paged block of memory before handing it off
  701. // to usbd.
  702. //
  703. if (!fRead) {
  704. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: Write request, allocating non-paged reg buffer, len = %d\n",pIoBlock->uLength));
  705. pBuffer = USAllocatePool(NonPagedPool, pIoBlock->uLength);
  706. if (NULL == pBuffer) {
  707. DebugTrace(TRACE_CRITICAL,("USReadWriteRegisters: ERROR!! cannot allocate write reg buffer\n"));
  708. DEBUG_BREAKPOINT();
  709. USFreePool(pUrb);
  710. pUrb = NULL;
  711. Status = STATUS_INSUFFICIENT_RESOURCES;
  712. goto USReadWriteRegisters_return;
  713. }
  714. //
  715. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  716. // validate that given pointer is readable.
  717. //
  718. try{
  719. RtlCopyMemory(pBuffer,
  720. pIoBlock->pbyData,
  721. pIoBlock->uLength);
  722. } except(EXCEPTION_EXECUTE_HANDLER) {
  723. //
  724. // Caller buffer is not valid, or worse..
  725. //
  726. DebugTrace(TRACE_ERROR,("USReadWriteRegisters: ERROR!! Copying caller buffer failed.\n"));
  727. DEBUG_BREAKPOINT();
  728. Status = GetExceptionCode();
  729. //
  730. // Clear allocated pool
  731. //
  732. USFreePool(pUrb);
  733. USFreePool(pBuffer);
  734. pUrb = NULL;
  735. pBuffer = NULL;
  736. goto USReadWriteRegisters_return;
  737. }
  738. }
  739. //
  740. // If the IoBlock is new style (Intel has added a uIndex field to the end of it),
  741. // then make sure we pass the corrected uIndex value to usbd.
  742. //
  743. uIndex = 0;
  744. if (IoBlockSize == sizeof(IO_BLOCK)) {
  745. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: New (intel) style IoBlock -- setting uIndex to pIoBlock -> uIndex\n"));
  746. uIndex = pIoBlock -> uIndex;
  747. }
  748. UsbBuildVendorClassSpecificCommand(pUrb,
  749. fRead ? USBD_TRANSFER_DIRECTION_IN : 0,
  750. pIoBlock->uLength,
  751. pBuffer,
  752. NULL,
  753. fRead ? 0xc0 : 0x40,
  754. Request,
  755. (SHORT)pIoBlock->uOffset,
  756. (USHORT)uIndex);
  757. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  758. if (!fRead) {
  759. DebugTrace(TRACE_STATUS,("USReadWriteRegisters: freeing temp reg buffer\n"));
  760. USFreePool(pBuffer);
  761. pBuffer = NULL;
  762. }
  763. USFreePool(pUrb);
  764. pUrb = NULL;
  765. USReadWriteRegisters_return:
  766. if(!NT_SUCCESS(Status)){
  767. DebugTrace(TRACE_ERROR,("USReadWriteRegisters: ERROR!! Still had unfreed pointer. Free it...\n"));
  768. if(pUrb){
  769. USFreePool(pUrb);
  770. }
  771. if( (pBuffer)
  772. && (!fRead ) )
  773. {
  774. USFreePool(pBuffer);
  775. }
  776. }
  777. DebugTrace(TRACE_PROC_LEAVE,("USReadWriteRegisters: Leaving.. Status = 0x%x\n", Status));
  778. return Status;
  779. }
  780. NTSTATUS
  781. USCancelPipe(
  782. IN PDEVICE_OBJECT pDeviceObject,
  783. IN PIRP pIrp,
  784. IN PIPE_TYPE PipeType,
  785. IN BOOLEAN fAbort // TRUE = Abort, FALSE = Reset
  786. )
  787. /*++
  788. Routine Description:
  789. Cansel URB or reset pipe. If PipeType is PIPE_ALL, it applies to every pipes a device has.
  790. If not, it applies to only one default pipe even if a device supports multipul same type of pipes.
  791. Arguments:
  792. pDeviceObject - Pointer to Device Object
  793. pIrp - Can be NULL if PipeType is ALL_PIPE
  794. PipeType - Specifies type of pipe
  795. fAbort - Specifies type of operation
  796. Return Value:
  797. Returns status
  798. --*/
  799. {
  800. NTSTATUS Status, temp;
  801. PUSBSCAN_DEVICE_EXTENSION pde;
  802. PAGED_CODE();
  803. // DebugTrace(TRACE_PROC_ENTER,("USCancelPipe: Enter.. - "));
  804. Status = STATUS_SUCCESS;
  805. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  806. switch (PipeType) {
  807. case EVENT_PIPE:
  808. DebugTrace(TRACE_STATUS,("USCancelPipe: EVENT_PIPE\n"));
  809. if(NULL == pIrp){
  810. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  811. break;
  812. }
  813. if (-1 == pde -> IndexInterrupt) {
  814. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! Interrupt pipe not valid\n"));
  815. DEBUG_BREAKPOINT();
  816. Status = STATUS_NOT_SUPPORTED;
  817. break;
  818. }
  819. Status = USAbortResetPipe(pDeviceObject,
  820. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexInterrupt),
  821. fAbort);
  822. DebugTrace(TRACE_STATUS,("Event Pipe aborted/reset, Status = 0x%x\n",Status));
  823. break;
  824. case READ_DATA_PIPE:
  825. DebugTrace(TRACE_STATUS,("USCancelPipe: READ_DATA_PIPE\n"));
  826. if(NULL == pIrp){
  827. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  828. break;
  829. }
  830. if (-1 == pde -> IndexBulkIn) {
  831. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! bulk-in pipe not valid\n"));
  832. DEBUG_BREAKPOINT();
  833. Status = STATUS_NOT_SUPPORTED;
  834. break;
  835. }
  836. Status = USAbortResetPipe(pDeviceObject,
  837. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexBulkIn),
  838. fAbort);
  839. DebugTrace(TRACE_STATUS,("USCancelPipe: Read Pipe aborted/reset, Status = 0x%x\n",Status));
  840. break;
  841. case WRITE_DATA_PIPE:
  842. DebugTrace(TRACE_STATUS,("USCancelPipe: WRITE_DATA_PIPE\n"));
  843. if(NULL == pIrp){
  844. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! pIrp not valid\n"));
  845. break;
  846. }
  847. if (-1 == pde -> IndexBulkOut) {
  848. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! bulk-out pipe not valid\n"));
  849. DEBUG_BREAKPOINT();
  850. Status = STATUS_NOT_SUPPORTED;
  851. break;
  852. }
  853. Status = USAbortResetPipe(pDeviceObject,
  854. USGetPipeIndexToUse(pDeviceObject, pIrp, pde -> IndexBulkOut),
  855. fAbort);
  856. DebugTrace(TRACE_STATUS,("Write Pipe aborted/reset, Status = 0x%x\n",Status));
  857. break;
  858. case ALL_PIPE:
  859. {
  860. ULONG i;
  861. DebugTrace(TRACE_STATUS,("USCancelPipe: ALL_PIPE\n"));
  862. for(i=0; i < pde -> NumberOfPipes; i++){
  863. temp = USAbortResetPipe(pDeviceObject, i, fAbort);
  864. // DebugTrace(TRACE_STATUS,("USCancelPipe: pipe[%d] aborted/reset, Status = 0x%x\n", i, temp));
  865. if(STATUS_SUCCESS != temp){
  866. Status = temp;
  867. }
  868. }
  869. break;
  870. }
  871. default:
  872. DebugTrace(TRACE_ERROR,("USCancelPipe: ERROR!! INVALID_PIPE\n"));
  873. Status = STATUS_INVALID_PARAMETER;
  874. break;
  875. }
  876. DebugTrace(TRACE_PROC_LEAVE,("USCancelPipe: Leaving.. Status = 0x%x\n", Status));
  877. return Status;
  878. }
  879. NTSTATUS
  880. USAbortResetPipe(
  881. IN PDEVICE_OBJECT pDeviceObject,
  882. IN ULONG uIndex,
  883. IN BOOLEAN fAbort // TRUE = Abort, FALSE = Reset
  884. )
  885. /*++
  886. Routine Description:
  887. Arguments:
  888. Return Value:
  889. --*/
  890. {
  891. NTSTATUS Status = STATUS_SUCCESS;
  892. NTSTATUS StatusReset = STATUS_SUCCESS;
  893. PUSBSCAN_DEVICE_EXTENSION pde;
  894. PURB pUrb;
  895. ULONG siz;
  896. PAGED_CODE();
  897. DebugTrace(TRACE_PROC_ENTER,("USAbortResetPipe: Enter... \n"));
  898. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  899. pUrb = NULL;
  900. //
  901. // Allocate URB
  902. //
  903. siz = sizeof(struct _URB_PIPE_REQUEST);
  904. pUrb = USAllocatePool(NonPagedPool, siz);
  905. if (NULL == pUrb) {
  906. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! cannot allocated URB\n"));
  907. DEBUG_BREAKPOINT();
  908. Status = STATUS_INSUFFICIENT_RESOURCES;
  909. goto USAbortResetPipe_return;
  910. }
  911. RtlZeroMemory(pUrb, siz);
  912. if (fAbort) {
  913. DebugTrace(TRACE_STATUS,("USAbortResetPipe: Aborting pipe[%d]\n", uIndex));
  914. //
  915. // Issue abort pipe call to USBD.
  916. //
  917. UsbBuildAbortPipeRequest(pUrb,
  918. siz,
  919. pde -> PipeInfo[uIndex].PipeHandle);
  920. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  921. if (STATUS_SUCCESS != Status) {
  922. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! Abort pipe failed. Status = 0x%x\n",Status));
  923. goto USAbortResetPipe_return;
  924. }
  925. UsbBuildResetPipeRequest(pUrb,
  926. siz,
  927. pde -> PipeInfo[uIndex].PipeHandle);
  928. StatusReset = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  929. if (STATUS_SUCCESS != StatusReset) {
  930. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! resetting pipe. Status = 0x%x\n",StatusReset));
  931. goto USAbortResetPipe_return;
  932. }
  933. } else {
  934. DebugTrace(TRACE_STATUS,("Reseting pipe[%d]\n", uIndex));
  935. //
  936. // Issue reset pipe call to USBD.
  937. //
  938. UsbBuildResetPipeRequest(pUrb,
  939. siz,
  940. pde -> PipeInfo[uIndex].PipeHandle);
  941. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  942. if (STATUS_SUCCESS != Status) {
  943. DebugTrace(TRACE_ERROR,("USAbortResetPipe: ERROR!! Reset pipe failed. Status = 0x%x\n",Status));
  944. goto USAbortResetPipe_return;
  945. }
  946. }
  947. USAbortResetPipe_return:
  948. //
  949. // Clean up.
  950. //
  951. if(pUrb){
  952. USFreePool(pUrb);
  953. }
  954. DebugTrace(TRACE_PROC_LEAVE,("USAbortResetPipe: Leaving.. Status = 0x%x\n", Status));
  955. return Status;
  956. }
  957. NTSTATUS
  958. USPassThruUSBRequest(
  959. IN PDEVICE_OBJECT pDeviceObject,
  960. IN PIO_BLOCK_EX pIoBlockEx,
  961. IN ULONG InLength,
  962. IN ULONG OutLength
  963. )
  964. /*++
  965. Routine Description:
  966. Implements generic pass-thru for vendor request to USBD
  967. Arguments:
  968. pDeviceObject - Device object
  969. pIoBlockEx - Pointer to I/O block as described in USBSCAN.H, passed from user mode client
  970. InLength - In length from IRP
  971. OutLength - Out length from IRP
  972. Return Value:
  973. NTSTATUS type
  974. --*/
  975. {
  976. NTSTATUS Status;
  977. PUSBSCAN_DEVICE_EXTENSION pde;
  978. PURB pUrb;
  979. ULONG siz;
  980. PVOID pBuffer;
  981. BOOLEAN fDirectionIn;
  982. PAGED_CODE();
  983. DebugTrace(TRACE_PROC_ENTER,("USPassThruUSBRequest: Enter..\n"));
  984. //
  985. // Initialize local variable.
  986. //
  987. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  988. Status = STATUS_SUCCESS;
  989. pUrb = NULL;
  990. pBuffer = NULL;
  991. fDirectionIn = TRUE;
  992. //
  993. // Allocate memory for URB
  994. //
  995. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  996. pUrb = USAllocatePool(NonPagedPool, siz);
  997. if (NULL == pUrb) {
  998. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocated URB\n"));
  999. DEBUG_BREAKPOINT();
  1000. Status = STATUS_INSUFFICIENT_RESOURCES;
  1001. goto USPassThruUSBRequest_return;
  1002. }
  1003. RtlZeroMemory(pUrb, siz);
  1004. //
  1005. // Setup URB
  1006. //
  1007. pBuffer = pIoBlockEx;
  1008. //
  1009. // If we are writing data, then we need to make a copy of the
  1010. // register block into a non-paged block of memory before handing it off
  1011. // to usbd.
  1012. //
  1013. if (!pIoBlockEx->fTransferDirectionIn) {
  1014. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Write request, allocating non-paged buffer, len = %d\n",pIoBlockEx->uLength));
  1015. fDirectionIn = FALSE;
  1016. if ( pIoBlockEx->uLength ) {
  1017. pBuffer = USAllocatePool(NonPagedPool, pIoBlockEx->uLength);
  1018. if (NULL == pBuffer) {
  1019. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocate write buffer"));
  1020. DEBUG_BREAKPOINT();
  1021. Status = STATUS_INSUFFICIENT_RESOURCES;
  1022. goto USPassThruUSBRequest_return;
  1023. }
  1024. //
  1025. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  1026. // validate that given pointer is readable.
  1027. //
  1028. try{
  1029. RtlCopyMemory(pBuffer,
  1030. pIoBlockEx->pbyData,
  1031. pIoBlockEx->uLength);
  1032. } except(EXCEPTION_EXECUTE_HANDLER) {
  1033. //
  1034. // Caller buffer is not valid, or worse..
  1035. //
  1036. DebugTrace(TRACE_ERROR,("USPassThruUSBRequest: ERROR!! Copying caller buffer failed.\n"));
  1037. DEBUG_BREAKPOINT();
  1038. Status = GetExceptionCode();
  1039. goto USPassThruUSBRequest_return;
  1040. }
  1041. } else {
  1042. //
  1043. // Zero length buffer used for Write , IHV claim that's useful.
  1044. //
  1045. pBuffer = NULL;
  1046. } // if ( pIoBlockEx->uLength )
  1047. }
  1048. UsbBuildVendorClassSpecificCommand(pUrb,
  1049. pIoBlockEx->fTransferDirectionIn ? USBD_TRANSFER_DIRECTION_IN : 0,
  1050. pIoBlockEx->uLength,
  1051. pBuffer,
  1052. NULL,
  1053. pIoBlockEx->bmRequestType,
  1054. pIoBlockEx->bRequest,
  1055. (SHORT)pIoBlockEx->uOffset,
  1056. (USHORT)pIoBlockEx -> uIndex
  1057. );
  1058. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1059. USPassThruUSBRequest_return:
  1060. //
  1061. // Clean up.
  1062. //
  1063. if(NULL != pUrb){
  1064. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free USB Request Block.\n"));
  1065. USFreePool(pUrb);
  1066. }
  1067. if( (!fDirectionIn)
  1068. && (NULL != pBuffer) )
  1069. {
  1070. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free temp buffer.\n"));
  1071. USFreePool(pBuffer);
  1072. }
  1073. DebugTrace(TRACE_PROC_LEAVE,("USPassThruUSBRequest: Leaving.. Status = 0x%x\n", Status));
  1074. return Status;
  1075. }
  1076. NTSTATUS
  1077. USPassThruUSBRequestPTP(
  1078. IN PDEVICE_OBJECT pDeviceObject,
  1079. IN PIO_BLOCK_EX pIoBlockEx,
  1080. IN ULONG InLength,
  1081. IN ULONG OutLength
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. Implements generic pass-thru for vendor request to USBD
  1086. Arguments:
  1087. pDeviceObject - Device object
  1088. pIoBlockEx - Pointer to I/O block as described in USBSCAN.H, passed from user mode client
  1089. InLength - In length from IRP
  1090. OutLength - Out length from IRP
  1091. Return Value:
  1092. NTSTATUS type
  1093. --*/
  1094. {
  1095. NTSTATUS Status;
  1096. PUSBSCAN_DEVICE_EXTENSION pde;
  1097. PURB pUrb;
  1098. ULONG siz;
  1099. PVOID pBuffer;
  1100. BOOLEAN fDirectionIn;
  1101. USHORT usUsbFunction;
  1102. PAGED_CODE();
  1103. DebugTrace(TRACE_PROC_ENTER,("USPassThruUSBRequest: Enter..\n"));
  1104. //
  1105. // Initialize local variable.
  1106. //
  1107. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  1108. Status = STATUS_SUCCESS;
  1109. pUrb = NULL;
  1110. pBuffer = NULL;
  1111. fDirectionIn = TRUE;
  1112. usUsbFunction = 0;
  1113. //
  1114. // Allocate memory for URB
  1115. //
  1116. siz = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
  1117. pUrb = USAllocatePool(NonPagedPool, siz);
  1118. if (NULL == pUrb) {
  1119. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocated URB\n"));
  1120. DEBUG_BREAKPOINT();
  1121. Status = STATUS_INSUFFICIENT_RESOURCES;
  1122. goto USPassThruUSBRequest_return;
  1123. }
  1124. RtlZeroMemory(pUrb, siz);
  1125. //
  1126. // Setup URB
  1127. //
  1128. pBuffer = pIoBlockEx;
  1129. //
  1130. // If we are writing data, then we need to make a copy of the
  1131. // register block into a non-paged block of memory before handing it off
  1132. // to usbd.
  1133. //
  1134. if (!pIoBlockEx->fTransferDirectionIn) {
  1135. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Write request, allocating non-paged buffer, len = %d\n",pIoBlockEx->uLength));
  1136. fDirectionIn = FALSE;
  1137. if ( pIoBlockEx->uLength ) {
  1138. pBuffer = USAllocatePool(NonPagedPool, pIoBlockEx->uLength);
  1139. if (NULL == pBuffer) {
  1140. DebugTrace(TRACE_CRITICAL,("USPassThruUSBRequest: ERROR!! cannot allocate write buffer"));
  1141. DEBUG_BREAKPOINT();
  1142. Status = STATUS_INSUFFICIENT_RESOURCES;
  1143. goto USPassThruUSBRequest_return;
  1144. }
  1145. //
  1146. // Caller gives us a pointer, embedded into IOCTL buffer. We need to
  1147. // validate that given pointer is readable.
  1148. //
  1149. try{
  1150. RtlCopyMemory(pBuffer,
  1151. pIoBlockEx->pbyData,
  1152. pIoBlockEx->uLength);
  1153. } except(EXCEPTION_EXECUTE_HANDLER) {
  1154. //
  1155. // Caller buffer is not valid, or worse..
  1156. //
  1157. DebugTrace(TRACE_ERROR,("USPassThruUSBRequest: ERROR!! Copying caller buffer failed.\n"));
  1158. DEBUG_BREAKPOINT();
  1159. Status = GetExceptionCode();
  1160. goto USPassThruUSBRequest_return;
  1161. }
  1162. } else {
  1163. //
  1164. // Zero length buffer used for Write , IHV claim that's useful.
  1165. //
  1166. pBuffer = NULL;
  1167. } // if ( pIoBlockEx->uLength )
  1168. }
  1169. //
  1170. // Set proper USB funtion depends on bmRequestType.
  1171. //
  1172. if(0xa1 == pIoBlockEx->bmRequestType){ // USB_PTPREQUEST_TYPE_IN: Class/Interface Device to Host.
  1173. usUsbFunction = URB_FUNCTION_CLASS_INTERFACE;
  1174. } else if(0x21 == pIoBlockEx->bmRequestType){ // USB_PTPREQUEST_TYPE_OUT: Class/Interface Host to Device.
  1175. usUsbFunction = URB_FUNCTION_CLASS_INTERFACE;
  1176. } else { // Default.
  1177. usUsbFunction = URB_FUNCTION_VENDOR_DEVICE;
  1178. }
  1179. UsbBuildVendorClassSpecificCommandPTP(usUsbFunction,
  1180. pUrb,
  1181. pIoBlockEx->fTransferDirectionIn ? USBD_TRANSFER_DIRECTION_IN : 0,
  1182. pIoBlockEx->uLength,
  1183. pBuffer,
  1184. NULL,
  1185. pIoBlockEx->bmRequestType,
  1186. pIoBlockEx->bRequest,
  1187. (SHORT)pIoBlockEx->uOffset,
  1188. (USHORT)pIoBlockEx -> uIndex);
  1189. Status = USBSCAN_CallUSBD(pDeviceObject, pUrb);
  1190. USPassThruUSBRequest_return:
  1191. //
  1192. // Clean up.
  1193. //
  1194. if(NULL != pUrb){
  1195. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free USB Request Block.\n"));
  1196. USFreePool(pUrb);
  1197. }
  1198. if( (!fDirectionIn)
  1199. && (NULL != pBuffer) )
  1200. {
  1201. DebugTrace(TRACE_STATUS,("USPassThruUSBRequest: Free temp buffer.\n"));
  1202. USFreePool(pBuffer);
  1203. }
  1204. DebugTrace(TRACE_PROC_LEAVE,("USPassThruUSBRequest: Leaving.. Status = 0x%x\n", Status));
  1205. return Status;
  1206. } // USPassThruUSBRequestPTP()