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.

3124 lines
80 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. smbpipe.c
  5. Abstract:
  6. This module contains the code for handling named pipe based transact
  7. SMB's.
  8. Functions that are handled are:
  9. SrvCallNamedPipe
  10. SrvWaitNamedPipe
  11. SrvQueryInfoNamedPipe
  12. SrvQueryStateNamedPipe
  13. SrvSetStateNamedPipe
  14. SrvPeekNamedPipe
  15. SrvTransactNamedPipe
  16. Author:
  17. Manny Weiser (9-18-90)
  18. Revision History:
  19. --*/
  20. #include "precomp.h"
  21. #include "pipe.tmh"
  22. #pragma hdrstop
  23. #define BugCheckFileId SRV_FILE_PIPE
  24. STATIC
  25. VOID SRVFASTCALL
  26. RestartCallNamedPipe (
  27. IN OUT PWORK_CONTEXT WorkContext
  28. );
  29. STATIC
  30. VOID SRVFASTCALL
  31. RestartWaitNamedPipe (
  32. IN OUT PWORK_CONTEXT WorkContext
  33. );
  34. STATIC
  35. VOID SRVFASTCALL
  36. RestartPeekNamedPipe (
  37. IN OUT PWORK_CONTEXT WorkContext
  38. );
  39. VOID SRVFASTCALL
  40. RestartRawWriteNamedPipe (
  41. IN OUT PWORK_CONTEXT WorkContext
  42. );
  43. STATIC
  44. VOID SRVFASTCALL
  45. RestartTransactNamedPipe (
  46. IN OUT PWORK_CONTEXT WorkContext
  47. );
  48. NTSTATUS
  49. RestartFastTransactNamedPipe (
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN PIRP Irp,
  52. IN OUT PWORK_CONTEXT WorkContext
  53. );
  54. VOID SRVFASTCALL
  55. RestartFastTransactNamedPipe2 (
  56. IN OUT PWORK_CONTEXT WorkContext
  57. );
  58. VOID SRVFASTCALL
  59. RestartReadNamedPipe (
  60. IN OUT PWORK_CONTEXT WorkContext
  61. );
  62. VOID SRVFASTCALL
  63. RestartWriteNamedPipe (
  64. IN OUT PWORK_CONTEXT WorkContext
  65. );
  66. #ifdef ALLOC_PRAGMA
  67. #pragma alloc_text( PAGE, SrvCallNamedPipe )
  68. #pragma alloc_text( PAGE, SrvWaitNamedPipe )
  69. #pragma alloc_text( PAGE, SrvQueryStateNamedPipe )
  70. #pragma alloc_text( PAGE, SrvQueryInformationNamedPipe )
  71. #pragma alloc_text( PAGE, SrvSetStateNamedPipe )
  72. #pragma alloc_text( PAGE, SrvPeekNamedPipe )
  73. #pragma alloc_text( PAGE, SrvTransactNamedPipe )
  74. #pragma alloc_text( PAGE, SrvFastTransactNamedPipe )
  75. #pragma alloc_text( PAGE, SrvRawWriteNamedPipe )
  76. #pragma alloc_text( PAGE, SrvReadNamedPipe )
  77. #pragma alloc_text( PAGE, SrvWriteNamedPipe )
  78. #pragma alloc_text( PAGE, RestartCallNamedPipe )
  79. #pragma alloc_text( PAGE, RestartWaitNamedPipe )
  80. #pragma alloc_text( PAGE, RestartPeekNamedPipe )
  81. #pragma alloc_text( PAGE, RestartReadNamedPipe )
  82. #pragma alloc_text( PAGE, RestartTransactNamedPipe )
  83. #pragma alloc_text( PAGE, RestartRawWriteNamedPipe )
  84. #pragma alloc_text( PAGE, RestartFastTransactNamedPipe2 )
  85. #pragma alloc_text( PAGE, RestartWriteNamedPipe )
  86. #pragma alloc_text( PAGE8FIL, RestartFastTransactNamedPipe )
  87. #endif
  88. SMB_TRANS_STATUS
  89. SrvCallNamedPipe (
  90. IN OUT PWORK_CONTEXT WorkContext
  91. )
  92. /*++
  93. Routine Description:
  94. This function processes a Call Named pipe request from a
  95. Transaction SMB. This call is handled asynchronously and
  96. is completed in RestartCallNamedPipe.
  97. Arguments:
  98. WorkContext - A pointer to a WORK_CONTEXT block.
  99. Return Value:
  100. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  101. smbtypes.h for a more complete description.
  102. --*/
  103. {
  104. HANDLE fileHandle;
  105. IO_STATUS_BLOCK ioStatusBlock;
  106. OBJECT_ATTRIBUTES objectAttributes;
  107. PFILE_OBJECT fileObject;
  108. OBJECT_HANDLE_INFORMATION handleInformation;
  109. PTRANSACTION transaction;
  110. NTSTATUS status;
  111. UNICODE_STRING pipePath;
  112. UNICODE_STRING fullName;
  113. FILE_PIPE_INFORMATION pipeInformation;
  114. PIRP irp = WorkContext->Irp;
  115. PIO_STACK_LOCATION irpSp;
  116. PAGED_CODE( );
  117. //
  118. // Strip "\PIPE\" prefix from the path string.
  119. //
  120. pipePath = WorkContext->Parameters.Transaction->TransactionName;
  121. if ( pipePath.Length <=
  122. (UNICODE_SMB_PIPE_PREFIX_LENGTH + sizeof(WCHAR)) ) {
  123. SrvSetSmbError( WorkContext, STATUS_INVALID_SMB );
  124. return SmbTransStatusErrorWithoutData;
  125. }
  126. pipePath.Buffer +=
  127. (UNICODE_SMB_PIPE_PREFIX_LENGTH / sizeof(WCHAR)) + 1;
  128. pipePath.Length -= UNICODE_SMB_PIPE_PREFIX_LENGTH + sizeof(WCHAR);
  129. //
  130. // Attempt to open the named pipe.
  131. //
  132. SrvAllocateAndBuildPathName(
  133. &SrvNamedPipeRootDirectory,
  134. &pipePath,
  135. NULL,
  136. &fullName
  137. );
  138. if ( fullName.Buffer == NULL ) {
  139. //
  140. // Unable to allocate heap for the full name.
  141. //
  142. IF_DEBUG(ERRORS) {
  143. SrvPrint0( "SrvCallNamedPipe: Unable to allocate heap for full path name\n" );
  144. }
  145. SrvSetSmbError (WorkContext, STATUS_INSUFF_SERVER_RESOURCES);
  146. IF_DEBUG(TRACE2) SrvPrint0( "SrvCallNamedPipe complete\n" );
  147. return SmbTransStatusErrorWithoutData;
  148. }
  149. SrvInitializeObjectAttributes_U(
  150. &objectAttributes,
  151. &fullName,
  152. OBJ_CASE_INSENSITIVE,
  153. NULL,
  154. NULL
  155. );
  156. INCREMENT_DEBUG_STAT( SrvDbgStatistics.TotalOpenAttempts );
  157. status = SrvIoCreateFile(
  158. WorkContext,
  159. &fileHandle,
  160. GENERIC_READ | GENERIC_WRITE,
  161. &objectAttributes,
  162. &ioStatusBlock,
  163. NULL,
  164. FILE_ATTRIBUTE_NORMAL,
  165. FILE_SHARE_READ | FILE_SHARE_WRITE,
  166. FILE_OPEN,
  167. 0, // Create Options
  168. NULL, // EA Buffer
  169. 0, // EA Length
  170. CreateFileTypeNone,
  171. (PVOID)NULL, // Create parameters
  172. IO_FORCE_ACCESS_CHECK,
  173. NULL
  174. );
  175. FREE_HEAP( fullName.Buffer );
  176. //
  177. // If the user didn't have this permission, update the statistics
  178. // database.
  179. //
  180. if ( status == STATUS_ACCESS_DENIED ) {
  181. SrvStatistics.AccessPermissionErrors++;
  182. }
  183. if (!NT_SUCCESS(status)) {
  184. //
  185. // The server could not open the requested name pipe,
  186. // return the error.
  187. //
  188. IF_SMB_DEBUG(OPEN_CLOSE1) {
  189. SrvPrint2( "SrvCallNamedPipe: Failed to open %ws, err=%x\n",
  190. WorkContext->Parameters.Transaction->TransactionName.Buffer, status );
  191. }
  192. SrvSetSmbError (WorkContext, status);
  193. IF_DEBUG(TRACE2) SrvPrint0( "SrvCallNamedPipe complete\n" );
  194. return SmbTransStatusErrorWithoutData;
  195. }
  196. SRVDBG_CLAIM_HANDLE( fileHandle, "FIL", 15, 0 );
  197. SrvStatistics.TotalFilesOpened++;
  198. //
  199. // Get a pointer to the file object, so that we can directly
  200. // build IRPs for asynchronous operations (read and write).
  201. // Also, get the granted access mask, so that we can prevent the
  202. // client from doing things that it isn't allowed to do.
  203. //
  204. status = ObReferenceObjectByHandle(
  205. fileHandle,
  206. 0,
  207. NULL,
  208. KernelMode,
  209. (PVOID *)&fileObject,
  210. &handleInformation
  211. );
  212. if ( !NT_SUCCESS(status) ) {
  213. SrvLogServiceFailure( SRV_SVC_OB_REF_BY_HANDLE, status );
  214. //
  215. // This internal error bugchecks the system.
  216. //
  217. INTERNAL_ERROR(
  218. ERROR_LEVEL_IMPOSSIBLE,
  219. "SrvCallNamedPipe: unable to reference file handle 0x%lx",
  220. fileHandle,
  221. NULL
  222. );
  223. SrvSetSmbError( WorkContext, status );
  224. IF_DEBUG(TRACE2) SrvPrint0( "SrvCallNamedPipe complete\n" );
  225. return SmbTransStatusErrorWithoutData;
  226. }
  227. //
  228. // Save file handle for the completion routine.
  229. //
  230. transaction = WorkContext->Parameters.Transaction;
  231. transaction->FileHandle = fileHandle;
  232. transaction->FileObject = fileObject;
  233. //
  234. // Set the pipe to message mode, so that we can preform a transceive
  235. //
  236. pipeInformation.CompletionMode = FILE_PIPE_QUEUE_OPERATION;
  237. pipeInformation.ReadMode = FILE_PIPE_MESSAGE_MODE;
  238. status = NtSetInformationFile (
  239. fileHandle,
  240. &ioStatusBlock,
  241. (PVOID)&pipeInformation,
  242. sizeof(pipeInformation),
  243. FilePipeInformation
  244. );
  245. if ( !NT_SUCCESS(status) ) {
  246. INTERNAL_ERROR(
  247. ERROR_LEVEL_UNEXPECTED,
  248. "SrvCallNamedPipe: NtSetInformationFile (pipe information) "
  249. "returned %X",
  250. status,
  251. NULL
  252. );
  253. SrvLogServiceFailure( SRV_SVC_NT_SET_INFO_FILE, status );
  254. SrvSetSmbError( WorkContext, status );
  255. IF_DEBUG(TRACE2) SrvPrint0( "SrvCallNamedPipe complete\n" );
  256. return SmbTransStatusErrorWithoutData;
  257. }
  258. //
  259. // Set the Restart Routine addresses in the work context block.
  260. //
  261. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  262. WorkContext->FspRestartRoutine = RestartCallNamedPipe;
  263. transaction = WorkContext->Parameters.Transaction;
  264. //
  265. // Build the IRP to start a pipe transceive.
  266. // Pass this request to NPFS.
  267. //
  268. //
  269. // Inline SrvBuildIoControlRequest
  270. //
  271. {
  272. //
  273. // Get a pointer to the next stack location. This one is used to
  274. // hold the parameters for the device I/O control request.
  275. //
  276. irpSp = IoGetNextIrpStackLocation( irp );
  277. //
  278. // Set up the completion routine.
  279. //
  280. IoSetCompletionRoutine(
  281. irp,
  282. SrvFsdIoCompletionRoutine,
  283. (PVOID)WorkContext,
  284. TRUE,
  285. TRUE,
  286. TRUE
  287. );
  288. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  289. irpSp->MinorFunction = 0;
  290. irpSp->DeviceObject = IoGetRelatedDeviceObject(fileObject);
  291. irpSp->FileObject = fileObject;
  292. irp->Tail.Overlay.OriginalFileObject = irpSp->FileObject;
  293. irp->Tail.Overlay.Thread = WorkContext->CurrentWorkQueue->IrpThread;
  294. DEBUG irp->RequestorMode = KernelMode;
  295. irp->MdlAddress = NULL;
  296. irp->AssociatedIrp.SystemBuffer = transaction->OutData;
  297. irpSp->Parameters.DeviceIoControl.Type3InputBuffer =
  298. transaction->InData;
  299. //
  300. // Copy the caller's parameters to the service-specific portion of the
  301. // IRP for those parameters that are the same for all three methods.
  302. //
  303. irpSp->Parameters.FileSystemControl.OutputBufferLength =
  304. transaction->MaxDataCount;
  305. irpSp->Parameters.FileSystemControl.InputBufferLength =
  306. transaction->DataCount;
  307. irpSp->Parameters.FileSystemControl.FsControlCode =
  308. FSCTL_PIPE_INTERNAL_TRANSCEIVE;
  309. }
  310. (VOID)IoCallDriver(
  311. irpSp->DeviceObject,
  312. irp
  313. );
  314. //
  315. // The tranceive was successfully started. Return the InProgress
  316. // status to the caller, indicating that the caller should do
  317. // nothing further with the SMB/WorkContext at the present time.
  318. //
  319. IF_DEBUG(TRACE2) SrvPrint0( "SrvCallNamedPipe complete\n" );
  320. return SmbTransStatusInProgress;
  321. } // SrvCallNamedPipe
  322. SMB_TRANS_STATUS
  323. SrvWaitNamedPipe (
  324. IN OUT PWORK_CONTEXT WorkContext
  325. )
  326. /*++
  327. Routine Description:
  328. This function processes a Wait named pipe transaction SMB.
  329. It issues an asynchronous call to NPFS. The function
  330. completetion is handled by RestartWaitNamedPipe().
  331. Arguments:
  332. WorkContext - A pointer to a WORK_CONTEXT block.
  333. Return Value:
  334. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  335. smbtypes.h for a more complete description.
  336. --*/
  337. {
  338. PFILE_PIPE_WAIT_FOR_BUFFER pipeWaitBuffer;
  339. PREQ_TRANSACTION request;
  340. PTRANSACTION transaction;
  341. UNICODE_STRING pipePath;
  342. CLONG nameLength;
  343. PAGED_CODE( );
  344. request = (PREQ_TRANSACTION)WorkContext->RequestParameters;
  345. transaction = WorkContext->Parameters.Transaction;
  346. //
  347. // Allocate and fill in FILE_PIPE_WAIT_FOR_BUFFER structure.
  348. //
  349. pipePath = transaction->TransactionName;
  350. if ( pipePath.Length <= (UNICODE_SMB_PIPE_PREFIX_LENGTH + sizeof(WCHAR)) ) {
  351. //
  352. // The transaction name does not include a pipe name. It's
  353. // either \PIPE or \PIPE\, or it doesn't even have \PIPE.
  354. //
  355. SrvSetSmbError( WorkContext, STATUS_INVALID_SMB );
  356. return SmbTransStatusErrorWithoutData;
  357. }
  358. nameLength = pipePath.Length -
  359. (UNICODE_SMB_PIPE_PREFIX_LENGTH + sizeof(WCHAR)) +
  360. sizeof(WCHAR);
  361. pipeWaitBuffer = ALLOCATE_NONPAGED_POOL(
  362. sizeof(FILE_PIPE_WAIT_FOR_BUFFER) + nameLength,
  363. BlockTypeDataBuffer
  364. );
  365. if ( pipeWaitBuffer == NULL ) {
  366. //
  367. // We could not allocate space for the buffer to issue the
  368. // pipe wait. Fail the request.
  369. //
  370. SrvSetSmbError( WorkContext, STATUS_INSUFF_SERVER_RESOURCES );
  371. IF_DEBUG(TRACE2) SrvPrint0( "SrvWaitNamedPipe complete\n" );
  372. return SmbTransStatusErrorWithoutData;
  373. }
  374. //
  375. // Copy the pipe name not including "\PIPE\" to the pipe wait for
  376. // buffer.
  377. //
  378. pipeWaitBuffer->NameLength = nameLength - sizeof(WCHAR);
  379. RtlCopyMemory(
  380. pipeWaitBuffer->Name,
  381. (PUCHAR)pipePath.Buffer + UNICODE_SMB_PIPE_PREFIX_LENGTH + sizeof(WCHAR),
  382. nameLength
  383. );
  384. //
  385. // Fill in the pipe timeout value if necessary.
  386. //
  387. if ( SmbGetUlong( &request->Timeout ) == 0 ) {
  388. pipeWaitBuffer->TimeoutSpecified = FALSE;
  389. } else {
  390. pipeWaitBuffer->TimeoutSpecified = TRUE;
  391. //
  392. // Convert timeout time from milliseconds to NT relative time.
  393. //
  394. pipeWaitBuffer->Timeout.QuadPart = -1 *
  395. UInt32x32To64( SmbGetUlong( &request->Timeout ), 10*1000 );
  396. }
  397. //
  398. // Set the Restart Routine addresses in the work context block.
  399. //
  400. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  401. WorkContext->FspRestartRoutine = RestartWaitNamedPipe;
  402. //
  403. // Build a Wait named pipe IRP and pass the request to NPFS.
  404. //
  405. SrvBuildIoControlRequest(
  406. WorkContext->Irp,
  407. SrvNamedPipeFileObject,
  408. WorkContext,
  409. IRP_MJ_FILE_SYSTEM_CONTROL,
  410. FSCTL_PIPE_WAIT,
  411. pipeWaitBuffer,
  412. sizeof(*pipeWaitBuffer) + nameLength,
  413. NULL,
  414. 0,
  415. NULL,
  416. NULL
  417. );
  418. (VOID)IoCallDriver( SrvNamedPipeDeviceObject, WorkContext->Irp );
  419. //
  420. // The tranceive was successfully started. Return the InProgress
  421. // status to the caller, indicating that the caller should do
  422. // nothing further with the SMB/WorkContext at the present time.
  423. //
  424. IF_DEBUG(TRACE2) SrvPrint0( "SrvWaitNamedPipe complete\n" );
  425. return SmbTransStatusInProgress;
  426. } // SrvWaitNamedPipe
  427. SMB_TRANS_STATUS
  428. SrvQueryStateNamedPipe (
  429. IN OUT PWORK_CONTEXT WorkContext
  430. )
  431. /*++
  432. Routine Description:
  433. This function processes a Query Named pipe transaction SMB.
  434. Since this call cannot block it is handled synchronously.
  435. Arguments:
  436. WorkContext - A pointer to a WORK_CONTEXT block.
  437. Return Value:
  438. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  439. smbtypes.h for a more complete description.
  440. --*/
  441. {
  442. PREQ_TRANSACTION request;
  443. PTRANSACTION transaction;
  444. HANDLE pipeHandle;
  445. IO_STATUS_BLOCK ioStatusBlock;
  446. USHORT pipeHandleState;
  447. FILE_PIPE_INFORMATION pipeInformation;
  448. FILE_PIPE_LOCAL_INFORMATION pipeLocalInformation;
  449. NTSTATUS status;
  450. USHORT fid;
  451. PRFCB rfcb;
  452. PAGED_CODE( );
  453. request = (PREQ_TRANSACTION)WorkContext->RequestParameters;
  454. transaction = WorkContext->Parameters.Transaction;
  455. //
  456. // Get the FID from the second setup word and use it to generate a
  457. // pointer to the RFCB.
  458. //
  459. // SrvVerifyFid will fill in WorkContext->Rfcb.
  460. //
  461. if( transaction->SetupCount < sizeof(USHORT)*2 )
  462. {
  463. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  464. return SmbTransStatusErrorWithoutData;
  465. }
  466. fid = SmbGetUshort( &transaction->InSetup[1] );
  467. rfcb = SrvVerifyFid(
  468. WorkContext,
  469. fid,
  470. FALSE,
  471. NULL, // don't serialize with raw write
  472. &status
  473. );
  474. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  475. //
  476. // Invalid file ID. Reject the request.
  477. //
  478. IF_DEBUG(SMB_ERRORS) {
  479. SrvPrint1( "SrvQueryStateNamedPipe: Invalid FID: 0x%lx\n", fid );
  480. }
  481. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  482. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryStateNamedPipe complete\n" );
  483. return SmbTransStatusErrorWithoutData;
  484. }
  485. pipeHandle = rfcb->Lfcb->FileHandle;
  486. status = NtQueryInformationFile (
  487. pipeHandle,
  488. &ioStatusBlock,
  489. (PVOID)&pipeInformation,
  490. sizeof(pipeInformation),
  491. FilePipeInformation
  492. );
  493. if (!NT_SUCCESS(status)) {
  494. INTERNAL_ERROR(
  495. ERROR_LEVEL_UNEXPECTED,
  496. "SrvQueryStateNamedPipe: NtQueryInformationFile (pipe "
  497. "information) returned %X",
  498. status,
  499. NULL
  500. );
  501. SrvLogServiceFailure( SRV_SVC_NT_QUERY_INFO_FILE, status );
  502. SrvSetSmbError( WorkContext, status );
  503. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryStateNamedPipe complete\n" );
  504. return SmbTransStatusErrorWithoutData;
  505. }
  506. status = NtQueryInformationFile (
  507. pipeHandle,
  508. &ioStatusBlock,
  509. (PVOID)&pipeLocalInformation,
  510. sizeof(pipeLocalInformation),
  511. FilePipeLocalInformation
  512. );
  513. if (!NT_SUCCESS(status)) {
  514. INTERNAL_ERROR(
  515. ERROR_LEVEL_UNEXPECTED,
  516. "SrvQueryStateNamedPipe: NtQueryInformationFile (pipe local "
  517. "information) returned %X",
  518. status,
  519. NULL
  520. );
  521. SrvLogServiceFailure( SRV_SVC_NT_QUERY_INFO_FILE, status );
  522. SrvSetSmbError( WorkContext, status );
  523. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryStateNamedPipe complete\n" );
  524. return SmbTransStatusErrorWithoutData;
  525. }
  526. //
  527. // Query succeeded generate response
  528. //
  529. pipeHandleState = (USHORT)pipeInformation.CompletionMode
  530. << PIPE_COMPLETION_MODE_BITS;
  531. pipeHandleState |= (USHORT)pipeLocalInformation.NamedPipeEnd
  532. << PIPE_PIPE_END_BITS;
  533. pipeHandleState |= (USHORT)pipeLocalInformation.NamedPipeType
  534. << PIPE_PIPE_TYPE_BITS;
  535. pipeHandleState |= (USHORT)pipeInformation.ReadMode
  536. << PIPE_READ_MODE_BITS;
  537. pipeHandleState |= (USHORT)((pipeLocalInformation.MaximumInstances
  538. << PIPE_MAXIMUM_INSTANCES_BITS)
  539. & SMB_PIPE_UNLIMITED_INSTANCES);
  540. if( transaction->MaxParameterCount < sizeof(USHORT) )
  541. {
  542. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  543. return SmbTransStatusErrorWithoutData;
  544. }
  545. SmbPutUshort(
  546. (PSMB_USHORT)WorkContext->Parameters.Transaction->OutParameters,
  547. pipeHandleState
  548. );
  549. transaction->SetupCount = 0;
  550. transaction->ParameterCount = sizeof(pipeHandleState);
  551. transaction->DataCount = 0;
  552. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryStateNamedPipe complete\n" );
  553. return SmbTransStatusSuccess;
  554. } // SrvQueryStateNamedPipe
  555. SMB_TRANS_STATUS
  556. SrvQueryInformationNamedPipe (
  557. IN OUT PWORK_CONTEXT WorkContext
  558. )
  559. /*++
  560. Routine Description:
  561. This function process a Query named pipe information transaction
  562. SMB. This call is handled synchronously.
  563. Arguments:
  564. WorkContext - A pointer to a WORK_CONTEXT block.
  565. Return Value:
  566. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  567. smbtypes.h for a more complete description.
  568. --*/
  569. {
  570. PREQ_TRANSACTION request;
  571. PTRANSACTION transaction;
  572. HANDLE pipeHandle;
  573. IO_STATUS_BLOCK ioStatusBlock;
  574. FILE_PIPE_LOCAL_INFORMATION pipeLocalInformation;
  575. PNAMED_PIPE_INFORMATION_1 namedPipeInfo;
  576. NTSTATUS status;
  577. USHORT fid;
  578. PRFCB rfcb;
  579. PLFCB lfcb;
  580. USHORT level;
  581. CLONG smbPathLength;
  582. PUNICODE_STRING pipeName;
  583. CLONG actualDataSize;
  584. BOOLEAN returnPipeName;
  585. BOOLEAN isUnicode;
  586. PAGED_CODE( );
  587. request = (PREQ_TRANSACTION)WorkContext->RequestParameters;
  588. transaction = WorkContext->Parameters.Transaction;
  589. //
  590. // Get the FID from the second setup word and use it to generate a
  591. // pointer to the RFCB.
  592. //
  593. // SrvVerifyFid will fill in WorkContext->Rfcb.
  594. //
  595. if( transaction->SetupCount < sizeof(USHORT)*2 )
  596. {
  597. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  598. return SmbTransStatusErrorWithoutData;
  599. }
  600. fid = SmbGetUshort( &transaction->InSetup[1] );
  601. rfcb = SrvVerifyFid(
  602. WorkContext,
  603. fid,
  604. FALSE,
  605. NULL, // don't serialize with raw write
  606. &status
  607. );
  608. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  609. //
  610. // Invalid file ID. Reject the request.
  611. //
  612. IF_DEBUG(SMB_ERRORS) {
  613. SrvPrint1( "SrvQueryStateNamedPipe: Invalid FID: 0x%lx\n", fid );
  614. }
  615. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  616. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryInfoNamedPipe complete\n" );
  617. return SmbTransStatusErrorWithoutData;
  618. }
  619. lfcb = rfcb->Lfcb;
  620. pipeHandle = lfcb->FileHandle;
  621. //
  622. // The information level is stored in paramter byte one.
  623. // Verify that is set correctly.
  624. //
  625. level = SmbGetUshort( (PSMB_USHORT)transaction->InParameters );
  626. if ( level != 1 ) {
  627. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  628. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryInfoNamedPipe complete\n" );
  629. return SmbTransStatusErrorWithoutData;
  630. }
  631. //
  632. // Now check that the response will fit. If everything expect for
  633. // the pipe name fits, return STATUS_BUFFER_OVERFLOW with the
  634. // fixed size portion of the data.
  635. //
  636. // *** Note that Unicode strings must be aligned in the SMB.
  637. //
  638. pipeName = &lfcb->Mfcb->FileName;
  639. actualDataSize = sizeof(NAMED_PIPE_INFORMATION_1) - sizeof(UCHAR);
  640. isUnicode = SMB_IS_UNICODE( WorkContext );
  641. if ( isUnicode ) {
  642. ASSERT( sizeof(WCHAR) == 2 );
  643. actualDataSize = (actualDataSize + 1) & ~1; // align to SHORT
  644. smbPathLength = (CLONG)(pipeName->Length) + sizeof(WCHAR);
  645. } else {
  646. smbPathLength = (CLONG)(RtlUnicodeStringToOemSize( pipeName ));
  647. }
  648. actualDataSize += smbPathLength;
  649. if ( transaction->MaxDataCount <
  650. FIELD_OFFSET(NAMED_PIPE_INFORMATION_1, PipeName ) ) {
  651. SrvSetSmbError( WorkContext, STATUS_BUFFER_TOO_SMALL );
  652. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryInfoNamedPipe complete\n" );
  653. return SmbTransStatusErrorWithoutData;
  654. }
  655. if ( (transaction->MaxDataCount < actualDataSize) ||
  656. (smbPathLength >= MAXIMUM_FILENAME_LENGTH) ) {
  657. //
  658. // Do not return the pipe name. It won't fit in the return buffer.
  659. //
  660. returnPipeName = FALSE;
  661. } else {
  662. returnPipeName = TRUE;
  663. }
  664. //
  665. // Everything is correct, ask NPFS for the information.
  666. //
  667. status = NtQueryInformationFile (
  668. pipeHandle,
  669. &ioStatusBlock,
  670. (PVOID)&pipeLocalInformation,
  671. sizeof(pipeLocalInformation),
  672. FilePipeLocalInformation
  673. );
  674. if (!NT_SUCCESS(status)) {
  675. INTERNAL_ERROR(
  676. ERROR_LEVEL_UNEXPECTED,
  677. "SrvQueryInformationNamedPipe: NtQueryInformationFile (pipe "
  678. "information) returned %X",
  679. status,
  680. NULL
  681. );
  682. SrvLogServiceFailure( SRV_SVC_NT_QUERY_INFO_FILE, status );
  683. SrvSetSmbError( WorkContext, status );
  684. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryInfoNamedPipe complete\n" );
  685. return SmbTransStatusErrorWithoutData;
  686. }
  687. //
  688. // Query succeeded format the response data into the buffer pointed
  689. // at by transaction->OutData
  690. //
  691. namedPipeInfo = (PNAMED_PIPE_INFORMATION_1)transaction->OutData;
  692. if ((pipeLocalInformation.OutboundQuota & 0xffff0000) != 0) {
  693. SmbPutAlignedUshort(
  694. &namedPipeInfo->OutputBufferSize,
  695. (USHORT)0xFFFF
  696. );
  697. } else {
  698. SmbPutAlignedUshort(
  699. &namedPipeInfo->OutputBufferSize,
  700. (USHORT)pipeLocalInformation.OutboundQuota
  701. );
  702. }
  703. if ((pipeLocalInformation.InboundQuota & 0xffff0000) != 0) {
  704. SmbPutAlignedUshort(
  705. &namedPipeInfo->InputBufferSize,
  706. (USHORT)0xFFFF
  707. );
  708. } else {
  709. SmbPutAlignedUshort(
  710. &namedPipeInfo->InputBufferSize,
  711. (USHORT)pipeLocalInformation.InboundQuota
  712. );
  713. }
  714. if ((pipeLocalInformation.MaximumInstances & 0xffffff00) != 0) {
  715. namedPipeInfo->MaximumInstances = (UCHAR)0xFF;
  716. } else {
  717. namedPipeInfo->MaximumInstances =
  718. (UCHAR)pipeLocalInformation.MaximumInstances;
  719. }
  720. if ((pipeLocalInformation.CurrentInstances & 0xffffff00) != 0) {
  721. namedPipeInfo->CurrentInstances = (UCHAR)0xFF;
  722. } else {
  723. namedPipeInfo->CurrentInstances =
  724. (UCHAR)pipeLocalInformation.CurrentInstances;
  725. }
  726. if ( returnPipeName ) {
  727. //
  728. // Copy full pipe path name to the output buffer, appending a NUL.
  729. //
  730. // *** Note that Unicode pipe names must be aligned in the SMB.
  731. //
  732. namedPipeInfo->PipeNameLength = (UCHAR)smbPathLength;
  733. if ( isUnicode ) {
  734. PVOID buffer = ALIGN_SMB_WSTR( namedPipeInfo->PipeName );
  735. RtlCopyMemory( buffer, pipeName->Buffer, smbPathLength );
  736. } else {
  737. UNICODE_STRING source;
  738. OEM_STRING destination;
  739. source.Buffer = pipeName->Buffer;
  740. source.Length = pipeName->Length;
  741. source.MaximumLength = source.Length;
  742. destination.Buffer = (PCHAR) namedPipeInfo->PipeName;
  743. destination.MaximumLength = (USHORT)smbPathLength;
  744. RtlUnicodeStringToOemString(
  745. &destination,
  746. &source,
  747. FALSE
  748. );
  749. }
  750. transaction->DataCount = actualDataSize;
  751. } else {
  752. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  753. transaction->DataCount =
  754. FIELD_OFFSET( NAMED_PIPE_INFORMATION_1, PipeName );
  755. }
  756. //
  757. // Set up to send success response
  758. //
  759. transaction->SetupCount = 0;
  760. transaction->ParameterCount = 0;
  761. IF_DEBUG(TRACE2) SrvPrint0( "SrvQueryInfoNamedPipe complete\n" );
  762. if ( returnPipeName) {
  763. return SmbTransStatusSuccess;
  764. } else {
  765. return SmbTransStatusErrorWithData;
  766. }
  767. } // SrvQueryInformationNamedPipe
  768. SMB_TRANS_STATUS
  769. SrvSetStateNamedPipe (
  770. IN OUT PWORK_CONTEXT WorkContext
  771. )
  772. /*++
  773. Routine Description:
  774. This function processes a set named pipe handle state transaction
  775. SMB. The call is issued synchronously.
  776. Arguments:
  777. WorkContext - A pointer to a WORK_CONTEXT block.
  778. Return Value:
  779. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  780. smbtypes.h for a more complete description.
  781. --*/
  782. {
  783. PREQ_TRANSACTION request;
  784. PTRANSACTION transaction;
  785. HANDLE pipeHandle;
  786. IO_STATUS_BLOCK ioStatusBlock;
  787. USHORT pipeHandleState;
  788. FILE_PIPE_INFORMATION pipeInformation;
  789. NTSTATUS status;
  790. USHORT fid;
  791. PRFCB rfcb;
  792. PAGED_CODE( );
  793. request = (PREQ_TRANSACTION)WorkContext->RequestParameters;
  794. transaction = WorkContext->Parameters.Transaction;
  795. //
  796. // Get the FID from the second setup word and use it to generate a
  797. // pointer to the RFCB.
  798. //
  799. // SrvVerifyFid will fill in WorkContext->Rfcb.
  800. //
  801. if( transaction->SetupCount < sizeof(USHORT)*2 )
  802. {
  803. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  804. return SmbTransStatusErrorWithoutData;
  805. }
  806. fid = SmbGetUshort( &transaction->InSetup[1] );
  807. rfcb = SrvVerifyFid(
  808. WorkContext,
  809. fid,
  810. FALSE,
  811. NULL, // don't serialize with raw write
  812. &status
  813. );
  814. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  815. //
  816. // Invalid file ID. Reject the request.
  817. //
  818. IF_DEBUG(SMB_ERRORS) {
  819. SrvPrint1( "SrvSetStateNamedPipe: Invalid FID: 0x%lx\n", fid );
  820. }
  821. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  822. IF_DEBUG(TRACE2) SrvPrint0( "SrvSetStateNamedPipe complete\n" );
  823. return SmbTransStatusErrorWithoutData;
  824. }
  825. pipeHandle = rfcb->Lfcb->FileHandle;
  826. //
  827. // The SMB contains 2 parameter bytes. Translate these to
  828. // NT format, then attempt to set the named pipe handle state.
  829. //
  830. if( transaction->ParameterCount < sizeof(USHORT) )
  831. {
  832. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  833. return SmbTransStatusErrorWithoutData;
  834. }
  835. pipeHandleState = SmbGetUshort(
  836. (PSMB_USHORT)
  837. WorkContext->Parameters.Transaction->InParameters
  838. );
  839. pipeInformation.CompletionMode =
  840. ((ULONG)pipeHandleState >> PIPE_COMPLETION_MODE_BITS) & 1;
  841. pipeInformation.ReadMode =
  842. ((ULONG)pipeHandleState >> PIPE_READ_MODE_BITS) & 1;
  843. status = NtSetInformationFile (
  844. pipeHandle,
  845. &ioStatusBlock,
  846. (PVOID)&pipeInformation,
  847. sizeof(pipeInformation),
  848. FilePipeInformation
  849. );
  850. if (NT_SUCCESS(status) ) {
  851. status = ioStatusBlock.Status;
  852. }
  853. if (!NT_SUCCESS(status)) {
  854. INTERNAL_ERROR(
  855. ERROR_LEVEL_UNEXPECTED,
  856. "SrvSetStateNamedPipe: NetSetInformationFile (pipe information) "
  857. "returned %X",
  858. status,
  859. NULL
  860. );
  861. SrvLogServiceFailure( SRV_SVC_NT_SET_INFO_FILE, status );
  862. SrvSetSmbError( WorkContext, status );
  863. IF_DEBUG(TRACE2) SrvPrint0( "SrvSetStateNamedPipe complete\n" );
  864. return SmbTransStatusErrorWithoutData;
  865. }
  866. //
  867. // Success. Update our internal pipe handle state.
  868. //
  869. rfcb->BlockingModePipe =
  870. (BOOLEAN)(pipeInformation.CompletionMode ==
  871. FILE_PIPE_QUEUE_OPERATION);
  872. rfcb->ByteModePipe =
  873. (BOOLEAN)(pipeInformation.ReadMode == FILE_PIPE_BYTE_STREAM_MODE);
  874. //
  875. // Now set up for the success response.
  876. //
  877. transaction->SetupCount = 0;
  878. transaction->ParameterCount = 0;
  879. transaction->DataCount = 0;
  880. IF_DEBUG(TRACE2) SrvPrint0( "SrvSetStateNamedPipe complete\n" );
  881. return SmbTransStatusSuccess;
  882. } // SrvSetStateNamedPipe
  883. SMB_TRANS_STATUS
  884. SrvPeekNamedPipe (
  885. IN OUT PWORK_CONTEXT WorkContext
  886. )
  887. /*++
  888. Routine Description:
  889. This function handles a peek named pipe transaction SMB. The
  890. call is issued asynchrously and is completed by RestartPeekNamedPipe().
  891. Arguments:
  892. WorkContext - A pointer to a WORK_CONTEXT block.
  893. Return Value:
  894. status - The result of the operation.
  895. --*/
  896. {
  897. PTRANSACTION transaction;
  898. USHORT fid;
  899. PRFCB rfcb;
  900. PLFCB lfcb;
  901. NTSTATUS status;
  902. PAGED_CODE( );
  903. transaction = WorkContext->Parameters.Transaction;
  904. //
  905. // Get the FID from the second setup word and use it to generate a
  906. // pointer to the RFCB.
  907. //
  908. // SrvVerifyFid will fill in WorkContext->Rfcb.
  909. //
  910. if( transaction->SetupCount < sizeof(USHORT)*2 )
  911. {
  912. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  913. return SmbTransStatusErrorWithoutData;
  914. }
  915. fid = SmbGetUshort( &transaction->InSetup[1] );
  916. rfcb = SrvVerifyFid(
  917. WorkContext,
  918. fid,
  919. FALSE,
  920. SrvRestartExecuteTransaction, // serialize with raw write
  921. &status
  922. );
  923. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  924. if ( !NT_SUCCESS( status ) ) {
  925. //
  926. // Invalid file ID. Reject the request.
  927. //
  928. IF_DEBUG(SMB_ERRORS) {
  929. SrvPrint1( "SrvPeekNamedPipe: Invalid FID: 0x%lx\n", fid );
  930. }
  931. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  932. IF_DEBUG(TRACE2) SrvPrint0( "SrvPeekNamedPipe complete\n" );
  933. return SmbTransStatusErrorWithoutData;
  934. }
  935. //
  936. // The work item has been queued because a raw write is in
  937. // progress.
  938. //
  939. return SmbTransStatusInProgress;
  940. }
  941. //
  942. // Set the Restart Routine addresses in the work context block.
  943. //
  944. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  945. WorkContext->FspRestartRoutine = RestartPeekNamedPipe;
  946. //
  947. // Issue the request to NPFS. We expect both parameters and
  948. // data to be returned. The buffer which we offer is contiguous
  949. // and large enough to contain both.
  950. //
  951. transaction = WorkContext->Parameters.Transaction;
  952. lfcb = rfcb->Lfcb;
  953. SrvBuildIoControlRequest(
  954. WorkContext->Irp,
  955. lfcb->FileObject,
  956. WorkContext,
  957. IRP_MJ_FILE_SYSTEM_CONTROL,
  958. FSCTL_PIPE_PEEK,
  959. transaction->OutParameters,
  960. 0,
  961. NULL,
  962. transaction->MaxParameterCount + transaction->MaxDataCount,
  963. NULL,
  964. NULL
  965. );
  966. //
  967. // Pass the request to NPFS.
  968. //
  969. (VOID)IoCallDriver( lfcb->DeviceObject, WorkContext->Irp );
  970. //
  971. // The peek was successfully started. Return the InProgress
  972. // status to the caller, indicating that the caller should do
  973. // nothing further with the SMB/WorkContext at the present time.
  974. //
  975. IF_DEBUG(TRACE2) SrvPrint0( "SrvPeekNamedPipe complete\n" );
  976. return SmbTransStatusInProgress;
  977. } // SrvPeekNamedPipe
  978. SMB_TRANS_STATUS
  979. SrvTransactNamedPipe (
  980. IN OUT PWORK_CONTEXT WorkContext
  981. )
  982. /*++
  983. Routine Description:
  984. This function handles the transact named pipe transaction SMB.
  985. The call to NPFS is issued asynchronously and is completed by
  986. RestartTransactNamedPipe()
  987. Arguments:
  988. WorkContext - A pointer to a WORK_CONTEXT block.
  989. Return Value:
  990. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  991. smbtypes.h for a more complete description.
  992. --*/
  993. {
  994. PTRANSACTION transaction;
  995. USHORT fid;
  996. PRFCB rfcb;
  997. NTSTATUS status;
  998. PIO_STACK_LOCATION irpSp;
  999. PIRP irp = WorkContext->Irp;
  1000. PAGED_CODE( );
  1001. transaction = WorkContext->Parameters.Transaction;
  1002. //
  1003. // Get the FID from the second setup word and use it to generate a
  1004. // pointer to the RFCB.
  1005. //
  1006. // SrvVerifyFid will fill in WorkContext->Rfcb.
  1007. //
  1008. if( transaction->SetupCount < sizeof(USHORT)*2 )
  1009. {
  1010. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  1011. return SmbTransStatusErrorWithoutData;
  1012. }
  1013. fid = SmbGetUshort( &transaction->InSetup[1] );
  1014. rfcb = SrvVerifyFid(
  1015. WorkContext,
  1016. fid,
  1017. FALSE,
  1018. SrvRestartExecuteTransaction, // serialize with raw write
  1019. &status
  1020. );
  1021. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  1022. if ( !NT_SUCCESS( status ) ) {
  1023. //
  1024. // Invalid file ID. Reject the request.
  1025. //
  1026. IF_DEBUG(SMB_ERRORS) {
  1027. SrvPrint1( "SrvTransactStateNamedPipe: Invalid FID: 0x%lx\n",
  1028. fid );
  1029. }
  1030. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  1031. IF_DEBUG(TRACE2) SrvPrint0( "SrvTransactNamedPipe complete\n" );
  1032. return SmbTransStatusErrorWithoutData;
  1033. }
  1034. //
  1035. // The work item has been queued because a raw write is in
  1036. // progress.
  1037. //
  1038. return SmbTransStatusInProgress;
  1039. }
  1040. //
  1041. // Set the Restart Routine addresses in the work context block.
  1042. //
  1043. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  1044. WorkContext->FspRestartRoutine = RestartTransactNamedPipe;
  1045. transaction = WorkContext->Parameters.Transaction;
  1046. //
  1047. // Inline SrvBuildIoControlRequest
  1048. //
  1049. {
  1050. //
  1051. // Get a pointer to the next stack location. This one is used to
  1052. // hold the parameters for the device I/O control request.
  1053. //
  1054. irpSp = IoGetNextIrpStackLocation( irp );
  1055. //
  1056. // Set up the completion routine.
  1057. //
  1058. IoSetCompletionRoutine(
  1059. irp,
  1060. SrvFsdIoCompletionRoutine,
  1061. (PVOID)WorkContext,
  1062. TRUE,
  1063. TRUE,
  1064. TRUE
  1065. );
  1066. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  1067. irpSp->MinorFunction = 0;
  1068. irpSp->DeviceObject = rfcb->Lfcb->DeviceObject;
  1069. irpSp->FileObject = rfcb->Lfcb->FileObject;
  1070. irp->Tail.Overlay.OriginalFileObject = irpSp->FileObject;
  1071. irp->Tail.Overlay.Thread = WorkContext->CurrentWorkQueue->IrpThread;
  1072. DEBUG irp->RequestorMode = KernelMode;
  1073. irp->MdlAddress = NULL;
  1074. irp->AssociatedIrp.SystemBuffer = transaction->OutData;
  1075. irpSp->Parameters.DeviceIoControl.Type3InputBuffer =
  1076. transaction->InData;
  1077. //
  1078. // Copy the caller's parameters to the service-specific portion of the
  1079. // IRP for those parameters that are the same for all three methods.
  1080. //
  1081. irpSp->Parameters.FileSystemControl.OutputBufferLength =
  1082. transaction->MaxDataCount;
  1083. irpSp->Parameters.FileSystemControl.InputBufferLength =
  1084. transaction->DataCount;
  1085. irpSp->Parameters.FileSystemControl.FsControlCode =
  1086. FSCTL_PIPE_INTERNAL_TRANSCEIVE;
  1087. }
  1088. //
  1089. // Pass the request to NPFS.
  1090. //
  1091. (VOID)IoCallDriver( irpSp->DeviceObject, irp );
  1092. //
  1093. // The tranceive was successfully started. Return the InProgress
  1094. // status to the caller, indicating that the caller should do
  1095. // nothing further with the SMB/WorkContext at the present time.
  1096. //
  1097. IF_DEBUG(TRACE2) SrvPrint0( "SrvTransactNamedPipe complete\n" );
  1098. return SmbTransStatusInProgress;
  1099. } // SrvTransactNamedPipe
  1100. BOOLEAN
  1101. SrvFastTransactNamedPipe (
  1102. IN OUT PWORK_CONTEXT WorkContext,
  1103. OUT SMB_STATUS * SmbStatus
  1104. )
  1105. /*++
  1106. Routine Description:
  1107. This function handles the special case of a single buffer transact
  1108. named pipe transaction SMB. The call to NPFS is issued asynchronously
  1109. and is completed by RestartFastTransactNamedPipe()
  1110. Arguments:
  1111. WorkContext - A pointer to a WORK_CONTEXT block.
  1112. SmbStatus - Status of the transaction.
  1113. Return Value:
  1114. TRUE, if fastpath succeeded,
  1115. FALSE, otherwise. Server must take long path.
  1116. --*/
  1117. {
  1118. USHORT fid;
  1119. PRFCB rfcb;
  1120. PSESSION session;
  1121. NTSTATUS status;
  1122. PIO_STACK_LOCATION irpSp;
  1123. PIRP irp = WorkContext->Irp;
  1124. CLONG outputBufferSize;
  1125. CLONG maxParameterCount;
  1126. CLONG maxDataCount;
  1127. PSMB_USHORT inSetup;
  1128. PSMB_USHORT outSetup;
  1129. PCHAR outParam;
  1130. PCHAR outData;
  1131. CLONG offset;
  1132. CLONG setupOffset;
  1133. PREQ_TRANSACTION request;
  1134. PRESP_TRANSACTION response;
  1135. PSMB_HEADER header;
  1136. PAGED_CODE( );
  1137. header = WorkContext->ResponseHeader;
  1138. request = (PREQ_TRANSACTION)WorkContext->RequestParameters;
  1139. response = (PRESP_TRANSACTION)WorkContext->ResponseParameters;
  1140. //
  1141. // Get the FID from the second setup word and use it to generate a
  1142. // pointer to the RFCB.
  1143. //
  1144. // SrvVerifyFid will fill in WorkContext->Rfcb.
  1145. //
  1146. setupOffset = (CLONG)((CLONG_PTR)(request->Buffer) - (CLONG_PTR)header);
  1147. inSetup = (PSMB_USHORT)( (PCHAR)header + setupOffset );
  1148. fid = SmbGetUshort( &inSetup[1] );
  1149. rfcb = SrvVerifyFid(
  1150. WorkContext,
  1151. fid,
  1152. FALSE,
  1153. SrvRestartSmbReceived, // serialize with raw write
  1154. &status
  1155. );
  1156. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  1157. if ( !NT_SUCCESS( status ) ) {
  1158. //
  1159. // Invalid file ID. Reject the request.
  1160. //
  1161. IF_DEBUG(SMB_ERRORS) {
  1162. SrvPrint1( "SrvTransactStateNamedPipe: Invalid FID: 0x%lx\n",
  1163. fid );
  1164. }
  1165. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  1166. IF_DEBUG(TRACE2) SrvPrint0( "SrvTransactNamedPipe complete\n" );
  1167. *SmbStatus = SmbStatusSendResponse;
  1168. return TRUE;
  1169. }
  1170. //
  1171. // The work item has been queued because a raw write is in
  1172. // progress.
  1173. //
  1174. *SmbStatus = SmbStatusInProgress;
  1175. return TRUE;
  1176. }
  1177. //
  1178. // See and see if all the data will fit into the response buffer.
  1179. // Reject the long path if not the case.
  1180. // The "+1" on the MaxSetupCount calculation below accounts for the
  1181. // USHORT byte count in the buffer.
  1182. //
  1183. maxParameterCount = SmbGetUshort( &request->MaxParameterCount );
  1184. maxDataCount = SmbGetUshort( &request->MaxDataCount );
  1185. session = rfcb->Lfcb->Session;
  1186. outputBufferSize = ((maxParameterCount * sizeof(CHAR) + 3) & ~3) +
  1187. ((maxDataCount * sizeof(CHAR) + 3) & ~3) +
  1188. (((request->MaxSetupCount + 1) * sizeof(USHORT) + 3) & ~3);
  1189. if ( sizeof(SMB_HEADER) +
  1190. sizeof (RESP_TRANSACTION) +
  1191. outputBufferSize
  1192. > (ULONG)session->MaxBufferSize) {
  1193. //
  1194. // This won't fit. Use the long path.
  1195. //
  1196. return(FALSE);
  1197. }
  1198. //
  1199. // If this operation may block, and we are running short of
  1200. // free work items, fail this SMB with an out of resources error.
  1201. //
  1202. if ( SrvReceiveBufferShortage( ) ) {
  1203. SrvStatistics.BlockingSmbsRejected++;
  1204. SrvSetSmbError(
  1205. WorkContext,
  1206. STATUS_INSUFF_SERVER_RESOURCES
  1207. );
  1208. *SmbStatus = SmbStatusSendResponse;
  1209. return TRUE;
  1210. } else {
  1211. //
  1212. // SrvBlockingOpsInProgress has already been incremented.
  1213. // Flag this work item as a blocking operation.
  1214. //
  1215. WorkContext->BlockingOperation = TRUE;
  1216. }
  1217. //
  1218. // Set the Restart Routine addresses in the work context block.
  1219. //
  1220. DEBUG WorkContext->FsdRestartRoutine = NULL;
  1221. //
  1222. // Setup pointers and locals.
  1223. //
  1224. outSetup = (PSMB_USHORT)response->Buffer;
  1225. //
  1226. // The "+1" on the end of the following calculation is to account
  1227. // for the USHORT byte count, which could overwrite data in certain
  1228. // cases should the MaxSetupCount be 0.
  1229. //
  1230. outParam = (PCHAR)(outSetup + (request->MaxSetupCount + 1));
  1231. offset = (CLONG)((outParam - (PCHAR)header + 3) & ~3);
  1232. outParam = (PCHAR)header + offset;
  1233. outData = outParam + maxParameterCount;
  1234. offset = (CLONG)((outData - (PCHAR)header + 3) & ~3);
  1235. outData = (PCHAR)header + offset;
  1236. //
  1237. // Fill in the work context parameters.
  1238. //
  1239. WorkContext->Parameters.FastTransactNamedPipe.OutSetup = outSetup;
  1240. WorkContext->Parameters.FastTransactNamedPipe.OutParam = outParam;
  1241. WorkContext->Parameters.FastTransactNamedPipe.OutData = outData;
  1242. //
  1243. // Inline SrvBuildIoControlRequest
  1244. //
  1245. {
  1246. //
  1247. // Get a pointer to the next stack location. This one is used to
  1248. // hold the parameters for the device I/O control request.
  1249. //
  1250. irpSp = IoGetNextIrpStackLocation( irp );
  1251. //
  1252. // Set up the completion routine.
  1253. //
  1254. IoSetCompletionRoutine(
  1255. irp,
  1256. RestartFastTransactNamedPipe,
  1257. (PVOID)WorkContext,
  1258. TRUE,
  1259. TRUE,
  1260. TRUE
  1261. );
  1262. irpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
  1263. irpSp->MinorFunction = 0;
  1264. irpSp->DeviceObject = rfcb->Lfcb->DeviceObject;
  1265. irpSp->FileObject = rfcb->Lfcb->FileObject;
  1266. irp->Tail.Overlay.OriginalFileObject = irpSp->FileObject;
  1267. irp->Tail.Overlay.Thread = WorkContext->CurrentWorkQueue->IrpThread;
  1268. DEBUG irp->RequestorMode = KernelMode;
  1269. irp->MdlAddress = NULL;
  1270. irp->AssociatedIrp.SystemBuffer = outData;
  1271. irpSp->Parameters.DeviceIoControl.Type3InputBuffer =
  1272. (PCHAR)header + SmbGetUshort( &request->DataOffset );
  1273. //
  1274. // Copy the caller's parameters to the service-specific portion of the
  1275. // IRP for those parameters that are the same for all three methods.
  1276. //
  1277. irpSp->Parameters.FileSystemControl.OutputBufferLength = maxDataCount;
  1278. irpSp->Parameters.FileSystemControl.InputBufferLength =
  1279. SmbGetUshort( &request->DataCount );
  1280. irpSp->Parameters.FileSystemControl.FsControlCode =
  1281. FSCTL_PIPE_INTERNAL_TRANSCEIVE;
  1282. }
  1283. //
  1284. // Pass the request to NPFS.
  1285. //
  1286. (VOID)IoCallDriver( irpSp->DeviceObject, irp );
  1287. //
  1288. // The tranceive was successfully started. Return the InProgress
  1289. // status to the caller, indicating that the caller should do
  1290. // nothing further with the SMB/WorkContext at the present time.
  1291. //
  1292. IF_DEBUG(TRACE2) SrvPrint0( "SrvTransactNamedPipe complete\n" );
  1293. *SmbStatus = SmbStatusInProgress;
  1294. return TRUE;
  1295. } // SrvFastTransactNamedPipe
  1296. SMB_TRANS_STATUS
  1297. SrvRawWriteNamedPipe (
  1298. IN OUT PWORK_CONTEXT WorkContext
  1299. )
  1300. /*++
  1301. Routine Description:
  1302. This function handles the raw write named pipe transaction SMB.
  1303. The call to NPFS is issued asynchronously and is completed by
  1304. RestartRawWriteNamedPipe().
  1305. Arguments:
  1306. WorkContext - A pointer to a WORK_CONTEXT block.
  1307. Return Value:
  1308. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  1309. smbtypes.h for a more complete description.
  1310. --*/
  1311. {
  1312. PTRANSACTION transaction;
  1313. USHORT fid;
  1314. PRFCB rfcb;
  1315. NTSTATUS status;
  1316. PAGED_CODE( );
  1317. transaction = WorkContext->Parameters.Transaction;
  1318. //
  1319. // Get the FID from the second setup word and use it to generate a
  1320. // pointer to the RFCB.
  1321. //
  1322. // SrvVerifyFid will fill in WorkContext->Rfcb.
  1323. //
  1324. if( transaction->SetupCount < sizeof(USHORT)*2 )
  1325. {
  1326. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  1327. return SmbTransStatusErrorWithoutData;
  1328. }
  1329. fid = SmbGetUshort( &transaction->InSetup[1] );
  1330. rfcb = SrvVerifyFid(
  1331. WorkContext,
  1332. fid,
  1333. FALSE,
  1334. SrvRestartExecuteTransaction, // serialize with raw write
  1335. &status
  1336. );
  1337. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  1338. if ( !NT_SUCCESS( status ) ) {
  1339. //
  1340. // Invalid file ID. Reject the request.
  1341. //
  1342. IF_DEBUG(SMB_ERRORS) {
  1343. SrvPrint1( "SrvRawWriteStateNamedPipe: Invalid FID: 0x%lx\n",
  1344. fid );
  1345. }
  1346. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  1347. IF_DEBUG(TRACE2) SrvPrint0( "SrvRawWriteNamedPipe complete\n" );
  1348. return SmbTransStatusErrorWithoutData;
  1349. }
  1350. //
  1351. // The work item has been queued because a raw write is in
  1352. // progress.
  1353. //
  1354. return SmbTransStatusInProgress;
  1355. }
  1356. //
  1357. // We only allow the special 0 bytes message mode write. Otherwise
  1358. // reject the request.
  1359. //
  1360. if ( transaction->DataCount != 2 ||
  1361. transaction->InData[0] != 0 ||
  1362. transaction->InData[1] != 0 ||
  1363. rfcb->ByteModePipe ) {
  1364. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  1365. return SmbTransStatusErrorWithoutData;
  1366. }
  1367. //
  1368. // Set the Restart Routine addresses in the work context block.
  1369. //
  1370. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  1371. WorkContext->FspRestartRoutine = RestartRawWriteNamedPipe;
  1372. SrvBuildIoControlRequest(
  1373. WorkContext->Irp,
  1374. rfcb->Lfcb->FileObject,
  1375. WorkContext,
  1376. IRP_MJ_FILE_SYSTEM_CONTROL,
  1377. FSCTL_PIPE_INTERNAL_WRITE,
  1378. transaction->InData,
  1379. 0,
  1380. NULL,
  1381. 0,
  1382. NULL,
  1383. NULL
  1384. );
  1385. //
  1386. // Pass the request to NPFS.
  1387. //
  1388. IoCallDriver( rfcb->Lfcb->DeviceObject, WorkContext->Irp );
  1389. //
  1390. // The write was successfully started. Return the InProgress
  1391. // status to the caller, indicating that the caller should do
  1392. // nothing further with the SMB/WorkContext at the present time.
  1393. //
  1394. IF_DEBUG(TRACE2) SrvPrint0( "SrvRawWriteNamedPipe complete\n" );
  1395. return SmbTransStatusInProgress;
  1396. } // SrvRawWriteNamedPipe
  1397. VOID SRVFASTCALL
  1398. RestartCallNamedPipe (
  1399. IN OUT PWORK_CONTEXT WorkContext
  1400. )
  1401. /*++
  1402. Routine Description:
  1403. This is the completion routine for SrvCallNamedPipe
  1404. Arguments:
  1405. WorkContext - A pointer to a WORK_CONTEXT block.
  1406. Return Value:
  1407. None.
  1408. --*/
  1409. {
  1410. NTSTATUS status;
  1411. PTRANSACTION transaction;
  1412. PAGED_CODE( );
  1413. //
  1414. // If the transceive request failed, set an error status in the response
  1415. // header.
  1416. //
  1417. status = WorkContext->Irp->IoStatus.Status;
  1418. transaction = WorkContext->Parameters.Transaction;
  1419. if ( status == STATUS_BUFFER_OVERFLOW ) {
  1420. //
  1421. // Down level clients, expect us to return STATUS_SUCCESS.
  1422. //
  1423. if ( !IS_NT_DIALECT( WorkContext->Connection->SmbDialect ) ) {
  1424. status = STATUS_SUCCESS;
  1425. } else {
  1426. //
  1427. // The buffer we supplied is not big enough. Set the
  1428. // error fields in the SMB, but continue so that we send
  1429. // all the information.
  1430. //
  1431. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  1432. }
  1433. } else if ( !NT_SUCCESS(status) ) {
  1434. IF_DEBUG(ERRORS) {
  1435. SrvPrint1( "RestartCallNamedPipe: Pipe transceive failed: %X\n",
  1436. status );
  1437. }
  1438. SrvSetSmbError( WorkContext, status );
  1439. } else {
  1440. //
  1441. // Success. Prepare to generate and send the response.
  1442. //
  1443. transaction->SetupCount = 0;
  1444. transaction->ParameterCount = 0;
  1445. transaction->DataCount = (ULONG)WorkContext->Irp->IoStatus.Information;
  1446. }
  1447. //
  1448. // Close the open pipe handle.
  1449. //
  1450. SRVDBG_RELEASE_HANDLE( transaction->FileHandle, "FIL", 19, transaction );
  1451. SrvNtClose( transaction->FileHandle, TRUE );
  1452. ObDereferenceObject( transaction->FileObject );
  1453. //
  1454. // Respond to the client
  1455. //
  1456. if ( NT_SUCCESS(status) ) {
  1457. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  1458. } else if ( status == STATUS_BUFFER_OVERFLOW ) {
  1459. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusErrorWithData);
  1460. } else {
  1461. IF_DEBUG(ERRORS) SrvPrint1( "Pipe call failed: %X\n", status );
  1462. SrvSetSmbError( WorkContext, status );
  1463. SrvCompleteExecuteTransaction(
  1464. WorkContext,
  1465. SmbTransStatusErrorWithoutData
  1466. );
  1467. }
  1468. IF_DEBUG(TRACE2) SrvPrint0( "RestartCallNamedPipe complete\n" );
  1469. return;
  1470. } // RestartCallNamedPipe
  1471. VOID SRVFASTCALL
  1472. RestartWaitNamedPipe (
  1473. IN OUT PWORK_CONTEXT WorkContext
  1474. )
  1475. /*++
  1476. Routine Description:
  1477. This is the completion routine for SrvWaitNamedPipe
  1478. Arguments:
  1479. WorkContext - A pointer to a WORK_CONTEXT block.
  1480. Return Value:
  1481. None.
  1482. --*/
  1483. {
  1484. PTRANSACTION transaction;
  1485. NTSTATUS status;
  1486. PAGED_CODE( );
  1487. //
  1488. // Deallocate the wait buffer.
  1489. //
  1490. DEALLOCATE_NONPAGED_POOL( WorkContext->Irp->AssociatedIrp.SystemBuffer );
  1491. //
  1492. // If the wait request failed, set an error status in the response
  1493. // header.
  1494. //
  1495. status = WorkContext->Irp->IoStatus.Status;
  1496. if ( !NT_SUCCESS(status) ) {
  1497. IF_DEBUG(ERRORS) SrvPrint1( "Pipe wait failed: %X\n", status );
  1498. SrvSetSmbError( WorkContext, status );
  1499. SrvCompleteExecuteTransaction(
  1500. WorkContext,
  1501. SmbTransStatusErrorWithoutData
  1502. );
  1503. IF_DEBUG(TRACE2) SrvPrint0( "RestartWaitNamedPipe complete\n" );
  1504. return;
  1505. }
  1506. //
  1507. // Success. Prepare to generate and send the response.
  1508. //
  1509. transaction = WorkContext->Parameters.Transaction;
  1510. transaction->SetupCount = 0;
  1511. transaction->ParameterCount = 0;
  1512. transaction->DataCount = 0;
  1513. //
  1514. // Generate and send the response.
  1515. //
  1516. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  1517. IF_DEBUG(TRACE2) SrvPrint0( "RestartWaitNamedPipe complete\n" );
  1518. return;
  1519. } // RestartWaitNamedPipe
  1520. VOID SRVFASTCALL
  1521. RestartPeekNamedPipe (
  1522. IN OUT PWORK_CONTEXT WorkContext
  1523. )
  1524. /*++
  1525. Routine Description:
  1526. This is the completion routine for PeekNamedPipe
  1527. Arguments:
  1528. WorkContext - A pointer to a WORK_CONTEXT block.
  1529. Return Value:
  1530. None.
  1531. --*/
  1532. {
  1533. NTSTATUS status;
  1534. PFILE_PIPE_PEEK_BUFFER pipePeekBuffer;
  1535. PRESP_PEEK_NMPIPE respPeekNmPipe;
  1536. USHORT readDataAvailable, messageLength, namedPipeState;
  1537. PTRANSACTION transaction;
  1538. PAGED_CODE( );
  1539. //
  1540. // If the peek request failed, set an error status in the response
  1541. // header.
  1542. //
  1543. status = WorkContext->Irp->IoStatus.Status;
  1544. if ( status == STATUS_BUFFER_OVERFLOW ) {
  1545. //
  1546. // Down level clients, expect us to return STATUS_SUCCESS.
  1547. //
  1548. if ( !IS_NT_DIALECT( WorkContext->Connection->SmbDialect ) ) {
  1549. status = STATUS_SUCCESS;
  1550. } else {
  1551. //
  1552. // The buffer we supplied is not big enough. Set the
  1553. // error fields in the SMB, but continue so that we send
  1554. // all the information.
  1555. //
  1556. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  1557. }
  1558. } else if ( !NT_SUCCESS(status) ) {
  1559. IF_DEBUG(ERRORS) SrvPrint1( "Pipe peek failed: %X\n", status );
  1560. SrvSetSmbError( WorkContext, status );
  1561. SrvCompleteExecuteTransaction(
  1562. WorkContext,
  1563. SmbTransStatusErrorWithoutData
  1564. );
  1565. IF_DEBUG(TRACE2) SrvPrint0( "RestartPeekNamedPipe complete\n" );
  1566. return;
  1567. }
  1568. //
  1569. // Success. Generate and send the response.
  1570. //
  1571. // The parameter bytes are currently in the format returned by NT.
  1572. // we will reformat them, and leave the extra space between the
  1573. // parameter and data bytes as extra pad.
  1574. //
  1575. //
  1576. // Since the NT and SMB formats overlap
  1577. // First read all the parameters into locals...
  1578. //
  1579. transaction = WorkContext->Parameters.Transaction;
  1580. pipePeekBuffer = (PFILE_PIPE_PEEK_BUFFER)transaction->OutParameters;
  1581. readDataAvailable = (USHORT)pipePeekBuffer->ReadDataAvailable;
  1582. messageLength = (USHORT)pipePeekBuffer->MessageLength;
  1583. namedPipeState = (USHORT)pipePeekBuffer->NamedPipeState;
  1584. //
  1585. // ... then copy them back in the new format.
  1586. //
  1587. respPeekNmPipe = (PRESP_PEEK_NMPIPE)pipePeekBuffer;
  1588. SmbPutAlignedUshort(
  1589. &respPeekNmPipe->ReadDataAvailable,
  1590. readDataAvailable
  1591. );
  1592. SmbPutAlignedUshort(
  1593. &respPeekNmPipe->MessageLength,
  1594. messageLength
  1595. );
  1596. SmbPutAlignedUshort(
  1597. &respPeekNmPipe->NamedPipeState,
  1598. namedPipeState
  1599. );
  1600. //
  1601. // Send the response. Set the output counts.
  1602. //
  1603. // NT return to us 4 ULONGS of parameter bytes, followed by data.
  1604. // We return to the client 6 parameter bytes.
  1605. //
  1606. transaction->SetupCount = 0;
  1607. transaction->ParameterCount = 6;
  1608. transaction->DataCount = (ULONG)WorkContext->Irp->IoStatus.Information -
  1609. (4 * sizeof(ULONG));
  1610. if (NT_SUCCESS(status)) {
  1611. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  1612. } else {
  1613. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusErrorWithData);
  1614. }
  1615. IF_DEBUG(TRACE2) SrvPrint0( "RestartPeekNamedPipe complete\n" );
  1616. return;
  1617. } // RestartPeekNamedPipe
  1618. VOID SRVFASTCALL
  1619. RestartTransactNamedPipe (
  1620. IN OUT PWORK_CONTEXT WorkContext
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. This is the completion routine for SrvTransactNamedPipe
  1625. Arguments:
  1626. WorkContext - A pointer to a WORK_CONTEXT block.
  1627. Return Value:
  1628. None.
  1629. --*/
  1630. {
  1631. NTSTATUS status;
  1632. PTRANSACTION transaction;
  1633. PAGED_CODE( );
  1634. //
  1635. // If the transceive request failed, set an error status in the response
  1636. // header.
  1637. //
  1638. status = WorkContext->Irp->IoStatus.Status;
  1639. if ( status == STATUS_BUFFER_OVERFLOW ) {
  1640. #if 0
  1641. //
  1642. // Down level clients, expect us to return STATUS_SUCCESS.
  1643. //
  1644. if ( !IS_NT_DIALECT( WorkContext->Connection->SmbDialect ) ) {
  1645. status = STATUS_SUCCESS;
  1646. } else {
  1647. //
  1648. // The buffer we supplied is not big enough. Set the
  1649. // error fields in the SMB, but continue so that we send
  1650. // all the information.
  1651. //
  1652. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  1653. }
  1654. #else
  1655. //
  1656. // os/2 returns ERROR_MORE_DATA in this case, why we convert
  1657. // this to NO_ERROR is a mystery.
  1658. //
  1659. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  1660. #endif
  1661. } else if ( !NT_SUCCESS(status) ) {
  1662. IF_DEBUG(ERRORS) SrvPrint1( "Pipe transceive failed: %X\n", status );
  1663. SrvSetSmbError(WorkContext, status);
  1664. SrvCompleteExecuteTransaction(
  1665. WorkContext,
  1666. SmbTransStatusErrorWithoutData
  1667. );
  1668. IF_DEBUG(TRACE2) SrvPrint0( "RestartTransactNamedPipe complete\n" );
  1669. return;
  1670. }
  1671. //
  1672. // Success. Generate and send the response.
  1673. //
  1674. transaction = WorkContext->Parameters.Transaction;
  1675. transaction->SetupCount = 0;
  1676. transaction->ParameterCount = 0;
  1677. transaction->DataCount = (ULONG)WorkContext->Irp->IoStatus.Information;
  1678. if ( NT_SUCCESS(status) ) {
  1679. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  1680. } else {
  1681. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusErrorWithData);
  1682. }
  1683. IF_DEBUG(TRACE2) SrvPrint0( "RestartTransactNamedPipe complete\n" );
  1684. return;
  1685. } // RestartTransactNamedpipe
  1686. NTSTATUS
  1687. RestartFastTransactNamedPipe (
  1688. IN PDEVICE_OBJECT DeviceObject,
  1689. IN PIRP Irp,
  1690. IN OUT PWORK_CONTEXT WorkContext
  1691. )
  1692. /*++
  1693. Routine Description:
  1694. This is the completion routine for SrvFastTransactNamedPipe
  1695. Arguments:
  1696. DeviceObject - Pointer to target device object for the request.
  1697. Irp - Pointer to I/O request packet
  1698. WorkContext - A pointer to a WORK_CONTEXT block.
  1699. Return Value:
  1700. STATUS_MORE_PROCESSING_REQUIRED.
  1701. --*/
  1702. {
  1703. NTSTATUS status;
  1704. PSMB_HEADER header;
  1705. PRESP_TRANSACTION response;
  1706. PSMB_USHORT byteCountPtr;
  1707. PCHAR paramPtr;
  1708. CLONG paramOffset;
  1709. PCHAR dataPtr;
  1710. CLONG dataOffset;
  1711. CLONG dataLength;
  1712. CLONG sendLength;
  1713. UNLOCKABLE_CODE( 8FIL );
  1714. //
  1715. // Reset the IRP cancelled bit.
  1716. //
  1717. Irp->Cancel = FALSE;
  1718. //
  1719. // If the transceive request failed, set an error status in the response
  1720. // header.
  1721. //
  1722. status = WorkContext->Irp->IoStatus.Status;
  1723. if ( status == STATUS_BUFFER_OVERFLOW ) {
  1724. //
  1725. // os/2 returns ERROR_MORE_DATA in this case, why we convert
  1726. // this to NO_ERROR is a mystery.
  1727. //
  1728. SrvSetBufferOverflowError( WorkContext );
  1729. } else if ( !NT_SUCCESS(status) ) {
  1730. IF_DEBUG(ERRORS) SrvPrint1( "Pipe transceive failed: %X\n", status );
  1731. if ( KeGetCurrentIrql() >= DISPATCH_LEVEL ) {
  1732. WorkContext->FspRestartRoutine = RestartFastTransactNamedPipe2;
  1733. QUEUE_WORK_TO_FSP( WorkContext );
  1734. return STATUS_MORE_PROCESSING_REQUIRED;
  1735. }
  1736. RestartFastTransactNamedPipe2( WorkContext );
  1737. goto error_no_data;
  1738. }
  1739. //
  1740. // Success. Generate and send the response.
  1741. //
  1742. dataLength = (CLONG)WorkContext->Irp->IoStatus.Information;
  1743. header = WorkContext->ResponseHeader;
  1744. //
  1745. // Save a pointer to the byte count field.
  1746. //
  1747. // If the output data and parameters are not already in the SMB
  1748. // buffer we must calculate how much of the parameters and data can
  1749. // be sent in this response. The maximum amount we can send is
  1750. // minimum of the size of our buffer and the size of the client's
  1751. // buffer.
  1752. //
  1753. // The parameter and data byte blocks are aligned on longword
  1754. // boundaries in the message.
  1755. //
  1756. byteCountPtr = WorkContext->Parameters.FastTransactNamedPipe.OutSetup;
  1757. //
  1758. // The data and paramter are already in the SMB buffer. The entire
  1759. // response will fit in one response buffer and there is no copying
  1760. // to do.
  1761. //
  1762. paramPtr = WorkContext->Parameters.FastTransactNamedPipe.OutParam;
  1763. paramOffset = (CLONG)(paramPtr - (PCHAR)header);
  1764. dataPtr = WorkContext->Parameters.FastTransactNamedPipe.OutData;
  1765. dataOffset = (CLONG)(dataPtr - (PCHAR)header);
  1766. //
  1767. // The client wants a response. Build the first (and possibly only)
  1768. // response. The last received SMB of the transaction request was
  1769. // retained for this purpose.
  1770. //
  1771. response = (PRESP_TRANSACTION)WorkContext->ResponseParameters;
  1772. //
  1773. // Build the parameters portion of the response.
  1774. //
  1775. response->WordCount = (UCHAR)10;
  1776. SmbPutUshort( &response->TotalParameterCount,
  1777. (USHORT)0
  1778. );
  1779. SmbPutUshort( &response->TotalDataCount,
  1780. (USHORT)dataLength
  1781. );
  1782. SmbPutUshort( &response->Reserved, 0 );
  1783. response->SetupCount = (UCHAR)0;
  1784. response->Reserved2 = 0;
  1785. //
  1786. // We need to be sure we're not sending uninitialized kernel memory
  1787. // back to the client with the response, so zero out the range between
  1788. // byteCountPtr and dataPtr.
  1789. //
  1790. RtlZeroMemory(byteCountPtr,(ULONG)(dataPtr - (PCHAR)byteCountPtr));
  1791. //
  1792. // Finish filling in the response parameters.
  1793. //
  1794. SmbPutUshort( &response->ParameterCount, (USHORT)0 );
  1795. SmbPutUshort( &response->ParameterOffset, (USHORT)paramOffset );
  1796. SmbPutUshort( &response->ParameterDisplacement, 0 );
  1797. SmbPutUshort( &response->DataCount, (USHORT)dataLength );
  1798. SmbPutUshort( &response->DataOffset, (USHORT)dataOffset );
  1799. SmbPutUshort( &response->DataDisplacement, 0 );
  1800. SmbPutUshort(
  1801. byteCountPtr,
  1802. (USHORT)(dataPtr - (PCHAR)(byteCountPtr + 1) + dataLength)
  1803. );
  1804. //
  1805. // Calculate the length of the response message.
  1806. //
  1807. sendLength = (CLONG)( dataPtr + dataLength -
  1808. (PCHAR)WorkContext->ResponseHeader );
  1809. WorkContext->ResponseBuffer->DataLength = sendLength;
  1810. //
  1811. // Set the bit in the SMB that indicates this is a response from the
  1812. // server.
  1813. //
  1814. WorkContext->ResponseHeader->Flags |= SMB_FLAGS_SERVER_TO_REDIR;
  1815. //
  1816. // Send the response.
  1817. //
  1818. SRV_START_SEND_2(
  1819. WorkContext,
  1820. SrvFsdRestartSmbAtSendCompletion,
  1821. NULL,
  1822. NULL
  1823. );
  1824. error_no_data:
  1825. //
  1826. // The response send is in progress. The caller will assume
  1827. // the we will handle send completion.
  1828. //
  1829. // Return STATUS_MORE_PROCESSING_REQUIRED so that IoCompleteRequest
  1830. // will stop working on the IRP.
  1831. //
  1832. IF_DEBUG(TRACE2) SrvPrint0( "RestartTransactNamedPipe complete\n" );
  1833. return STATUS_MORE_PROCESSING_REQUIRED;
  1834. } // RestartFastTransactNamedPipe
  1835. VOID SRVFASTCALL
  1836. RestartFastTransactNamedPipe2 (
  1837. IN OUT PWORK_CONTEXT WorkContext
  1838. )
  1839. /*++
  1840. Routine Description:
  1841. This is the completion routine for SrvFastTransactNamedPipe
  1842. Arguments:
  1843. WorkContext - A pointer to a WORK_CONTEXT block.
  1844. Return Value:
  1845. None.
  1846. --*/
  1847. {
  1848. PAGED_CODE( );
  1849. //
  1850. // The transceive request failed. Set an error status in the response
  1851. // header.
  1852. //
  1853. SrvSetSmbError( WorkContext, WorkContext->Irp->IoStatus.Status );
  1854. //
  1855. // An error occurred, so no transaction-specific response data
  1856. // will be returned.
  1857. //
  1858. // Calculate the length of the response message.
  1859. //
  1860. WorkContext->ResponseBuffer->DataLength =
  1861. (CLONG)( (PCHAR)WorkContext->ResponseParameters -
  1862. (PCHAR)WorkContext->ResponseHeader );
  1863. //
  1864. // Send the response.
  1865. //
  1866. SRV_START_SEND_2(
  1867. WorkContext,
  1868. SrvFsdRestartSmbAtSendCompletion,
  1869. NULL,
  1870. NULL
  1871. );
  1872. return;
  1873. } // RestartFastTransactNamedPipe2
  1874. VOID SRVFASTCALL
  1875. RestartRawWriteNamedPipe (
  1876. IN OUT PWORK_CONTEXT WorkContext
  1877. )
  1878. /*++
  1879. Routine Description:
  1880. This is the completion routine for SrvRawWriteNamedPipe
  1881. Arguments:
  1882. WorkContext - A pointer to a WORK_CONTEXT block.
  1883. Return Value:
  1884. None.
  1885. --*/
  1886. {
  1887. NTSTATUS status;
  1888. PTRANSACTION transaction;
  1889. PAGED_CODE( );
  1890. //
  1891. // If the write request failed, set an error status in the response
  1892. // header.
  1893. //
  1894. status = WorkContext->Irp->IoStatus.Status;
  1895. if ( !NT_SUCCESS(status) ) {
  1896. IF_DEBUG(ERRORS) SrvPrint1( "Pipe raw write failed: %X\n", status );
  1897. SrvSetSmbError( WorkContext, status );
  1898. SrvCompleteExecuteTransaction(
  1899. WorkContext,
  1900. SmbTransStatusErrorWithoutData
  1901. );
  1902. IF_DEBUG(TRACE2) SrvPrint0( "RestartRawWriteNamedPipe complete\n" );
  1903. return;
  1904. }
  1905. //
  1906. // Success. Generate and send the response.
  1907. //
  1908. transaction = WorkContext->Parameters.Transaction;
  1909. transaction->SetupCount = 0;
  1910. transaction->ParameterCount = 2;
  1911. transaction->DataCount = 0;
  1912. SmbPutUshort( (PSMB_USHORT)transaction->OutParameters, 2 );
  1913. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  1914. IF_DEBUG(TRACE2) SrvPrint0( "RestartRawWriteNamedPipe complete\n" );
  1915. return;
  1916. } // RestartRawWriteNamedpipe
  1917. SMB_TRANS_STATUS
  1918. SrvWriteNamedPipe (
  1919. IN OUT PWORK_CONTEXT WorkContext
  1920. )
  1921. /*++
  1922. Routine Description:
  1923. This function handles the raw write named pipe transaction SMB.
  1924. The call to NPFS is issued asynchronously and is completed by
  1925. RestartRawWriteNamedPipe().
  1926. Arguments:
  1927. WorkContext - A pointer to a WORK_CONTEXT block.
  1928. Return Value:
  1929. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  1930. smbtypes.h for a more complete description.
  1931. --*/
  1932. {
  1933. PTRANSACTION transaction;
  1934. USHORT fid;
  1935. PRFCB rfcb;
  1936. PLFCB lfcb;
  1937. NTSTATUS status;
  1938. LARGE_INTEGER offset;
  1939. ULONG key = 0;
  1940. PCHAR writeAddress;
  1941. CLONG writeLength;
  1942. PAGED_CODE( );
  1943. transaction = WorkContext->Parameters.Transaction;
  1944. //
  1945. // Get the FID from the second setup word and use it to generate a
  1946. // pointer to the RFCB.
  1947. //
  1948. // SrvVerifyFid will fill in WorkContext->Rfcb.
  1949. //
  1950. if( transaction->SetupCount < sizeof(USHORT)*2 )
  1951. {
  1952. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  1953. return SmbTransStatusErrorWithoutData;
  1954. }
  1955. fid = SmbGetUshort( &transaction->InSetup[1] );
  1956. IF_DEBUG(IPX_PIPES) {
  1957. KdPrint(("SrvWriteNamedPipe: fid = %x length = %d\n",
  1958. fid, transaction->DataCount));
  1959. }
  1960. rfcb = SrvVerifyFid(
  1961. WorkContext,
  1962. fid,
  1963. FALSE,
  1964. SrvRestartExecuteTransaction, // serialize with raw write
  1965. &status
  1966. );
  1967. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  1968. if ( !NT_SUCCESS( status ) ) {
  1969. //
  1970. // Invalid file ID. Reject the request.
  1971. //
  1972. IF_DEBUG(SMB_ERRORS) {
  1973. SrvPrint1( "SrvWriteNamedPipe: Invalid FID: 0x%lx\n",
  1974. fid );
  1975. }
  1976. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  1977. IF_DEBUG(TRACE2) SrvPrint0( "SrvWriteNamedPipe complete\n" );
  1978. return SmbTransStatusErrorWithoutData;
  1979. }
  1980. //
  1981. // The work item has been queued because a raw write is in
  1982. // progress.
  1983. //
  1984. return SmbTransStatusInProgress;
  1985. }
  1986. lfcb = rfcb->Lfcb;
  1987. writeLength = transaction->DataCount;
  1988. writeAddress = transaction->InData;
  1989. //
  1990. // Try the fast I/O path first. If that fails, fall through to the
  1991. // normal build-an-IRP path.
  1992. //
  1993. if ( lfcb->FastIoWrite != NULL ) {
  1994. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastWritesAttempted );
  1995. try {
  1996. if ( lfcb->FastIoWrite(
  1997. lfcb->FileObject,
  1998. &offset,
  1999. writeLength,
  2000. TRUE,
  2001. key,
  2002. writeAddress,
  2003. &WorkContext->Irp->IoStatus,
  2004. lfcb->DeviceObject
  2005. ) ) {
  2006. //
  2007. // The fast I/O path worked. Call the restart routine directly
  2008. // to do postprocessing (including sending the response).
  2009. //
  2010. RestartWriteNamedPipe( WorkContext );
  2011. IF_DEBUG(IPX_PIPES) SrvPrint0( "SrvWriteNamedPipe complete.\n" );
  2012. return SmbTransStatusInProgress;
  2013. }
  2014. }
  2015. except( EXCEPTION_EXECUTE_HANDLER ) {
  2016. // Fall through to the slow path on an exception
  2017. status = GetExceptionCode();
  2018. IF_DEBUG(ERRORS) {
  2019. KdPrint(("FastIoRead threw exception %x\n", status ));
  2020. }
  2021. }
  2022. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastWritesFailed );
  2023. }
  2024. IF_DEBUG(IPX_PIPES) {
  2025. KdPrint(("SrvWriteNamedPipe: Using slow path.\n"));
  2026. }
  2027. //
  2028. // The turbo path failed. Build the write request, reusing the
  2029. // receive IRP.
  2030. //
  2031. // Build the PIPE_INTERNAL_WRITE IRP.
  2032. //
  2033. SrvBuildIoControlRequest(
  2034. WorkContext->Irp,
  2035. lfcb->FileObject,
  2036. WorkContext,
  2037. IRP_MJ_FILE_SYSTEM_CONTROL,
  2038. FSCTL_PIPE_INTERNAL_WRITE,
  2039. writeAddress,
  2040. writeLength,
  2041. NULL,
  2042. 0,
  2043. NULL,
  2044. NULL
  2045. );
  2046. //
  2047. // Pass the request to the file system.
  2048. //
  2049. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  2050. WorkContext->FspRestartRoutine = RestartWriteNamedPipe;
  2051. (VOID)IoCallDriver( lfcb->DeviceObject, WorkContext->Irp );
  2052. //
  2053. // The write has been started. Control will return to
  2054. // RestartWriteNamedPipe when the write completes.
  2055. //
  2056. IF_DEBUG(TRACE2) SrvPrint0( "SrvWriteNamedPipe complete\n" );
  2057. return SmbTransStatusInProgress;
  2058. } // SrvWriteNamedPipe
  2059. VOID SRVFASTCALL
  2060. RestartWriteNamedPipe (
  2061. IN OUT PWORK_CONTEXT WorkContext
  2062. )
  2063. /*++
  2064. Routine Description:
  2065. This is the completion routine for SrvRawWriteNamedPipe
  2066. Arguments:
  2067. WorkContext - A pointer to a WORK_CONTEXT block.
  2068. Return Value:
  2069. None.
  2070. --*/
  2071. {
  2072. NTSTATUS status;
  2073. PIO_STATUS_BLOCK iosb;
  2074. PTRANSACTION transaction;
  2075. PAGED_CODE( );
  2076. //
  2077. // If the write request failed, set an error status in the response
  2078. // header.
  2079. //
  2080. iosb = &WorkContext->Irp->IoStatus;
  2081. status = iosb->Status;
  2082. IF_DEBUG(IPX_PIPES) {
  2083. KdPrint(("RestartWriteNamedPipe: Status = %x\n", status));
  2084. }
  2085. if ( !NT_SUCCESS(status) ) {
  2086. IF_DEBUG(ERRORS) SrvPrint1( " pipe write failed: %X\n", status );
  2087. SrvSetSmbError( WorkContext, status );
  2088. SrvCompleteExecuteTransaction(
  2089. WorkContext,
  2090. SmbTransStatusErrorWithoutData
  2091. );
  2092. IF_DEBUG(TRACE2) SrvPrint0( "RestartWriteNamedPipe complete\n" );
  2093. return;
  2094. }
  2095. //
  2096. // Success. Generate and send the response.
  2097. //
  2098. transaction = WorkContext->Parameters.Transaction;
  2099. transaction->SetupCount = 0;
  2100. transaction->ParameterCount = 2;
  2101. transaction->DataCount = 0;
  2102. SmbPutUshort( (PSMB_USHORT)transaction->OutParameters,
  2103. (USHORT)iosb->Information
  2104. );
  2105. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  2106. IF_DEBUG(TRACE2) SrvPrint0( "RestartWriteNamedPipe complete\n" );
  2107. return;
  2108. } // RestartWriteNamedPipe
  2109. SMB_TRANS_STATUS
  2110. SrvReadNamedPipe (
  2111. IN OUT PWORK_CONTEXT WorkContext
  2112. )
  2113. /*++
  2114. Routine Description:
  2115. This function handles the raw Read named pipe transaction SMB.
  2116. The call to NPFS is issued asynchronously and is completed by
  2117. RestartRawReadNamedPipe().
  2118. Arguments:
  2119. WorkContext - A pointer to a WORK_CONTEXT block.
  2120. Return Value:
  2121. SMB_TRANS_STATUS - Indicates whether an error occurred. See
  2122. smbtypes.h for a more complete description.
  2123. --*/
  2124. {
  2125. PTRANSACTION transaction;
  2126. USHORT fid;
  2127. PRFCB rfcb;
  2128. PLFCB lfcb;
  2129. NTSTATUS status;
  2130. LARGE_INTEGER offset;
  2131. ULONG key = 0;
  2132. PCHAR readAddress;
  2133. CLONG readLength;
  2134. PAGED_CODE( );
  2135. transaction = WorkContext->Parameters.Transaction;
  2136. //
  2137. // Get the FID from the second setup word and use it to generate a
  2138. // pointer to the RFCB.
  2139. //
  2140. // SrvVerifyFid will fill in WorkContext->Rfcb.
  2141. //
  2142. if( transaction->SetupCount < sizeof(USHORT)*2 )
  2143. {
  2144. SrvSetSmbError( WorkContext, STATUS_INVALID_PARAMETER );
  2145. return SmbTransStatusErrorWithoutData;
  2146. }
  2147. fid = SmbGetUshort( &transaction->InSetup[1] );
  2148. IF_DEBUG(IPX_PIPES) {
  2149. KdPrint(("SrvReadNamedPipe: fid = %x length = %d\n",
  2150. fid, transaction->MaxDataCount));
  2151. }
  2152. rfcb = SrvVerifyFid(
  2153. WorkContext,
  2154. fid,
  2155. FALSE,
  2156. SrvRestartExecuteTransaction, // serialize with raw Read
  2157. &status
  2158. );
  2159. if ( rfcb == SRV_INVALID_RFCB_POINTER ) {
  2160. if ( !NT_SUCCESS( status ) ) {
  2161. //
  2162. // Invalid file ID. Reject the request.
  2163. //
  2164. IF_DEBUG(SMB_ERRORS) {
  2165. SrvPrint1( "SrvReadNamedPipe: Invalid FID: 0x%lx\n",
  2166. fid );
  2167. }
  2168. SrvSetSmbError( WorkContext, STATUS_INVALID_HANDLE );
  2169. IF_DEBUG(TRACE2) SrvPrint0( "SrvReadNamedPipe complete\n" );
  2170. return SmbTransStatusErrorWithoutData;
  2171. }
  2172. //
  2173. // The work item has been queued because a raw Read is in
  2174. // progress.
  2175. //
  2176. return SmbTransStatusInProgress;
  2177. }
  2178. lfcb = rfcb->Lfcb;
  2179. readLength = transaction->MaxDataCount;
  2180. readAddress = transaction->OutData;
  2181. //
  2182. // Try the fast I/O path first. If that fails, fall through to the
  2183. // normal build-an-IRP path.
  2184. //
  2185. if ( lfcb->FastIoRead != NULL ) {
  2186. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastReadsAttempted );
  2187. try {
  2188. if ( lfcb->FastIoRead(
  2189. lfcb->FileObject,
  2190. &offset,
  2191. readLength,
  2192. TRUE,
  2193. key,
  2194. readAddress,
  2195. &WorkContext->Irp->IoStatus,
  2196. lfcb->DeviceObject
  2197. ) ) {
  2198. //
  2199. // The fast I/O path worked. Call the restart routine directly
  2200. // to do postprocessing (including sending the response).
  2201. //
  2202. RestartReadNamedPipe( WorkContext );
  2203. IF_SMB_DEBUG(READ_WRITE2) SrvPrint0( "SrvReadNamedPipe complete.\n" );
  2204. return SmbTransStatusInProgress;
  2205. }
  2206. }
  2207. except( EXCEPTION_EXECUTE_HANDLER ) {
  2208. // Fall through to the slow path on an exception
  2209. status = GetExceptionCode();
  2210. IF_DEBUG(ERRORS) {
  2211. KdPrint(("FastIoRead threw exception %x\n", status ));
  2212. }
  2213. }
  2214. INCREMENT_DEBUG_STAT2( SrvDbgStatistics.FastReadsFailed );
  2215. }
  2216. //
  2217. // The turbo path failed. Build the Read request, reusing the
  2218. // receive IRP.
  2219. //
  2220. // Build the PIPE_INTERNAL_READ IRP.
  2221. //
  2222. SrvBuildIoControlRequest(
  2223. WorkContext->Irp,
  2224. lfcb->FileObject,
  2225. WorkContext,
  2226. IRP_MJ_FILE_SYSTEM_CONTROL,
  2227. FSCTL_PIPE_INTERNAL_READ,
  2228. readAddress,
  2229. 0,
  2230. NULL,
  2231. readLength,
  2232. NULL,
  2233. NULL
  2234. );
  2235. //
  2236. // Pass the request to the file system.
  2237. //
  2238. WorkContext->FsdRestartRoutine = SrvQueueWorkToFspAtDpcLevel;
  2239. WorkContext->FspRestartRoutine = RestartReadNamedPipe;
  2240. (VOID)IoCallDriver( lfcb->DeviceObject, WorkContext->Irp );
  2241. //
  2242. // The Read has been started. Control will return to
  2243. // SrvFsdRestartRead when the Read completes.
  2244. //
  2245. IF_DEBUG(TRACE2) SrvPrint0( "SrvReadNamedPipe complete\n" );
  2246. return SmbTransStatusInProgress;
  2247. } // SrvReadNamedPipe
  2248. VOID SRVFASTCALL
  2249. RestartReadNamedPipe (
  2250. IN OUT PWORK_CONTEXT WorkContext
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. This is the completion routine for SrvRawReadNamedPipe
  2255. Arguments:
  2256. WorkContext - A pointer to a WORK_CONTEXT block.
  2257. Return Value:
  2258. None.
  2259. --*/
  2260. {
  2261. NTSTATUS status;
  2262. PTRANSACTION transaction;
  2263. PAGED_CODE( );
  2264. //
  2265. // If the transceive request failed, set an error status in the response
  2266. // header.
  2267. //
  2268. status = WorkContext->Irp->IoStatus.Status;
  2269. if ( status == STATUS_BUFFER_OVERFLOW ) {
  2270. SrvSetSmbError2( WorkContext, STATUS_BUFFER_OVERFLOW, TRUE );
  2271. } else if ( !NT_SUCCESS(status) ) {
  2272. IF_DEBUG(ERRORS) SrvPrint1( "Pipe transceive failed: %X\n", status );
  2273. SrvSetSmbError(WorkContext, status);
  2274. SrvCompleteExecuteTransaction(
  2275. WorkContext,
  2276. SmbTransStatusErrorWithoutData
  2277. );
  2278. IF_DEBUG(TRACE2) SrvPrint0( "RestartReadNamedPipe complete\n" );
  2279. return;
  2280. }
  2281. //
  2282. // Success. Generate and send the response.
  2283. //
  2284. transaction = WorkContext->Parameters.Transaction;
  2285. transaction->SetupCount = 0;
  2286. transaction->ParameterCount = 0;
  2287. transaction->DataCount = (ULONG)WorkContext->Irp->IoStatus.Information;
  2288. if ( NT_SUCCESS(status) ) {
  2289. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusSuccess);
  2290. } else {
  2291. SrvCompleteExecuteTransaction(WorkContext, SmbTransStatusErrorWithData);
  2292. }
  2293. IF_DEBUG(TRACE2) SrvPrint0( "RestartReadNamedPipe complete\n" );
  2294. return;
  2295. } // RestartReadNamedPipe