Source code of Windows XP (NT5)
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.

382 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. smbprint.c
  5. Abstract:
  6. This module implements printing SMB processors:
  7. Open Print File
  8. Close Print File
  9. Get Print Queue
  10. Author:
  11. David Treadwell (davidtr) 08-Feb-1990
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #include "smbprint.tmh"
  16. #pragma hdrstop
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text( PAGE, SrvSmbOpenPrintFile )
  19. #pragma alloc_text( PAGE, SrvSmbGetPrintQueue )
  20. #pragma alloc_text( PAGE, SrvSmbClosePrintFile )
  21. #endif
  22. SMB_PROCESSOR_RETURN_TYPE
  23. SrvSmbOpenPrintFile (
  24. SMB_PROCESSOR_PARAMETERS
  25. )
  26. /*++
  27. Routine Description:
  28. This routine processes the Open Print File SMB.
  29. Arguments:
  30. SMB_PROCESSOR_PARAMETERS - See smbtypes.h for a description
  31. of the parameters to SMB processor routines.
  32. Return Value:
  33. SMB_PROCESSOR_RETURN_TYPE - See smbtypes.h
  34. --*/
  35. {
  36. NTSTATUS status = STATUS_SUCCESS;
  37. SMB_STATUS SmbStatus = SmbStatusInProgress;
  38. PTREE_CONNECT treeConnect;
  39. PRESP_OPEN_PRINT_FILE response;
  40. PAGED_CODE( );
  41. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  42. WorkContext->PreviousSMB = EVENT_TYPE_SMB_OPEN_PRINT_FILE;
  43. SrvWmiStartContext(WorkContext);
  44. //
  45. // Make sure we are on a blocking thread!
  46. //
  47. if( WorkContext->UsingBlockingThread == 0 ) {
  48. SrvQueueWorkToBlockingThread( WorkContext );
  49. return SmbStatusInProgress;
  50. }
  51. //
  52. // Verify that this is a print share.
  53. //
  54. // *** We are putting in this check because some public domain Samba
  55. // smb clients are trying to print through a disk share.
  56. //
  57. treeConnect = SrvVerifyTid(
  58. WorkContext,
  59. SmbGetAlignedUshort( &WorkContext->RequestHeader->Tid )
  60. );
  61. if ( treeConnect == NULL ) {
  62. IF_DEBUG(SMB_ERRORS) {
  63. KdPrint(( "SrvSmbPrintFile: Invalid TID.\n" ));
  64. }
  65. SrvSetSmbError( WorkContext, STATUS_SMB_BAD_TID );
  66. status = STATUS_SMB_BAD_TID;
  67. SmbStatus = SmbStatusSendResponse;
  68. goto Cleanup;
  69. }
  70. //
  71. // if it's not a print share, tell the client to get lost.
  72. //
  73. if ( treeConnect->Share->ShareType != ShareTypePrint ) {
  74. SrvSetSmbError( WorkContext, STATUS_INVALID_DEVICE_REQUEST );
  75. status = STATUS_INVALID_DEVICE_REQUEST;
  76. SmbStatus = SmbStatusSendResponse;
  77. goto Cleanup;
  78. }
  79. //
  80. // Call SrvCreateFile to open a print spooler file. None of the
  81. // options such as desired access, etc. are relevant for a print
  82. // open--they are all set to default values by SrvCreateFile.
  83. //
  84. status = SrvCreateFile(
  85. WorkContext,
  86. 0, // SmbDesiredAccess
  87. 0, // SmbFileAttributes
  88. 0, // SmbOpenFunction
  89. 0, // SmbAllocationSize
  90. 0, // SmbFileName
  91. NULL, // EndOfSmbFileName
  92. NULL, // EaBuffer
  93. 0, // EaLength
  94. NULL, // EaErrorOffset
  95. 0, // RequestedOplockType
  96. NULL // RestartRoutine
  97. );
  98. //
  99. // There should never be an oplock on one of these special spooler
  100. // files.
  101. //
  102. ASSERT( status != STATUS_OPLOCK_BREAK_IN_PROGRESS );
  103. if ( !NT_SUCCESS(status) ) {
  104. SrvSetSmbError( WorkContext, status );
  105. SmbStatus = SmbStatusSendResponse;
  106. goto Cleanup;
  107. }
  108. //
  109. // Set up the response SMB.
  110. //
  111. response = (PRESP_OPEN_PRINT_FILE)WorkContext->ResponseParameters;
  112. response->WordCount = 1;
  113. SmbPutUshort( &response->Fid, WorkContext->Rfcb->Fid );
  114. SmbPutUshort( &response->ByteCount, 0 );
  115. WorkContext->ResponseParameters = NEXT_LOCATION(
  116. response,
  117. RESP_OPEN_PRINT_FILE,
  118. 0
  119. );
  120. SmbStatus = SmbStatusSendResponse;
  121. Cleanup:
  122. SrvWmiEndContext(WorkContext);
  123. return SmbStatus;
  124. } // SrvSmbOpenPrintFile
  125. SMB_PROCESSOR_RETURN_TYPE
  126. SrvSmbClosePrintFile (
  127. SMB_PROCESSOR_PARAMETERS
  128. )
  129. /*++
  130. Routine Description:
  131. This routine processes the Close Print File SMB.
  132. Arguments:
  133. SMB_PROCESSOR_PARAMETERS - See smbtypes.h for a description
  134. of the parameters to SMB processor routines.
  135. Return Value:
  136. SMB_PROCESSOR_RETURN_TYPE - See smbtypes.h
  137. --*/
  138. {
  139. PREQ_CLOSE_PRINT_FILE request;
  140. PRESP_CLOSE_PRINT_FILE response;
  141. PSESSION session;
  142. PRFCB rfcb;
  143. NTSTATUS status = STATUS_SUCCESS;
  144. SMB_STATUS SmbStatus = SmbStatusInProgress;
  145. PAGED_CODE( );
  146. if (WorkContext->PreviousSMB == EVENT_TYPE_SMB_LAST_EVENT)
  147. WorkContext->PreviousSMB = EVENT_TYPE_SMB_CLOSE_PRINT_FILE;
  148. SrvWmiStartContext(WorkContext);
  149. //
  150. // Make sure we are on a blocking thread
  151. //
  152. if( WorkContext->UsingBlockingThread == 0 ) {
  153. SrvQueueWorkToBlockingThread( WorkContext );
  154. SmbStatus = SmbStatusInProgress;
  155. goto Cleanup;
  156. }
  157. IF_SMB_DEBUG(OPEN_CLOSE1) {
  158. KdPrint(( "Close print file request header at 0x%p, response header at 0x%p\n",
  159. WorkContext->RequestHeader,
  160. WorkContext->ResponseHeader ));
  161. KdPrint(( "Close print file request parameters at 0x%p, response parameters at 0x%p\n",
  162. WorkContext->RequestParameters,
  163. WorkContext->ResponseParameters ));
  164. }
  165. //
  166. // Set up parameters.
  167. //
  168. request = (PREQ_CLOSE_PRINT_FILE)(WorkContext->RequestParameters);
  169. response = (PRESP_CLOSE_PRINT_FILE)(WorkContext->ResponseParameters);
  170. //
  171. // If a session block has not already been assigned to the current
  172. // work context, verify the UID. If verified, the address of the
  173. // session block corresponding to this user is stored in the
  174. // WorkContext block and the session block is referenced.
  175. //
  176. session = SrvVerifyUid(
  177. WorkContext,
  178. SmbGetAlignedUshort( &WorkContext->RequestHeader->Uid )
  179. );
  180. if ( session == NULL ) {
  181. IF_DEBUG(SMB_ERRORS) {
  182. KdPrint(( "SrvSmbClose: Invalid UID: 0x%lx\n",
  183. SmbGetAlignedUshort( &WorkContext->RequestHeader->Uid ) ));
  184. }
  185. SrvSetSmbError( WorkContext, STATUS_SMB_BAD_UID );
  186. status = STATUS_SMB_BAD_UID;
  187. SmbStatus = SmbStatusSendResponse;
  188. goto Cleanup;
  189. }
  190. //
  191. // First, verify the FID. If verified, the RFCB and the TreeConnect
  192. // block are referenced and their addresses are stored in the
  193. // WorkContext block, and the RFCB address is returned.
  194. //
  195. // Call SrvVerifyFid, but do not fail (return NULL) if there
  196. // is a saved write behind error for this rfcb. The rfcb is
  197. // needed in order to process the close.
  198. //
  199. rfcb = SrvVerifyFid(
  200. WorkContext,
  201. SmbGetUshort( &request->Fid ),
  202. FALSE,
  203. SrvRestartSmbReceived, // serialize with raw write
  204. &status
  205. );
  206. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  207. if ( !NT_SUCCESS( status ) ) {
  208. //
  209. // Invalid file ID. Reject the request.
  210. //
  211. IF_DEBUG(SMB_ERRORS) {
  212. KdPrint(( "SrvSmbClose: Invalid FID: 0x%lx\n",
  213. SmbGetUshort( &request->Fid ) ));
  214. }
  215. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  216. status = STATUS_INVALID_HANDLE;
  217. SmbStatus = SmbStatusSendResponse;
  218. goto Cleanup;
  219. }
  220. //
  221. // The work item has been queued because a raw write is in
  222. // progress.
  223. //
  224. SmbStatus = SmbStatusInProgress;
  225. goto Cleanup;
  226. } else if ( !NT_SUCCESS( rfcb->SavedError ) ) {
  227. //
  228. // Check the saved error.
  229. //
  230. (VOID)SrvCheckForSavedError( WorkContext, rfcb );
  231. }
  232. //
  233. // Now proceed to do the actual close file, even if there was
  234. // a write behind error.
  235. //
  236. SrvCloseRfcb( rfcb );
  237. //
  238. // Dereference the RFCB immediately, rather than waiting for normal
  239. // work context cleanup after the response send completes. This
  240. // gets the xFCB structures cleaned up in a more timely manner.
  241. //
  242. // *** The specific motivation for this change was to fix a problem
  243. // where a compatibility mode open was closed, the response was
  244. // sent, and a Delete SMB was received before the send
  245. // completion was processed. This resulted in the MFCB and LFCB
  246. // still being present, which caused the delete processing to
  247. // try to use the file handle in the LFCB, which we just closed
  248. // here.
  249. //
  250. SrvDereferenceRfcb( rfcb );
  251. WorkContext->Rfcb = NULL;
  252. //
  253. // Build the response SMB.
  254. //
  255. response->WordCount = 0;
  256. SmbPutUshort( &response->ByteCount, 0 );
  257. WorkContext->ResponseParameters = NEXT_LOCATION(
  258. response,
  259. RESP_CLOSE_PRINT_FILE,
  260. 0
  261. );
  262. SmbStatus = SmbStatusSendResponse;
  263. Cleanup:
  264. SrvWmiEndContext(WorkContext);
  265. return SmbStatus;
  266. } // SrvSmbClosePrintFile
  267. SMB_PROCESSOR_RETURN_TYPE
  268. SrvSmbGetPrintQueue (
  269. SMB_PROCESSOR_PARAMETERS
  270. )
  271. /*++
  272. Routine Description:
  273. This routine processes the Get Print Queue SMB.
  274. Arguments:
  275. SMB_PROCESSOR_PARAMETERS - See smbtypes.h for a description
  276. of the parameters to SMB processor routines.
  277. Return Value:
  278. SMB_PROCESSOR_RETURN_TYPE - See smbtypes.h
  279. --*/
  280. {
  281. PAGED_CODE( );
  282. return SrvSmbNotImplemented( SMB_PROCESSOR_ARGUMENTS );
  283. } // SrvSmbGetPrintQueue