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.

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