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.

192 lines
4.8 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. writesup.c
  5. Abstract:
  6. This module implements the write support routine. This is a common
  7. write function that is called by write and mailslot write.
  8. Author:
  9. Manny Weiser (mannyw) 16-Jan-1991
  10. Revision History:
  11. --*/
  12. #include "mailslot.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_WRITESUP)
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text( PAGE, MsWriteDataQueue )
  19. #endif
  20. NTSTATUS
  21. MsWriteDataQueue (
  22. IN PDATA_QUEUE WriteQueue,
  23. IN PUCHAR WriteBuffer,
  24. IN ULONG WriteLength
  25. )
  26. /*++
  27. Routine Description:
  28. This function writes data from the write buffer into read entries in
  29. the write queue. It will also dequeue entries in the queue as necessary.
  30. Arguments:
  31. WriteQueue - Provides the write queue to process.
  32. WriteBuffer - Provides the buffer from which to read the data.
  33. WriteLength - Provides the length, in bytes, of WriteBuffer.
  34. Return Value:
  35. STATUS_MORE_PROCESSING_REQUIRED if not all the data was written,
  36. other status codes as appropriate.
  37. --*/
  38. {
  39. NTSTATUS status;
  40. BOOLEAN result;
  41. PDATA_ENTRY dataEntry;
  42. PLIST_ENTRY listEntry;
  43. PFCB fcb;
  44. PUCHAR readBuffer;
  45. ULONG readLength;
  46. PIRP readIrp;
  47. NTSTATUS readStatus = STATUS_UNSUCCESSFUL;
  48. PWORK_CONTEXT workContext;
  49. PKTIMER timer;
  50. PAGED_CODE();
  51. DebugTrace(+1, Dbg, "MsWriteDataQueue\n", 0);
  52. DebugTrace( 0, Dbg, "WriteQueue = %08lx\n", (ULONG)WriteQueue);
  53. DebugTrace( 0, Dbg, "WriteBuffer = %08lx\n", (ULONG)WriteBuffer);
  54. DebugTrace( 0, Dbg, "WriteLength = %08lx\n", WriteLength);
  55. //
  56. // Now while the write queue has some read entries in it and
  57. // we have not successfully completed a read then we'll do the
  58. // following main loop.
  59. //
  60. status = STATUS_MORE_PROCESSING_REQUIRED;
  61. for (listEntry = MsGetNextDataQueueEntry( WriteQueue );
  62. (MsIsDataQueueReaders(WriteQueue) &&
  63. status == STATUS_MORE_PROCESSING_REQUIRED);
  64. listEntry = MsGetNextDataQueueEntry( WriteQueue )) {
  65. dataEntry = CONTAINING_RECORD( listEntry, DATA_ENTRY, ListEntry );
  66. readBuffer = dataEntry->DataPointer;
  67. readLength = dataEntry->DataSize;
  68. DebugTrace(0, Dbg, "Top of write loop...\n", 0);
  69. DebugTrace(0, Dbg, "ReadBuffer = %08lx\n", (ULONG)readBuffer);
  70. DebugTrace(0, Dbg, "ReadLength = %08lx\n", readLength);
  71. //
  72. // If the buffer for this read operation is large enough
  73. // copy the data.
  74. //
  75. if ( readLength >= WriteLength ) {
  76. //
  77. // Copy the data from the write buffer to the read buffer. This may take an exception
  78. // because its a raw user mode buffer
  79. //
  80. status = readStatus = STATUS_SUCCESS;
  81. try {
  82. RtlCopyMemory (readBuffer,
  83. WriteBuffer,
  84. WriteLength);
  85. } except (EXCEPTION_EXECUTE_HANDLER) {
  86. return GetExceptionCode ();
  87. }
  88. } else {
  89. //
  90. // This read buffer was overflowed.
  91. //
  92. WriteLength = 0;
  93. readStatus = STATUS_BUFFER_TOO_SMALL;
  94. }
  95. //
  96. // We are about to complete a read IRP, so dequeue it.
  97. //
  98. readIrp = MsRemoveDataQueueEntry( WriteQueue, dataEntry );
  99. if ( readIrp == NULL) {
  100. //
  101. // Cancel routine was already running for this IRP. Ignore it as it will be completed by
  102. // cancel code. Force the loop for the next read irp if there is one.
  103. //
  104. status = STATUS_MORE_PROCESSING_REQUIRED;
  105. continue;
  106. }
  107. //
  108. // Update the FCB last access time and complete the read request.
  109. //
  110. fcb = CONTAINING_RECORD( WriteQueue, FCB, DataQueue );
  111. if ( NT_SUCCESS( readStatus ) ) {
  112. KeQuerySystemTime( &fcb->Specific.Fcb.LastAccessTime );
  113. }
  114. readIrp->IoStatus.Information = WriteLength;
  115. MsCompleteRequest( readIrp, readStatus );
  116. }
  117. DebugTrace(0, Dbg, "Finished loop...\n", 0);
  118. //
  119. // At this point we've finished off all of the read entries in the
  120. // queue and we might not have written the write data. If that
  121. // is the case then we'll set our result to FALSE otherwise we're
  122. // done so we'll return TRUE.
  123. //
  124. if ( status == STATUS_MORE_PROCESSING_REQUIRED ) {
  125. ASSERT( !MsIsDataQueueReaders( WriteQueue ));
  126. }
  127. DebugTrace(-1, Dbg, "MsWriteDataQueue -> %08lx\n", status);
  128. return status;
  129. }
  130.