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.

288 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. readwrite.c
  5. Abstract:
  6. This file contains RAM disk driver code for reading from and writing to
  7. a RAM disk.
  8. Author:
  9. Chuck Lenzmeier (ChuckL) 2001
  10. Environment:
  11. Kernel mode only.
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. NTSTATUS
  18. RamdiskReadWrite (
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN PIRP Irp
  21. )
  22. /*++
  23. Routine Description:
  24. This routine is called by the I/O system to read from or write to a
  25. device that we control.
  26. Arguments:
  27. DeviceObject - a pointer to the object that represents the device on which
  28. I/O is to be performed
  29. Irp - a pointer to the I/O Request Packet for this request
  30. Return Value:
  31. NTSTATUS - the status of the operation
  32. --*/
  33. {
  34. NTSTATUS status;
  35. PDISK_EXTENSION diskExtension;
  36. PIO_STACK_LOCATION irpSp;
  37. ULONGLONG ioOffset;
  38. ULONG ioLength;
  39. //
  40. // Get the device extension pointer. Get parameters from the IRP.
  41. //
  42. diskExtension = DeviceObject->DeviceExtension;
  43. irpSp = IoGetCurrentIrpStackLocation(Irp);
  44. ioOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
  45. ioLength = irpSp->Parameters.Read.Length;
  46. //
  47. // If this is not a disk PDO, we can't handle this IRP.
  48. //
  49. if ( diskExtension->DeviceType != RamdiskDeviceTypeDiskPdo ) {
  50. status = STATUS_INVALID_DEVICE_REQUEST;
  51. goto complete_irp;
  52. }
  53. DBGPRINT( DBG_READWRITE, DBG_PAINFUL,
  54. ("RamdiskReadWrite: offset %I64x, length %x\n", ioOffset, ioLength) );
  55. //
  56. // If it's a zero-length operation, we don't have to do anything.
  57. //
  58. if ( ioLength == 0 ) {
  59. status = STATUS_SUCCESS;
  60. goto complete_irp;
  61. }
  62. //
  63. // Check for invalid parameters:
  64. // The transfer must be sector aligned.
  65. // The length cannot cause the offset to wrap.
  66. // The transfer cannot go beyond the end of the disk.
  67. // Writes cannot be performed on a readonly disk.
  68. //
  69. if ( ((ioOffset | ioLength) & (diskExtension->BytesPerSector - 1)) != 0 ) {
  70. status = STATUS_INVALID_PARAMETER;
  71. goto complete_irp;
  72. }
  73. if ( (ioOffset + ioLength) < ioOffset ) {
  74. status = STATUS_INVALID_PARAMETER;
  75. goto complete_irp;
  76. }
  77. if ( (ioOffset + ioLength) > diskExtension->DiskLength ) {
  78. status = STATUS_NONEXISTENT_SECTOR;
  79. goto complete_irp;
  80. }
  81. if ( (irpSp->MajorFunction == IRP_MJ_WRITE) && diskExtension->Options.Readonly ) {
  82. status = STATUS_MEDIA_WRITE_PROTECTED;
  83. goto complete_irp;
  84. }
  85. //
  86. // If the RAM disk is not file-backed, then the disk image is in memory,
  87. // and we can do the operation regardless of what context we're in. If the
  88. // RAM disk is file-backed, we need to be in thread context to do the
  89. // operation.
  90. //
  91. if ( RAMDISK_IS_FILE_BACKED(diskExtension->DiskType) ) {
  92. status = SendIrpToThread( DeviceObject, Irp );
  93. if ( status != STATUS_PENDING ) {
  94. goto complete_irp;
  95. }
  96. return status;
  97. }
  98. status = RamdiskReadWriteReal(
  99. Irp,
  100. diskExtension
  101. );
  102. complete_irp:
  103. //
  104. // Complete the IRP.
  105. //
  106. Irp->IoStatus.Status = status;
  107. IoCompleteRequest( Irp, IO_DISK_INCREMENT );
  108. return status;
  109. } // RamdiskReadWrite
  110. NTSTATUS
  111. RamdiskReadWriteReal (
  112. IN PIRP Irp,
  113. IN PDISK_EXTENSION DiskExtension
  114. )
  115. /*++
  116. Routine Description:
  117. This routine is called in thread context to perform a read or a write.
  118. Arguments:
  119. Irp - a pointer to the I/O Request Packet for this request
  120. DiskExtension - a pointer to the device extension for the target device
  121. Return Value:
  122. NTSTATUS - the status of the operation
  123. --*/
  124. {
  125. NTSTATUS status;
  126. PIO_STACK_LOCATION irpSp;
  127. PUCHAR bufferAddress;
  128. PUCHAR diskByteAddress;
  129. ULONGLONG ioOffset;
  130. ULONG ioLength;
  131. ULONG mappedLength;
  132. //
  133. // Get a system-space pointer to the user's buffer. A system address must
  134. // be used because we may already have left the original caller's address
  135. // space.
  136. //
  137. ASSERT( Irp->MdlAddress != NULL );
  138. bufferAddress = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  139. if ( bufferAddress == NULL ) {
  140. //
  141. // Unable to get a pointer to the user's buffer.
  142. //
  143. return STATUS_INSUFFICIENT_RESOURCES;
  144. }
  145. //
  146. // Get parameters from the IRP.
  147. //
  148. irpSp = IoGetCurrentIrpStackLocation(Irp);
  149. ioOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
  150. ioLength = irpSp->Parameters.Read.Length;
  151. Irp->IoStatus.Information = 0;
  152. while ( ioLength != 0 ) {
  153. //
  154. // Map the appropriate RAM disk pages.
  155. //
  156. diskByteAddress = RamdiskMapPages( DiskExtension, ioOffset, ioLength, &mappedLength );
  157. if ( diskByteAddress == NULL ) {
  158. //
  159. // Unable to map the RAM disk.
  160. //
  161. return STATUS_INSUFFICIENT_RESOURCES;
  162. }
  163. ASSERT( mappedLength <= ioLength );
  164. Irp->IoStatus.Information += mappedLength;
  165. //
  166. // Copy the data in the appropriate direction.
  167. //
  168. status = STATUS_SUCCESS;
  169. switch ( irpSp->MajorFunction ) {
  170. case IRP_MJ_READ:
  171. RtlCopyMemory( bufferAddress, diskByteAddress, mappedLength );
  172. break;
  173. case IRP_MJ_WRITE:
  174. RtlCopyMemory( diskByteAddress, bufferAddress, mappedLength );
  175. break;
  176. default:
  177. ASSERT( FALSE );
  178. status = STATUS_INVALID_PARAMETER;
  179. ioLength = mappedLength;
  180. }
  181. //
  182. // Unmap the previously mapped pages.
  183. //
  184. RamdiskUnmapPages( DiskExtension, diskByteAddress, ioOffset, mappedLength );
  185. ioLength -= mappedLength;
  186. ioOffset += mappedLength;
  187. bufferAddress += mappedLength;
  188. }
  189. return status;
  190. } // RamdiskReadWriteReal