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.

317 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Write.c
  5. Abstract:
  6. This module implements the File Write routine for Write called by the
  7. Fsd/Fsp dispatch drivers.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Tom Jolly [tomjolly] 8-Aug-2000
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "UdfProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (UDFS_BUG_CHECK_WRITE)
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (UDFS_DEBUG_LEVEL_WRITE)
  23. NTSTATUS
  24. UdfCommonWrite (
  25. IN PIRP_CONTEXT IrpContext,
  26. IN PIRP Irp
  27. )
  28. {
  29. PIO_STACK_LOCATION IrpSp;
  30. PFILE_OBJECT FileObject;
  31. TYPE_OF_OPEN TypeOfOpen;
  32. PFCB Fcb;
  33. PCCB Ccb;
  34. BOOLEAN Wait;
  35. BOOLEAN PagingIo;
  36. BOOLEAN SynchronousIo;
  37. BOOLEAN WriteToEof;
  38. LONGLONG StartingOffset;
  39. LONGLONG ByteCount;
  40. NTSTATUS Status = STATUS_SUCCESS;
  41. UDF_IO_CONTEXT LocalIoContext;
  42. //
  43. // Get current Irp stack location and file object
  44. //
  45. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  46. FileObject = IrpSp->FileObject;
  47. DebugTrace((+1, Dbg, "UdfCommonWrite\n"));
  48. DebugTrace(( 0, Dbg, "Irp = %8lx\n", Irp));
  49. DebugTrace(( 0, Dbg, "ByteCount = %8lx\n", IrpSp->Parameters.Write.Length));
  50. DebugTrace(( 0, Dbg, "ByteOffset.LowPart = %8lx\n", IrpSp->Parameters.Write.ByteOffset.LowPart));
  51. DebugTrace(( 0, Dbg, "ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Write.ByteOffset.HighPart));
  52. //
  53. // Extract the nature of the write from the file object, and case on it
  54. //
  55. TypeOfOpen = UdfDecodeFileObject( FileObject, &Fcb, &Ccb);
  56. //
  57. // We only support write to the volume file
  58. //
  59. if (TypeOfOpen != UserVolumeOpen) {
  60. Irp->IoStatus.Information = 0;
  61. UdfCompleteRequest( IrpContext, Irp, STATUS_NOT_IMPLEMENTED );
  62. return STATUS_NOT_IMPLEMENTED;
  63. }
  64. ASSERT( Fcb == IrpContext->Vcb->VolumeDasdFcb);
  65. ASSERT( Ccb != NULL);
  66. //
  67. // Initialize the appropriate local variables.
  68. //
  69. Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
  70. PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
  71. SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);
  72. //
  73. // Extract the bytecount and starting offset
  74. //
  75. ByteCount = IrpSp->Parameters.Write.Length;
  76. StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart;
  77. WriteToEof = (StartingOffset == -1);
  78. Irp->IoStatus.Information = 0;
  79. //
  80. // If there is nothing to write, return immediately
  81. //
  82. if (ByteCount == 0) {
  83. UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
  84. return STATUS_SUCCESS;
  85. }
  86. //
  87. // Watch for overflow
  88. //
  89. if ((MAXLONGLONG - StartingOffset) < ByteCount) {
  90. UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  91. return STATUS_INVALID_PARAMETER;
  92. }
  93. //
  94. // Not sure what we're synchronising against, but....
  95. //
  96. UdfAcquireFileShared( IrpContext, Fcb );
  97. try {
  98. //
  99. // Verify the Fcb. Allow writes if this handle is dismounting
  100. // the volume.
  101. //
  102. if ((NULL == Ccb) || !FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE)) {
  103. UdfVerifyFcbOperation( IrpContext, Fcb );
  104. }
  105. if ((NULL == Ccb) || !FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {
  106. //
  107. // Clamp to volume size
  108. //
  109. if ( StartingOffset >= Fcb->FileSize.QuadPart) {
  110. try_leave( NOTHING);
  111. }
  112. if ( ByteCount > (Fcb->FileSize.QuadPart - StartingOffset)) {
  113. ByteCount = Fcb->FileSize.QuadPart - StartingOffset;
  114. if (0 == ByteCount) {
  115. try_leave( NOTHING);
  116. }
  117. }
  118. }
  119. else {
  120. //
  121. // This has a peculiar interpretation, but just adjust the starting
  122. // byte to the end of the visible volume.
  123. //
  124. if (WriteToEof) {
  125. StartingOffset = Fcb->FileSize.QuadPart;
  126. }
  127. }
  128. //
  129. // Initialize the IoContext for the write.
  130. // If there is a context pointer, we need to make sure it was
  131. // allocated and not a stale stack pointer.
  132. //
  133. if (IrpContext->IoContext == NULL ||
  134. !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
  135. //
  136. // If we can wait, use the context on the stack. Otherwise
  137. // we need to allocate one.
  138. //
  139. if (Wait) {
  140. IrpContext->IoContext = &LocalIoContext;
  141. ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
  142. } else {
  143. IrpContext->IoContext = UdfAllocateIoContext();
  144. SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
  145. }
  146. }
  147. RtlZeroMemory( IrpContext->IoContext, sizeof( UDF_IO_CONTEXT ));
  148. //
  149. // Store whether we allocated this context structure in the structure
  150. // itself.
  151. //
  152. IrpContext->IoContext->AllocatedContext =
  153. BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
  154. if (Wait) {
  155. KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
  156. NotificationEvent,
  157. FALSE );
  158. } else {
  159. IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread();
  160. IrpContext->IoContext->Resource = Fcb->Resource;
  161. IrpContext->IoContext->RequestedByteCount = (ULONG)ByteCount;
  162. }
  163. //
  164. // For DASD we have to probe and lock the user's buffer
  165. //
  166. UdfLockUserBuffer( IrpContext, (ULONG)ByteCount, IoReadAccess );
  167. //
  168. // Set the FO_MODIFIED flag here to trigger a verify when this
  169. // handle is closed. Note that we can err on the conservative
  170. // side with no problem, i.e. if we accidently do an extra
  171. // verify there is no problem.
  172. //
  173. SetFlag( FileObject->Flags, FO_FILE_MODIFIED );
  174. //
  175. // Write the data and wait for the results
  176. //
  177. Irp->IoStatus.Information = (ULONG)ByteCount;
  178. UdfSingleAsync( IrpContext,
  179. StartingOffset,
  180. (ULONG)ByteCount);
  181. if (!Wait) {
  182. //
  183. // We, nor anybody else, need the IrpContext any more.
  184. //
  185. ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO);
  186. UdfCleanupIrpContext( IrpContext, TRUE);
  187. DebugTrace((-1, Dbg, "UdfCommonWrite -> STATUS_PENDING\n"));
  188. try_leave( Status = STATUS_PENDING);
  189. }
  190. UdfWaitSync( IrpContext );
  191. //
  192. // If the call didn't succeed, raise the error status
  193. //
  194. Status = Irp->IoStatus.Status;
  195. if (!NT_SUCCESS( Status)) {
  196. UdfNormalizeAndRaiseStatus( IrpContext, Status );
  197. }
  198. //
  199. // Update the current file position. We assume that
  200. // open/create zeros out the CurrentByteOffset field.
  201. //
  202. if (SynchronousIo && !PagingIo) {
  203. FileObject->CurrentByteOffset.QuadPart =
  204. StartingOffset + Irp->IoStatus.Information;
  205. }
  206. }
  207. finally {
  208. UdfReleaseFile( IrpContext, Fcb);
  209. DebugTrace((-1, Dbg, "UdfCommonWrite -> %08lx\n", Status ));
  210. }
  211. if (STATUS_PENDING != Status) {
  212. UdfCompleteRequest( IrpContext, Irp, Status );
  213. }
  214. return Status;
  215. }