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.

265 lines
7.6 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. smbclose.c
  5. Abstract:
  6. This module contains routines for processing the following SMBs:
  7. Close
  8. Author:
  9. David Treadwell (davidtr) 16-Nov-1989
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #include "smbclose.tmh"
  14. #pragma hdrstop
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text( PAGE, SrvSmbClose )
  17. #endif
  18. SMB_PROCESSOR_RETURN_TYPE
  19. SrvSmbClose (
  20. SMB_PROCESSOR_PARAMETERS
  21. )
  22. /*++
  23. Routine Description:
  24. Processes a Close SMB.
  25. Arguments:
  26. SMB_PROCESSOR_PARAMETERS - See smbprocs.h for a description
  27. of the parameters to SMB processor routines.
  28. Return Value:
  29. SMB_PROCESSOR_RETURN_TYPE - See smbprocs.h
  30. --*/
  31. {
  32. PREQ_CLOSE request;
  33. PRESP_CLOSE response;
  34. NTSTATUS status = STATUS_SUCCESS;
  35. PSESSION session;
  36. PRFCB rfcb;
  37. SMB_STATUS SmbStatus = SmbStatusInProgress;
  38. PAGED_CODE( );
  39. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  40. WorkContext->PreviousSMB = EVENT_TYPE_SMB_CLOSE;
  41. SrvWmiStartContext(WorkContext);
  42. IF_SMB_DEBUG(OPEN_CLOSE1) {
  43. KdPrint(( "Close file request header at 0x%p, response header at 0x%p\n",
  44. WorkContext->RequestHeader,
  45. WorkContext->ResponseHeader ));
  46. KdPrint(( "Close file request parameters at 0x%p, response parameters at 0x%p\n",
  47. WorkContext->RequestParameters,
  48. WorkContext->ResponseParameters ));
  49. }
  50. //
  51. // Set up parameters.
  52. //
  53. request = (PREQ_CLOSE)(WorkContext->RequestParameters);
  54. response = (PRESP_CLOSE)(WorkContext->ResponseParameters);
  55. //
  56. // If a session block has not already been assigned to the current
  57. // work context, verify the UID. If verified, the address of the
  58. // session block corresponding to this user is stored in the
  59. // WorkContext block and the session block is referenced.
  60. //
  61. session = SrvVerifyUid(
  62. WorkContext,
  63. SmbGetAlignedUshort( &WorkContext->RequestHeader->Uid )
  64. );
  65. if ( session == NULL ) {
  66. IF_DEBUG(SMB_ERRORS) {
  67. KdPrint(( "SrvSmbClose: Invalid UID: 0x%lx\n",
  68. SmbGetAlignedUshort( &WorkContext->RequestHeader->Uid ) ));
  69. }
  70. SrvSetSmbError( WorkContext, STATUS_SMB_BAD_UID );
  71. SmbStatus = SmbStatusSendResponse;
  72. goto Cleanup;
  73. }
  74. //
  75. // First, verify the FID. If verified, the RFCB and the TreeConnect
  76. // block are referenced and their addresses are stored in the
  77. // WorkContext block, and the RFCB address is returned.
  78. //
  79. // Call SrvVerifyFid, but do not fail (return NULL) if there
  80. // is a saved write behind error for this rfcb. The rfcb is
  81. // needed in order to process the close.
  82. //
  83. rfcb = SrvVerifyFid(
  84. WorkContext,
  85. SmbGetUshort( &request->Fid ),
  86. FALSE,
  87. SrvRestartSmbReceived, // serialize with raw write
  88. &status
  89. );
  90. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  91. if ( !NT_SUCCESS( status ) ) {
  92. //
  93. // Invalid file ID. Reject the request.
  94. //
  95. IF_DEBUG(SMB_ERRORS) {
  96. KdPrint(( "SrvSmbClose: Invalid FID: 0x%lx\n",
  97. SmbGetUshort( &request->Fid ) ));
  98. }
  99. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  100. SmbStatus = SmbStatusSendResponse;
  101. goto Cleanup;
  102. }
  103. //
  104. // The work item has been queued because a raw write is in
  105. // progress.
  106. //
  107. SmbStatus = SmbStatusInProgress;
  108. goto Cleanup;
  109. } else if( rfcb->ShareType == ShareTypePrint &&
  110. WorkContext->UsingLpcThread == 0 ) {
  111. //
  112. // Closing this file will result in the scheduling of a print
  113. // job. This means we will have to talk with srvsvc, a lengthy
  114. // operation. Shift this close over to a LPC thread.
  115. //
  116. // NOTE: We don't allow the LPC throttle to reject this request
  117. // because that would result in a failure to schedule a job.
  118. //
  119. SrvQueueWorkToLpcThread( WorkContext, FALSE );
  120. SmbStatus = SmbStatusInProgress;
  121. goto Cleanup;
  122. } else if ( !NT_SUCCESS( rfcb->SavedError ) ) {
  123. //
  124. // Check the saved error.
  125. //
  126. (VOID) SrvCheckForSavedError( WorkContext, rfcb );
  127. }
  128. //
  129. // Set the last write time on the file from the time specified in
  130. // the SMB. Even though the SMB spec says that this is optional,
  131. // we must support it for the following reasons:
  132. //
  133. // 1) The only way to set a file time in DOS is through a
  134. // handle-based API which the DOS redir never sees; the API
  135. // just sets the time in DOS's FCB, and the redir is expected
  136. // set the time when it closes the file. Therefore, if we
  137. // didn't do this, there would be no way t set a file time
  138. // from DOS.
  139. //
  140. // 2) It is better for a file to have a redirector's version
  141. // of a time than the server's. This keeps the time
  142. // consistent for apps running on the client. Setting
  143. // the file time on close keeps the file time consistent
  144. // with the time on the client.
  145. //
  146. // !!! should we do anything with the return code from this routine?
  147. if( rfcb->WriteAccessGranted ||
  148. rfcb->AppendAccessGranted ) {
  149. (VOID)SrvSetLastWriteTime(
  150. rfcb,
  151. SmbGetUlong( &request->LastWriteTimeInSeconds ),
  152. rfcb->GrantedAccess
  153. );
  154. }
  155. //
  156. // Now proceed to do the actual close file, even if there was
  157. // a write behind error.
  158. //
  159. SrvCloseRfcb( rfcb );
  160. //
  161. // Dereference the RFCB immediately, rather than waiting for normal
  162. // work context cleanup after the response send completes. This
  163. // gets the xFCB structures cleaned up in a more timely manner.
  164. //
  165. // *** The specific motivation for this change was to fix a problem
  166. // where a compatibility mode open was closed, the response was
  167. // sent, and a Delete SMB was received before the send
  168. // completion was processed. This resulted in the MFCB and LFCB
  169. // still being present, which caused the delete processing to
  170. // try to use the file handle in the LFCB, which we just closed
  171. // here.
  172. //
  173. SrvDereferenceRfcb( rfcb );
  174. WorkContext->Rfcb = NULL;
  175. WorkContext->OplockOpen = FALSE;
  176. #if 0
  177. //
  178. // If this is a CloseAndTreeDisc SMB, do the tree disconnect.
  179. //
  180. if ( WorkContext->RequestHeader->Command == SMB_COM_CLOSE_AND_TREE_DISC ) {
  181. IF_SMB_DEBUG(OPEN_CLOSE1) {
  182. KdPrint(( "Disconnecting tree 0x%lx\n", WorkContext->TreeConnect ));
  183. }
  184. SrvCloseTreeConnect( WorkContext->TreeConnect );
  185. }
  186. #endif
  187. //
  188. // Build the response SMB.
  189. //
  190. response->WordCount = 0;
  191. SmbPutUshort( &response->ByteCount, 0 );
  192. WorkContext->ResponseParameters = NEXT_LOCATION(
  193. response,
  194. RESP_CLOSE,
  195. 0
  196. );
  197. SmbStatus = SmbStatusSendResponse;
  198. Cleanup:
  199. SrvWmiEndContext(WorkContext);
  200. return SmbStatus;
  201. } // SrvSmbClose