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.

273 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. io.c
  5. Abstract:
  6. This module contains IRP building routines.
  7. Author:
  8. Manny Weiser (mannyw) 13-Jan-1992
  9. Revision History:
  10. --*/
  11. #include "mup.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text( PAGE, MupBuildIoControlRequest )
  14. #endif
  15. PIRP
  16. MupBuildIoControlRequest (
  17. IN OUT PIRP Irp OPTIONAL,
  18. IN PFILE_OBJECT FileObject OPTIONAL,
  19. IN PVOID Context,
  20. IN UCHAR MajorFunction,
  21. IN ULONG IoControlCode,
  22. IN PVOID MainBuffer,
  23. IN ULONG InputBufferLength,
  24. IN PVOID AuxiliaryBuffer OPTIONAL,
  25. IN ULONG OutputBufferLength,
  26. IN PIO_COMPLETION_ROUTINE CompletionRoutine
  27. )
  28. /*++
  29. Routine Description:
  30. This function builds an I/O request packet for a device or
  31. file system I/O control request.
  32. Arguments:
  33. Irp - Supplies a pointer to an IRP. If NULL, this routine allocates
  34. an IRP and returns its address. Otherwise, it supplies the
  35. address of an IRP allocated by the caller.
  36. FileObject - Supplies a pointer the file object to which this
  37. request is directed. This pointer is copied into the IRP, so
  38. that the called driver can find its file-based context. NOTE
  39. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  40. that the file object is not deleted while the I/O operation is
  41. in progress. The server accomplishes this by incrementing a
  42. reference count in a local block to account for the I/O; the
  43. local block in turn references the file object.
  44. Context - Supplies a PVOID value that is passed to the completion
  45. routine.
  46. MajorFunction - The major function that we are calling. Currently
  47. this most be one of IRP_MJ_FILE_SYSTEM_CONTROL or
  48. IRP_MJ_DEVICE_IO_CONTROL.
  49. IoControlCode - Supplies the control code for the operation.
  50. MainBuffer - Supplies the address of the main buffer. This must
  51. be a system virtual address, and the buffer must be locked in
  52. memory. If ControlCode specifies a method 0 request, the actual
  53. length of the buffer must be the greater of InputBufferLength
  54. and OutputBufferLength.
  55. InputBufferLength - Supplies the length of the input buffer.
  56. AuxiliaryBuffer - Supplies the address of the auxiliary buffer. If the
  57. control code method is 0, this is a buffered I/O buffer, but the
  58. data returned by the called driver in the system buffer is not
  59. automatically copied into the auxiliary buffer. Instead, the
  60. auxiliary data ends up in MainBuffer. If the caller wishes the
  61. data to be in AuxiliaryBuffer, it must copy the data at some point
  62. after the completion routine runs.
  63. If the control code method is 1 or 2, this parameter is ignored;
  64. instead, the Mdl parameter is used to obtain the starting
  65. virtual address of the buffer.
  66. CompletionRoutine - The IO completion routine.
  67. Return Value:
  68. PIRP - Returns a pointer to the constructed IRP. If the Irp
  69. parameter was not NULL on input, the function return value will
  70. be the same value (so it is safe to discard the return value in
  71. this case). It is the responsibility of the calling program to
  72. deallocate the IRP after the I/O request is complete.
  73. --*/
  74. {
  75. CLONG method;
  76. PDEVICE_OBJECT deviceObject;
  77. PIO_STACK_LOCATION irpSp;
  78. PMDL pMdl;
  79. ASSERT( MajorFunction == IRP_MJ_DEVICE_CONTROL );
  80. PAGED_CODE();
  81. if (MainBuffer == NULL) {
  82. return (NULL);
  83. }
  84. //
  85. // Get the method with which the buffers are being passed.
  86. //
  87. method = IoControlCode & 3;
  88. //
  89. // Allocate an IRP. The stack size is one higher
  90. // than that of the target device, to allow for the caller's
  91. // completion routine.
  92. //
  93. deviceObject = IoGetRelatedDeviceObject( FileObject );
  94. //
  95. // Get the address of the target device object.
  96. //
  97. Irp = IoAllocateIrp( (CCHAR)(deviceObject->StackSize + 1), FALSE );
  98. if ( Irp == NULL ) {
  99. //
  100. // Unable to allocate an IRP. Inform the caller.
  101. //
  102. return NULL;
  103. }
  104. IoSetNextIrpStackLocation( Irp );
  105. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  106. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  107. //
  108. // Get a pointer to the current stack location and fill in the
  109. // device object pointer.
  110. //
  111. irpSp = IoGetCurrentIrpStackLocation( Irp );
  112. irpSp->DeviceObject = deviceObject;
  113. //
  114. // Set up the completion routine.
  115. //
  116. IoSetCompletionRoutine(
  117. Irp,
  118. CompletionRoutine,
  119. Context,
  120. TRUE,
  121. TRUE,
  122. TRUE
  123. );
  124. //
  125. // Get a pointer to the next stack location. This one is used to
  126. // hold the parameters for the device I/O control request.
  127. //
  128. irpSp = IoGetNextIrpStackLocation( Irp );
  129. irpSp->MajorFunction = MajorFunction;
  130. irpSp->MinorFunction = 0;
  131. irpSp->FileObject = FileObject;
  132. irpSp->DeviceObject = deviceObject;
  133. //
  134. // Copy the caller's parameters to the service-specific portion of the
  135. // IRP for those parameters that are the same for all three methods.
  136. //
  137. irpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
  138. irpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
  139. irpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
  140. //
  141. // Based on the method by which the buffers are being passed,
  142. // describe a system buffer and optionally build an MDL.
  143. //
  144. switch ( method ) {
  145. case 0:
  146. //
  147. // For this case, InputBuffer must be large enough to contain
  148. // both the input and the output buffers.
  149. //
  150. Irp->MdlAddress = NULL;
  151. Irp->AssociatedIrp.SystemBuffer = MainBuffer;
  152. Irp->UserBuffer = AuxiliaryBuffer;
  153. Irp->Flags = (ULONG)IRP_BUFFERED_IO;
  154. if ( ARGUMENT_PRESENT(AuxiliaryBuffer) ) {
  155. Irp->Flags |= IRP_INPUT_OPERATION;
  156. }
  157. break;
  158. case 1:
  159. case 2:
  160. //
  161. // For these two cases, MainBuffer is the buffered I/O "system
  162. // buffer". Build an MDL for either read or write access,
  163. // depending on the method, for the output buffer.
  164. //
  165. pMdl = IoAllocateMdl( MainBuffer, InputBufferLength, FALSE, FALSE, Irp );
  166. if (pMdl == NULL) {
  167. IoFreeIrp(Irp);
  168. return NULL;
  169. }
  170. Irp->AssociatedIrp.SystemBuffer = MainBuffer;
  171. Irp->Flags = (ULONG)IRP_BUFFERED_IO;
  172. //
  173. // An MDL to describe the buffer has not been built. Build
  174. // it now.
  175. //
  176. MmProbeAndLockPages(
  177. Irp->MdlAddress,
  178. KernelMode,
  179. IoReadAccess
  180. );
  181. break;
  182. case 3:
  183. //
  184. // For this case, do nothing. Everything is up to the driver.
  185. // Simply give the driver a copy of the caller's parameters and
  186. // let the driver do everything itself.
  187. //
  188. Irp->MdlAddress = NULL;
  189. Irp->AssociatedIrp.SystemBuffer = NULL;
  190. Irp->UserBuffer = AuxiliaryBuffer;
  191. irpSp->Parameters.DeviceIoControl.Type3InputBuffer = MainBuffer;
  192. break;
  193. }
  194. return Irp;
  195. } // MupBuildIoControlRequest