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.

408 lines
15 KiB

  1. /***************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Dot4Usb.sys - Lower Filter Driver for Dot4.sys for USB connected
  5. IEEE 1284.4 devices.
  6. File Name:
  7. Ioctl.c
  8. Abstract:
  9. Dispatch routines for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
  10. Environment:
  11. Kernel mode only
  12. Notes:
  13. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  14. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  16. PURPOSE.
  17. Copyright (c) 2000 Microsoft Corporation. All Rights Reserved.
  18. Revision History:
  19. 01/18/2000 : created
  20. ToDo in this file:
  21. - code review
  22. Author(s):
  23. Doug Fritz (DFritz)
  24. Joby Lafky (JobyL)
  25. ****************************************************************************/
  26. #include "pch.h"
  27. /************************************************************************/
  28. /* DispatchDeviceControl */
  29. /************************************************************************/
  30. //
  31. // Routine Description:
  32. //
  33. // Dispatch routine for IRP_MJ_DEVICE_CONTROL
  34. // - We don't currently handle any such requests but we may do
  35. // so in the future. Pass any unhandled requests down the
  36. // stack to the device below us.
  37. //
  38. // Arguments:
  39. //
  40. // DevObj - pointer to DeviceObject that is the target of the request
  41. // Irp - pointer to device control IRP
  42. //
  43. // Return Value:
  44. //
  45. // NTSTATUS
  46. //
  47. /************************************************************************/
  48. NTSTATUS
  49. DispatchDeviceControl(
  50. IN PDEVICE_OBJECT DevObj,
  51. IN PIRP Irp
  52. )
  53. {
  54. PDEVICE_EXTENSION devExt = DevObj->DeviceExtension;
  55. NTSTATUS status;
  56. ULONG info = 0;
  57. TR_VERBOSE(("DispatchDeviceControl - enter"));
  58. status = IoAcquireRemoveLock( &devExt->RemoveLock, Irp );
  59. if( NT_SUCCESS(status) ) {
  60. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  61. switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {
  62. case IOCTL_PAR_QUERY_DEVICE_ID:
  63. // ISSUE - 000901 - DFritz - these new IOCTLs need to do parameter validation to avoid AVs
  64. {
  65. const LONG minValidIdLength = sizeof("MFG:x;MDL:y;");
  66. const ULONG bufSize = 1024;
  67. PCHAR idBuffer = ExAllocatePool( NonPagedPool, bufSize );
  68. LONG idLength;
  69. if( idBuffer ) {
  70. RtlZeroMemory( idBuffer, bufSize );
  71. idLength = UsbGet1284Id( DevObj, idBuffer, bufSize-1 );
  72. if( idLength < minValidIdLength ) {
  73. status = STATUS_UNSUCCESSFUL;
  74. } else if( (ULONG)idLength >= irpSp->Parameters.DeviceIoControl.OutputBufferLength ) {
  75. status = STATUS_BUFFER_TOO_SMALL;
  76. } else {
  77. RtlZeroMemory( Irp->AssociatedIrp.SystemBuffer, idLength+1 );
  78. RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, idBuffer+2, idLength-2 );
  79. info = idLength - 1;
  80. status = STATUS_SUCCESS;
  81. }
  82. ExFreePool( idBuffer );
  83. } else {
  84. status = STATUS_NO_MEMORY;
  85. }
  86. }
  87. Irp->IoStatus.Status = status;
  88. Irp->IoStatus.Information = info;
  89. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  90. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  91. break;
  92. case IOCTL_PAR_QUERY_RAW_DEVICE_ID:
  93. {
  94. const LONG minValidIdLength = sizeof("MFG:x;MDL:y;");
  95. const ULONG bufSize = 1024;
  96. PCHAR idBuffer = ExAllocatePool( NonPagedPool, bufSize );
  97. LONG idLength;
  98. if( idBuffer ) {
  99. RtlZeroMemory( idBuffer, bufSize );
  100. idLength = UsbGet1284Id( DevObj, idBuffer, bufSize-1 );
  101. if( idLength < minValidIdLength ) {
  102. status = STATUS_UNSUCCESSFUL;
  103. } else if( (ULONG)idLength >= irpSp->Parameters.DeviceIoControl.OutputBufferLength ) {
  104. status = STATUS_BUFFER_TOO_SMALL;
  105. } else {
  106. RtlZeroMemory( Irp->AssociatedIrp.SystemBuffer, idLength+1 );
  107. RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, idBuffer, idLength);
  108. info = idLength + 1;
  109. status = STATUS_SUCCESS;
  110. }
  111. ExFreePool( idBuffer );
  112. } else {
  113. status = STATUS_NO_MEMORY;
  114. }
  115. }
  116. Irp->IoStatus.Status = status;
  117. Irp->IoStatus.Information = info;
  118. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  119. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  120. break;
  121. case IOCTL_PAR_QUERY_DEVICE_ID_SIZE:
  122. {
  123. const LONG minValidIdLength = sizeof("MFG:x;MDL:y;");
  124. const ULONG bufSize = 1024;
  125. PCHAR idBuffer = ExAllocatePool( NonPagedPool, bufSize );
  126. LONG idLength;
  127. if( idBuffer ) {
  128. RtlZeroMemory( idBuffer, bufSize );
  129. idLength = UsbGet1284Id( DevObj, idBuffer, bufSize-1 );
  130. if( idLength < minValidIdLength ) {
  131. status = STATUS_UNSUCCESSFUL;
  132. } else if( sizeof(ULONG) < irpSp->Parameters.DeviceIoControl.OutputBufferLength ) {
  133. status = STATUS_BUFFER_TOO_SMALL;
  134. } else {
  135. ++idLength; // save room for terminating NULL
  136. RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &idLength, sizeof(ULONG));
  137. info = sizeof(ULONG);
  138. status = STATUS_SUCCESS;
  139. }
  140. ExFreePool( idBuffer );
  141. } else {
  142. status = STATUS_NO_MEMORY;
  143. }
  144. }
  145. Irp->IoStatus.Status = status;
  146. Irp->IoStatus.Information = info;
  147. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  148. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  149. break;
  150. case IOCTL_PAR_QUERY_LOCATION:
  151. _snprintf( Irp->AssociatedIrp.SystemBuffer, 4, "USB" );
  152. info = 4;
  153. status = STATUS_SUCCESS;
  154. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  155. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  156. default:
  157. // pass request down
  158. IoSkipCurrentIrpStackLocation( Irp );
  159. status = IoCallDriver( devExt->LowerDevObj, Irp );
  160. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  161. }
  162. } else {
  163. // unable to acquire RemoveLock - FAIL request
  164. Irp->IoStatus.Status = status;
  165. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  166. }
  167. return status;
  168. }
  169. /************************************************************************/
  170. /* DispatchInternalDeviceControl */
  171. /************************************************************************/
  172. //
  173. // Routine Description:
  174. //
  175. // Dispatch routine for IRP_MJ_INTERNAL_DEVICE_CONTROL
  176. // - We expect DataLink requests from dot4.sys driver above us. Any
  177. // request that we don't handle is simply passed down the stack
  178. // to the driver below us.
  179. //
  180. // Arguments:
  181. //
  182. // DevObj - pointer to DeviceObject that is the target of the request
  183. // Irp - pointer to device control IRP
  184. //
  185. // Return Value:
  186. //
  187. // NTSTATUS
  188. //
  189. /************************************************************************/
  190. NTSTATUS
  191. DispatchInternalDeviceControl(
  192. IN PDEVICE_OBJECT DevObj,
  193. IN PIRP Irp
  194. )
  195. {
  196. NTSTATUS status;
  197. PDEVICE_EXTENSION devExt = DevObj->DeviceExtension;
  198. TR_VERBOSE(("DispatchInternalDeviceControl - enter"));
  199. status = IoAcquireRemoveLock( &devExt->RemoveLock, Irp );
  200. if( NT_SUCCESS(status) ) {
  201. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  202. BOOLEAN bCompleteIrp = FALSE;
  203. KIRQL oldIrql;
  204. switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {
  205. case IOCTL_INTERNAL_PARDOT3_CONNECT:
  206. //
  207. // Enter a "DataLink Connected" state with dot4.sys
  208. //
  209. TR_VERBOSE(("DispatchInternalDeviceControl - IOCTL_INTERNAL_PARDOT3_CONNECT"));
  210. KeAcquireSpinLock( &devExt->SpinLock, &oldIrql );
  211. if( !devExt->IsDLConnected ) {
  212. devExt->IsDLConnected = TRUE;
  213. status = STATUS_SUCCESS;
  214. } else {
  215. // we believe that we are in a "datalink connected state" but obviously
  216. // dot4.sys doesn't agree - suggest investigating further if we hit
  217. // this assert
  218. D4UAssert(FALSE);
  219. status = STATUS_INVALID_DEVICE_REQUEST;
  220. }
  221. KeReleaseSpinLock( &devExt->SpinLock, oldIrql );
  222. bCompleteIrp = TRUE;
  223. break;
  224. case IOCTL_INTERNAL_PARDOT3_RESET:
  225. //
  226. // This IOCTL is specific to parallel and is a NOOP for a USB connection.
  227. //
  228. TR_VERBOSE(("DispatchInternalDeviceControl - IOCTL_INTERNAL_PARDOT3_RESET"));
  229. status = STATUS_SUCCESS;
  230. bCompleteIrp = TRUE;
  231. break;
  232. case IOCTL_INTERNAL_PARDOT3_DISCONNECT:
  233. //
  234. // Terminate the "DataLink Connected" state with dot4.sys and
  235. // invalidate any Dot4Event since the event may be freed anytime
  236. // after we complete this IRP.
  237. //
  238. TR_VERBOSE(("DispatchInternalDeviceControl - IOCTL_INTERNAL_PARDOT3_DISCONNECT"));
  239. UsbStopReadInterruptPipeLoop( DevObj );
  240. KeAcquireSpinLock( &devExt->SpinLock, &oldIrql );
  241. devExt->Dot4Event = NULL; // invalidate dot4's event, if any, so we stop signalling dot4
  242. if( devExt->IsDLConnected ) {
  243. devExt->IsDLConnected = FALSE;
  244. } else {
  245. // we believe that we are NOT in a "datalink connected state" but obviously
  246. // dot4.sys doesn't agree - suggest investigating further if we hit
  247. // this assert
  248. D4UAssert(FALSE);
  249. }
  250. KeReleaseSpinLock( &devExt->SpinLock, oldIrql );
  251. status = STATUS_SUCCESS; // we always succeed this request since it is a disconnect
  252. bCompleteIrp = TRUE;
  253. break;
  254. case IOCTL_INTERNAL_PARDOT3_SIGNAL:
  255. //
  256. // dot4.sys is giving us a pointer to an Event that it owns and dot4
  257. // expects us to Signal this event whenever we detect that the device has
  258. // data available to be read. We continue signalling this event on device
  259. // data avail until we receive a disconnect IOCTL.
  260. //
  261. TR_VERBOSE(("DispatchInternalDeviceControl - IOCTL_INTERNAL_PARDOT3_SIGNAL"));
  262. KeAcquireSpinLock( &devExt->SpinLock, &oldIrql );
  263. if( devExt->IsDLConnected ) {
  264. if( !devExt->Dot4Event ) {
  265. // our state indicates that it is OK to receive this request
  266. if( irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PKEVENT) ) {
  267. status = STATUS_INVALID_PARAMETER;
  268. } else {
  269. // save the pointer to the event in our device extension
  270. PKEVENT Event;
  271. RtlCopyMemory(&Event, Irp->AssociatedIrp.SystemBuffer, sizeof(PKEVENT));
  272. devExt->Dot4Event = Event;
  273. status = STATUS_SUCCESS;
  274. }
  275. } else {
  276. // we already have an event and dot4.sys sent us another one? - bad driver - AV crash likely real soon now
  277. D4UAssert(FALSE);
  278. status = STATUS_INVALID_DEVICE_REQUEST;
  279. }
  280. } else {
  281. // we're not in a datalink connected state - this is an invalid request
  282. D4UAssert(FALSE);
  283. status = STATUS_INVALID_DEVICE_REQUEST;
  284. }
  285. KeReleaseSpinLock( &devExt->SpinLock, oldIrql );
  286. if( NT_SUCCESS(status) && devExt->InterruptPipe ) {
  287. status = UsbStartReadInterruptPipeLoop( DevObj );
  288. }
  289. bCompleteIrp = TRUE;
  290. break;
  291. default :
  292. // unhandled request - pass it down the stack
  293. IoSkipCurrentIrpStackLocation( Irp );
  294. status = IoCallDriver( devExt->LowerDevObj, Irp );
  295. bCompleteIrp = FALSE;
  296. }
  297. if( bCompleteIrp ) {
  298. // we didn't pass this request down the stack, so complete it now
  299. Irp->IoStatus.Status = status;
  300. Irp->IoStatus.Information = 0;
  301. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  302. }
  303. IoReleaseRemoveLock( &devExt->RemoveLock, Irp );
  304. } else {
  305. // unable to acquire RemoveLock - we're in the process of being removed - FAIL request
  306. Irp->IoStatus.Status = status;
  307. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  308. }
  309. return status;
  310. }