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.

2284 lines
72 KiB

  1. /*++ Copyright (c) 1987-1993 Microsoft Corporation
  2. Module Name:
  3. SmbPse.c
  4. Abstract:
  5. This module defines the types and functions related to the SMB protocol
  6. selection engine: the component that translates minirdr calldowns into
  7. SMBs.
  8. Author:
  9. Joe Linn [JoeLi] -- Implemented Ordinary Exchange
  10. Notes:
  11. The Ordinary exchange bridges the mismatch between the connection engine exchange
  12. which is oriented towards sending a single SMB request to the server and processing
  13. the response from the server and the requests recieved from RDBSS.
  14. The requests from RDBSS come in one of two flavours -- synchronous and asynchronous.
  15. There are requests which often translate into multiple SMB's being sent to the
  16. server and the associated response processing. There is no one to one mapping
  17. between the requests and the SMBs that need to be sent. In some cases a reconnection
  18. attempt needs to be made and in others a delayed open needs to be sent before the
  19. associated request can be processed. There are instances of requests which are
  20. inherently multi SMB, e.g., large read and write requests.
  21. The ordinary exchange provides the framework for dealing with all these variations.
  22. The ORDINARY_EXCHANGE wraps a connection engine exchange and extends it with
  23. different hooks for customization. The custromization of ORDINARY_EXCHANGE is
  24. possible both from the data and control viewpoint. The data portion is provided
  25. by a union at the tail end of the ORDINARY_EXCHANGE which provides for the
  26. appropriate state to be captured.
  27. The code customization consists of three routines that can be specified as
  28. part of the ORDIANRY_EXCHANGE. These are the Asynchronous Resumption routine
  29. (AsyncResumptionRoutine), the continuation routine (ContinuationRoutine) and
  30. the start routine (StartRoutine).
  31. The SmbPseCreateOrdinaryExchange, SmbPseSubmitOrdinaryExchange and
  32. SmbPseFinalizeOrdinaryExchange provide the necessay mechanism for creating an
  33. ordinary exchange, triggering the action and finalizing it upon completion.
  34. The ordinary exchange implementation tailors the dispatch vector associated
  35. with the underlying connection engine exchange using extensive tables. All
  36. the routines suffixed with _default are the default routines for the
  37. underlying connection engine exchange.
  38. The typical course of exchange in response to a request from the RDBSS is to
  39. 1) create an ordinary exchange (SmbPseCreateOrdinaryExchange)
  40. 2) submit it for processing (SmbPseSubmitOrdinaryExchange)
  41. 2.1) The Ordinary exchange completes the initialization w.r.t the state
  42. associated with it and initiates the processing in the connection
  43. engine (SmbCeInitiateExchange)
  44. 2.2) The connection engine completes the initialization associated
  45. with the connection engine and invokes the Start routine provided in
  46. the dispatch vector.
  47. 2.3) This results in the Start routine provided to the Ordinary exchange
  48. being invoked. The request specific initialization is carried out followed
  49. by a call to SmbCeTranceive or SmbCeSend.
  50. 2.4) The resulting exchange is suspended while the underlying connection
  51. engine interfaces with the transport to ship the packet over and receive
  52. the response.
  53. 2.5) Once the connection engine quiesces the SMbPseContinueOrdinaryExchange
  54. is called. This routine either invokes the continuation routine to resume
  55. processing or wrap up the ordianry exchange processing and return to
  56. the caller. this involves either setting the event for synchronous
  57. requests or invoking the AsyncResumption routine for asynchronous requests.
  58. The request for read/write which involve multiple packets use the continuation
  59. routine to spin up further requests. These can be network exchanges which are wired
  60. to the original exchange and are referred to as associated exchanges. On completion
  61. of all associated exchanges the connection engine invokes the
  62. AssociatedExchangeCompletionHandler which results in the resumption of
  63. ORDINARY_EXCHANGE processing in 2.5.
  64. --*/
  65. #include "precomp.h"
  66. #pragma hdrstop
  67. #include <dfsfsctl.h>
  68. #ifdef ALLOC_PRAGMA
  69. #pragma alloc_text(PAGE, __SmbPseDbgCheckOEMdls)
  70. #pragma alloc_text(PAGE, SmbPseContinueOrdinaryExchange)
  71. #pragma alloc_text(PAGE, SmbPseOrdinaryExchange)
  72. #pragma alloc_text(PAGE, __SmbPseCreateOrdinaryExchange)
  73. #pragma alloc_text(PAGE, SmbPseFinalizeOrdinaryExchange)
  74. #pragma alloc_text(PAGE, SmbPseExchangeStart_default)
  75. #pragma alloc_text(PAGE, SmbPseExchangeCopyDataHandler_Read)
  76. #pragma alloc_text(PAGE, __SmbPseRMTableEntry)
  77. #pragma alloc_text(PAGE, SmbPseInitializeTables)
  78. #pragma alloc_text(PAGE, MRxSmbQueryDosVolumeInformation)
  79. #endif
  80. RXDT_DefineCategory(SMBPSE);
  81. #define Dbg (DEBUG_TRACE_SMBPSE)
  82. #define MINIMUM_SEND_SIZE 512
  83. PVOID LastOE;
  84. #define MIN(x,y) ((x) < (y) ? (x) : (y))
  85. #define IM_THE_LAST_GUY (*Response==0)
  86. //
  87. // Generic AndX request
  88. //
  89. GENERIC_ANDX NullGenericAndX = {
  90. // typedef struct _GENERIC_ANDX {
  91. 0, // UCHAR WordCount; // Count of parameter words
  92. // UCHAR AndXCommand; // Secondary (X) command; 0xFF = none
  93. SMB_COM_NO_ANDX_COMMAND,
  94. 0, // UCHAR AndXReserved; // Reserved
  95. 0 // _USHORT( AndXOffset ); // Offset (from SMB header start)
  96. // } GENERIC_ANDX;
  97. };
  98. NTSTATUS
  99. SmbPseExchangeStart_default(
  100. IN OUT PSMB_EXCHANGE pExchange);
  101. NTSTATUS
  102. SmbPseExchangeSendCallbackHandler_default(
  103. IN PSMB_EXCHANGE pExchange,
  104. IN PMDL pXmitBuffer,
  105. IN NTSTATUS SendCompletionStatus);
  106. NTSTATUS
  107. SmbPseExchangeCopyDataHandler_default(
  108. IN PSMB_EXCHANGE pExchange,
  109. IN PMDL pDataBuffer,
  110. IN ULONG DataSize);
  111. NTSTATUS
  112. SmbPseExchangeCopyDataHandler_Read(
  113. IN PSMB_EXCHANGE pExchange,
  114. IN PMDL pDataBuffer,
  115. IN ULONG DataSize);
  116. NTSTATUS
  117. SmbPseExchangeReceive_default(
  118. IN struct _SMB_EXCHANGE *pExchange,
  119. IN ULONG BytesIndicated,
  120. IN ULONG BytesAvailable,
  121. OUT ULONG *pBytesTaken,
  122. IN PSMB_HEADER pSmbHeader,
  123. OUT PMDL *pDataBufferPointer,
  124. OUT PULONG pDataSize,
  125. IN ULONG ReceiveFlags);
  126. NTSTATUS
  127. SmbPseExchangeFinalize_default(
  128. IN OUT struct _SMB_EXCHANGE *pExchange,
  129. OUT BOOLEAN *pPostFinalize);
  130. SMB_EXCHANGE_DISPATCH_VECTOR
  131. SmbPseOEDispatch = {
  132. SmbPseExchangeStart_default,
  133. SmbPseExchangeReceive_default,
  134. SmbPseExchangeCopyDataHandler_default,
  135. SmbPseExchangeSendCallbackHandler_default,
  136. SmbPseExchangeFinalize_default,
  137. NULL
  138. };
  139. #if DBG
  140. #define P__ASSERT(exp) { \
  141. if (!(exp)) { \
  142. DbgPrint("NOT %s\n",#exp); \
  143. errors++; \
  144. }}
  145. VOID
  146. __SmbPseOEAssertConsistentLinkage(
  147. PSZ MsgPrefix,
  148. PSZ File,
  149. unsigned Line,
  150. PRX_CONTEXT RxContext,
  151. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  152. PSMBSTUFFER_BUFFER_STATE StufferState,
  153. ULONG Flags
  154. )
  155. /*++
  156. Routine Description:
  157. This routine performs a variety of checks to ensure that the linkage between the rxcontext, the OE, and
  158. the stufferstate is correct and that various fields have correct values. if anything is bad....print stuff out and brkpoint;
  159. Arguments:
  160. MsgPrefix an identifying msg
  161. RxContext duh
  162. OrdinaryExchange .
  163. StufferState .
  164. Return Value:
  165. none
  166. Notes:
  167. --*/
  168. {
  169. ULONG errors = 0;
  170. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  171. PSMB_EXCHANGE Exchange = &OrdinaryExchange->Exchange;
  172. pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  173. if (Exchange->CancellationStatus != SMBCE_EXCHANGE_CANCELLED) {
  174. P__ASSERT( OrdinaryExchange->SerialNumber == RxContext->SerialNumber );
  175. P__ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT );
  176. }
  177. P__ASSERT( NodeType(OrdinaryExchange)==SMB_EXCHANGE_NTC(ORDINARY_EXCHANGE) );
  178. P__ASSERT( OrdinaryExchange->RxContext == RxContext );
  179. P__ASSERT( NodeType(StufferState) == SMB_NTC_STUFFERSTATE );
  180. P__ASSERT( Exchange == StufferState->Exchange);
  181. P__ASSERT( StufferState->RxContext == RxContext );
  182. if(StufferState->HeaderMdl!=NULL){
  183. P__ASSERT( !RxMdlIsPartial(StufferState->HeaderMdl) );
  184. }
  185. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED)) {
  186. P__ASSERT( RxMdlIsPartial(StufferState->HeaderPartialMdl) );
  187. }
  188. if (errors==0) {
  189. return;
  190. }
  191. DbgPrint("%s INCONSISTENT OE STATE: %d errors at %s line %d\n",
  192. MsgPrefix,errors,File,Line);
  193. //DbgBreakPoint();
  194. return;
  195. }
  196. VOID
  197. __SmbPseDbgRunMdlChain(
  198. PMDL MdlChain,
  199. ULONG CountToCompare,
  200. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  201. PSZ MsgPrefix,
  202. PSZ File,
  203. unsigned Line
  204. )
  205. {
  206. ULONG i,total;
  207. RxDbgTrace(0,Dbg,("__SmbPseRunMdlChain: -------------%08lx\n",MdlChain));
  208. for (total=i=0;MdlChain!=NULL;i++,MdlChain=MdlChain->Next) {
  209. total+=MdlChain->ByteCount;
  210. RxDbgTrace(0,Dbg,("--->%02d %08lx %08lx %08lx %6d %6d\n",i,MdlChain,MdlChain->MdlFlags,
  211. MmGetMdlVirtualAddress(MdlChain),MdlChain->ByteCount,total));
  212. }
  213. if (total == CountToCompare) return;
  214. DbgPrint("%s: MdlChain.Count!=CountToCompart c1,c2,xch.st=%08lx %08lx %08lx\n",
  215. MsgPrefix,
  216. total,CountToCompare,OrdinaryExchange->Status,
  217. File,Line);
  218. //DbgBreakPoint();
  219. }
  220. #define SmbPseDbgRunMdlChain(a,b,c,d) {\
  221. __SmbPseDbgRunMdlChain(a,b,c,d,__FILE__,__LINE__);\
  222. }
  223. VOID
  224. __SmbPseDbgCheckOEMdls(
  225. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  226. PSZ MsgPrefix,
  227. PSZ File,
  228. unsigned Line
  229. )
  230. {
  231. ULONG errors = 0;
  232. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  233. PMDL SubmitMdl = StufferState->HeaderPartialMdl;
  234. PAGED_CODE();
  235. P__ASSERT (OrdinaryExchange->SaveDataMdlForDebug == SubmitMdl->Next);
  236. P__ASSERT (OrdinaryExchange->SaveDataMdlForDebug == StufferState->DataMdl);
  237. P__ASSERT (SubmitMdl != NULL);
  238. if (errors==0) {
  239. return;
  240. }
  241. DbgPrint("%s CheckOEMdls failed: %d errors at %s line %d: OE=%08lx\n",
  242. MsgPrefix,errors,File,Line,OrdinaryExchange);
  243. //DbgBreakPoint();
  244. return;
  245. }
  246. #define SmbPseDbgCheckOEMdls(a,b) {\
  247. __SmbPseDbgCheckOEMdls(a,b,__FILE__,__LINE__);\
  248. }
  249. ULONG SmbPseShortStatus(ULONG Status)
  250. {
  251. ULONG ShortStatus;
  252. ShortStatus = Status & 0xc0003fff;
  253. ShortStatus = ShortStatus | (ShortStatus >>16);
  254. return(ShortStatus);
  255. }
  256. VOID SmbPseUpdateOEHistory(
  257. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  258. ULONG Tag1,
  259. ULONG Tag2
  260. )
  261. {
  262. ULONG MyIndex,Long0,Long1;
  263. MyIndex = InterlockedIncrement(&OrdinaryExchange->History.Next);
  264. MyIndex = (MyIndex-1) & (SMBPSE_OE_HISTORY_SIZE-1);
  265. Long0 = (Tag1<<16) | (Tag2 & 0xffff);
  266. Long1 = (SmbPseShortStatus(OrdinaryExchange->SmbStatus)<<16) | OrdinaryExchange->Flags;
  267. OrdinaryExchange->History.Markers[MyIndex].Longs[0] = Long0;
  268. OrdinaryExchange->History.Markers[MyIndex].Longs[1] = Long1;
  269. }
  270. VOID SmbPseVerifyDataPartialAllocationPerFlags(
  271. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  272. )
  273. {
  274. BOOLEAN FlagsSayPartialAllocated,TheresADataPartial;
  275. ULONG t = OrdinaryExchange->Flags & (SMBPSE_OE_FLAG_OE_ALLOCATED_DATA_PARTIAL|SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_SMBBUF);
  276. FlagsSayPartialAllocated = (t!=0)?TRUE:FALSE; //the compiler is getting confused
  277. TheresADataPartial = (OrdinaryExchange->DataPartialMdl != NULL)?TRUE:FALSE; //the compiler is getting confused
  278. if ( FlagsSayPartialAllocated != TheresADataPartial){
  279. DbgPrint("Flags %08lx datapartial %08lx t %08lx fspa %08lx tadp %08lx\n",
  280. OrdinaryExchange->Flags, OrdinaryExchange->DataPartialMdl,
  281. t, FlagsSayPartialAllocated, TheresADataPartial);
  282. ASSERT ( FlagsSayPartialAllocated == TheresADataPartial);
  283. }
  284. }
  285. #else
  286. #define SmbPseDbgRunMdlChain(a,b,c,d) {NOTHING;}
  287. #define SmbPseDbgCheckOEMdls(a,b) {NOTHING;}
  288. #define SmbPseVerifyDataPartialAllocationPerFlags(a) {NOTHING;}
  289. #endif
  290. #define UPDATE_OE_HISTORY_WITH_STATUS(a) \
  291. UPDATE_OE_HISTORY_2SHORTS(a,SmbPseShortStatus(OrdinaryExchange->Status))
  292. VOID
  293. MRxSmbResumeAsyncReadWriteRequests(
  294. PRX_CONTEXT RxContext)
  295. /*++
  296. Routine Description:
  297. Asynchronous read write requests can be deferred because of SMB FCB resource
  298. acquistion. In all such cases this routine resumes the request. We
  299. cannot directly reume execution with MRxSmbRead/MRxSmbWrite routine because
  300. we need to invoke LowIoCompletion in certain failure cases. We have two choices
  301. to do so .... either we can include this logic in the MRxSmbRead/MRxSmbWrite
  302. routine or consolidate it in pne place. This routine implements the later
  303. approach.
  304. Arguments:
  305. RxContext - the RDBSS context
  306. Notes:
  307. --*/
  308. {
  309. NTSTATUS Status;
  310. PMRX_CALLDOWN ResumptionRoutine;
  311. switch (RxContext->MajorFunction) {
  312. case IRP_MJ_READ:
  313. ResumptionRoutine = MRxSmbRead;
  314. break;
  315. case IRP_MJ_WRITE:
  316. ResumptionRoutine = MRxSmbWrite;
  317. break;
  318. default:
  319. ASSERT(!"Valid IRP Major Function code for CscResumeReadWrite");
  320. return;
  321. }
  322. Status = (ResumptionRoutine)(RxContext);
  323. if (Status != STATUS_PENDING) {
  324. if (Status != STATUS_SUCCESS) {
  325. DbgPrint("RxContext Async CSC Status %lx\n",Status);
  326. RxContext->StoredStatus = Status;
  327. RxContext->InformationToReturn = 0;
  328. }
  329. // Invoke the Low Io Resumption routine
  330. RxLowIoCompletion(RxContext);
  331. }
  332. }
  333. NTSTATUS
  334. SmbPseHoldOrdinaryExchange(
  335. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  336. )
  337. /*++
  338. Routine Description:
  339. This routine holds an exchange until the session recovery completes. Session
  340. recovery is initiated when a kerberos ticket expires on the server and we get
  341. a STATUS_NETWORK_SESSION_EXPIRED error from the server. The session needs to
  342. be rebuilt before operations can resume. Note that this is a special case
  343. because the server maintains state across a session setup. Session recovery is
  344. indicated by the pSessionEntry->SessionRecoverInProgress flag.
  345. Once session recovery is complete, we call SmbPseContinueOrdinaryExchange().
  346. Note that if we are unable to hold the exchange, we directly call
  347. SmbPseContinueOrdinaryExchange().
  348. Arguments:
  349. OrdinaryExchange - the context of the operation. .
  350. Return Value:
  351. STATUS_PENDING if the exchange was 'held' successfully.
  352. Notes:
  353. IRQL < DISPATCH_DEVEL
  354. --*/
  355. {
  356. NTSTATUS Status;
  357. ASSERT( OrdinaryExchange->AsyncResumptionRoutine != NULL );
  358. Status = SmbCeHoldExchangeForSessionRecovery(
  359. (PSMB_EXCHANGE)OrdinaryExchange,
  360. (PSMBCE_RELEASE_ROUTINE) OrdinaryExchange->AsyncResumptionRoutine );
  361. //
  362. // If we didnt hold, then call the continuation routine directly.
  363. //
  364. if( Status != STATUS_PENDING ) {
  365. Status = OrdinaryExchange->AsyncResumptionRoutine(
  366. OrdinaryExchange,
  367. OrdinaryExchange->RxContext );
  368. }
  369. return Status;
  370. }
  371. NTSTATUS
  372. SmbPseContinueOrdinaryExchange(
  373. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  374. )
  375. /*++
  376. Routine Description:
  377. This routine resumes processing on an exchange. This is called when work is
  378. required to finish processing a request that cannot be completed at DPC
  379. level. This happens either because the parse routine needs access to
  380. structures that are not locks OR because the operation if asynchronous and
  381. there maybe more work to be done.
  382. The two cases are regularized by delaying the parse if we know that we're
  383. going to post: this is indicated by the presense of a resume routine.
  384. Arguments:
  385. RxContext - the context of the operation. .
  386. Return Value:
  387. NTSTATUS - The return status for the operation
  388. Notes:
  389. --*/
  390. {
  391. NTSTATUS Status;
  392. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  393. RxCaptureFobx;
  394. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  395. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  396. PMDL SubmitMdl, HeaderFullMdl;
  397. BOOLEAN InvokeContinuationRoutine = FALSE;
  398. PAGED_CODE();
  399. RxDbgTrace(+1, Dbg, ("SmbPseContinueOrdinaryExchange entering........OE=%08lx\n",OrdinaryExchange));
  400. Status = Exchange->Status;
  401. if (OrdinaryExchange->OpSpecificState !=
  402. SmbPseOEInnerIoStates_OperationCompleted) {
  403. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_AWAITING_DISPATCH);
  404. SmbPseOEAssertConsistentLinkageFromOE("SmbPseContinueOrdinaryExchange:");
  405. UPDATE_OE_HISTORY_WITH_STATUS('0c');
  406. SubmitMdl = StufferState->HeaderPartialMdl;
  407. HeaderFullMdl = StufferState->HeaderMdl;
  408. ASSERT(FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED));
  409. SmbPseOEAssertConsistentLinkage("Top of OE continue: ");
  410. RxUnprotectMdlFromFree(SubmitMdl);
  411. RxUnprotectMdlFromFree(HeaderFullMdl);
  412. SmbPseDbgCheckOEMdls(
  413. OrdinaryExchange,"SmbPseContinueOrdinaryExchange(top)");
  414. SmbPseDbgRunMdlChain(
  415. SubmitMdl,
  416. OrdinaryExchange->SaveLengthForDebug,
  417. OrdinaryExchange,
  418. "SmbPseContinueOrdinaryExchange(top)");
  419. MmPrepareMdlForReuse(SubmitMdl);
  420. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED);
  421. SmbPseVerifyDataPartialAllocationPerFlags(OrdinaryExchange);
  422. if ( OrdinaryExchange->DataPartialMdl ) {
  423. MmPrepareMdlForReuse( OrdinaryExchange->DataPartialMdl );
  424. }
  425. RxDbgTrace( 0, Dbg, (" --> P4Reuse %08lx, full %08lx is no longer unlocked here\n"
  426. ,SubmitMdl,HeaderFullMdl));
  427. }
  428. if (OrdinaryExchange->ContinuationRoutine == NULL) {
  429. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  430. ULONG BytesTaken;
  431. ULONG DataSize = 0;
  432. ULONG MessageLength = OrdinaryExchange->MessageLength;
  433. PMDL DataBufferPointer = NULL;
  434. PSMB_HEADER SmbHeader = (PSMB_HEADER)StufferState->BufferBase;
  435. Status = SMB_EXCHANGE_DISPATCH(
  436. Exchange,
  437. Receive,
  438. (
  439. Exchange, // IN struct SMB_EXCHANGE *pExchange,
  440. MessageLength, // IN ULONG BytesIndicated,
  441. MessageLength, // IN ULONG BytesAvailable,
  442. &BytesTaken, // OUT ULONG *pBytesTaken,
  443. SmbHeader, // IN PSMB_HEADER pSmbHeader,
  444. &DataBufferPointer, // OUT PMDL *pDataBufferPointer,
  445. &DataSize, // OUT PULONG pDataSize)
  446. TDI_RECEIVE_ENTIRE_MESSAGE
  447. ));
  448. if (Status == STATUS_SUCCESS) {
  449. Status = Exchange->Status;
  450. UPDATE_OE_HISTORY_WITH_STATUS('2c');
  451. } else {
  452. UPDATE_OE_HISTORY_WITH_STATUS('dd');
  453. }
  454. if (DataSize != 0 ||
  455. DataBufferPointer != NULL ||
  456. BytesTaken != MessageLength ||
  457. Status == STATUS_MORE_PROCESSING_REQUIRED) {
  458. Status = STATUS_INVALID_NETWORK_RESPONSE;
  459. }
  460. InvokeContinuationRoutine = TRUE;
  461. }
  462. } else {
  463. InvokeContinuationRoutine = TRUE;
  464. }
  465. if (InvokeContinuationRoutine) {
  466. if ( OrdinaryExchange->ContinuationRoutine != NULL ) {
  467. if ( Status == STATUS_MORE_PROCESSING_REQUIRED){
  468. Exchange->Status = STATUS_SUCCESS;
  469. }
  470. Status = OrdinaryExchange->ContinuationRoutine( OrdinaryExchange );
  471. UPDATE_OE_HISTORY_WITH_STATUS('1c');
  472. if (Status != STATUS_PENDING) {
  473. Exchange->Status = Status;
  474. OrdinaryExchange->ContinuationRoutine = NULL;
  475. }
  476. }
  477. }
  478. if (Status != STATUS_PENDING) {
  479. if (Status != STATUS_SUCCESS) {
  480. if (RxContext->MajorFunction != IRP_MJ_CLOSE) {
  481. // There is no point in transitioning CLOSE operations since
  482. // the context is lost anycase.
  483. Status = CscTransitionVNetRootForDisconnectedOperation(
  484. RxContext,
  485. SmbCeGetExchangeVNetRoot(
  486. (PSMB_EXCHANGE)OrdinaryExchange),
  487. Status);
  488. }
  489. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus = Status;
  490. }
  491. if (OrdinaryExchange->AsyncResumptionRoutine ) {
  492. //
  493. // To prevent critical work queue threads from getting stuck trying to re-initiate exchanges
  494. // which returned with STATUS_RETRY, we 'hold' these on a session recovery list. When session
  495. // setup completes, these will be retried.
  496. //
  497. if( OrdinaryExchange->Status == STATUS_RETRY ) {
  498. Status = SmbPseHoldOrdinaryExchange(OrdinaryExchange);
  499. } else {
  500. //call the continuation is it's async
  501. Status = OrdinaryExchange->AsyncResumptionRoutine(
  502. OrdinaryExchange,
  503. RxContext );
  504. }
  505. UPDATE_OE_HISTORY_WITH_STATUS('3c');
  506. }
  507. //remove my references, if i'm the last guy then do the putaway...
  508. UPDATE_OE_HISTORY_WITH_STATUS('4c');
  509. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  510. }
  511. RxDbgTrace(-1, Dbg, ("SmbPseContinueOrdinaryExchange returning %08lx.\n", Status));
  512. return(Status);
  513. } // SmbPseContinueOrdinaryExchange
  514. NTSTATUS
  515. SmbPseOrdinaryExchange(
  516. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  517. IN SMB_PSE_ORDINARY_EXCHANGE_TYPE OEType
  518. )
  519. /*++
  520. Routine Description:
  521. This routine implements an ordinary exchange as viewed by the protocol
  522. selection routines.
  523. Arguments:
  524. OrdinaryExchange - the exchange to be conducted.
  525. OEType - Ordinary Exchange Type
  526. Return Value:
  527. NTSTATUS - The return status for the operation
  528. Notes:
  529. --*/
  530. {
  531. NTSTATUS Status;
  532. RxCaptureFobx;
  533. RxCaptureFcb;
  534. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  535. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  536. PSMBSTUFFER_BUFFER_STATE StufferState;
  537. PSMB_PSE_OE_START_ROUTINE Continuation;
  538. ULONG SmbLength;
  539. PMDL SubmitMdl,HeaderFullMdl;
  540. ULONG SendOptions;
  541. DEBUG_ONLY_DECL( ULONG LengthP; ULONG LengthF; )
  542. KEVENT SyncEvent;
  543. PAGED_CODE();
  544. RxDbgTrace(+1, Dbg, ("SmbPseOrdinaryExchange entering.......OE=%08lx\n",OrdinaryExchange));
  545. SmbPseOEAssertConsistentLinkageFromOE("SmbPseOrdinaryExchange:");
  546. OrdinaryExchange->OEType = OEType;
  547. StufferState = &OrdinaryExchange->AssociatedStufferState;
  548. KeInitializeEvent(
  549. &SyncEvent,
  550. NotificationEvent,
  551. FALSE );
  552. HeaderFullMdl = StufferState->HeaderMdl;
  553. ASSERT( HeaderFullMdl != NULL );
  554. SmbLength = (ULONG)(StufferState->CurrentPosition - StufferState->BufferBase);
  555. SubmitMdl = StufferState->HeaderPartialMdl;
  556. ASSERT(RxMdlIsOwned(SubmitMdl));
  557. RxBuildPartialHeaderMdl(
  558. StufferState->HeaderMdl,
  559. SubmitMdl,
  560. StufferState->BufferBase,
  561. SmbLength );
  562. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED);
  563. //
  564. // If there is a data MDL associated with this request, then
  565. // we'll have to chain it.
  566. //
  567. SubmitMdl->Next = StufferState->DataMdl;
  568. if (StufferState->DataMdl) {
  569. SmbLength += StufferState->DataSize;
  570. }
  571. DbgDoit(
  572. SmbPseDbgRunMdlChain(
  573. SubmitMdl,
  574. SmbLength,
  575. OrdinaryExchange,
  576. "SmbPseOrdinaryExchange(before)");
  577. OrdinaryExchange->SaveDataMdlForDebug = SubmitMdl->Next;
  578. OrdinaryExchange->SaveLengthForDebug = SmbLength;
  579. if (OrdinaryExchange->RxContextCapturedRequestPacket != NULL) {
  580. OrdinaryExchange->SaveIrpMdlForDebug =
  581. OrdinaryExchange->RxContextCapturedRequestPacket->MdlAddress;
  582. }
  583. )
  584. RxDbgTrace(
  585. 0,
  586. Dbg,
  587. (" --> mdllength/smblength %08lx/%08lx headermdl %08lx\n",
  588. MmGetMdlByteCount(SubmitMdl), SmbLength, StufferState->HeaderMdl) );
  589. ClearFlag(
  590. OrdinaryExchange->Flags,
  591. (SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED |
  592. SMBPSE_OE_FLAG_OE_ALREADY_RESUMED) );
  593. SendOptions = OrdinaryExchange->SendOptions;
  594. SmbCeReferenceExchange( Exchange ); //this one is taken away in ContinueOE
  595. SmbCeReferenceExchange( Exchange ); //this one is taken away below...
  596. //i must NOT finalize before SmbCe returns
  597. SmbCeResetExchange(Exchange);
  598. Continuation = OrdinaryExchange->AsyncResumptionRoutine;
  599. if (((OrdinaryExchange->OEType == SMBPSE_OETYPE_WRITE) ||
  600. (OrdinaryExchange->OEType == SMBPSE_OETYPE_READ) ||
  601. (OrdinaryExchange->OEType == SMBPSE_OETYPE_LOCKS)) &&
  602. BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)
  603. ) {
  604. ASSERT(Continuation!=NULL);
  605. }
  606. if (Continuation == NULL) {
  607. OrdinaryExchange->pSmbCeSynchronizationEvent = &SyncEvent;
  608. }
  609. DbgDoit((LengthP = MmGetMdlByteCount(SubmitMdl),LengthF = MmGetMdlByteCount(HeaderFullMdl)));
  610. RxProtectMdlFromFree(SubmitMdl);
  611. RxProtectMdlFromFree(HeaderFullMdl);
  612. SmbPseOEAssertConsistentLinkage("just before transceive: ");
  613. UPDATE_OE_HISTORY_2SHORTS('eo',(Continuation!=NULL)?'!!':0);
  614. DbgDoit( InterlockedIncrement(&OrdinaryExchange->History.Submits); )
  615. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID)) {
  616. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  617. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  618. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(OrdinaryExchange);
  619. if (smbSrvOpen->Version == pServerEntry->Server.Version) {
  620. Status = STATUS_SUCCESS;
  621. } else {
  622. Exchange->Status = Exchange->SmbStatus = Status = STATUS_CONNECTION_DISCONNECTED;
  623. capFcb->fShouldBeOrphaned = TRUE;
  624. }
  625. IF_DEBUG {
  626. PSMB_HEADER pSmbHeader = (PSMB_HEADER)MmGetSystemAddressForMdlSafe(SubmitMdl,LowPagePriority);
  627. USHORT Flags2 = 0;
  628. if (pSmbHeader) {
  629. Flags2 = SmbGetUshort(&pSmbHeader->Flags2);
  630. }
  631. RxDbgTrace(0, Dbg, ("Flags2 Value for Exchange %lx is %lx\n",Exchange,Flags2));
  632. }
  633. } else {
  634. Status = STATUS_SUCCESS;
  635. }
  636. if (Status == STATUS_SUCCESS) {
  637. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_NO_RESPONSE_EXPECTED)) {
  638. Status = SmbCeSend(
  639. Exchange,
  640. SendOptions,
  641. SubmitMdl,
  642. SmbLength);
  643. } else {
  644. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(OrdinaryExchange);
  645. Status = SmbCeTranceive(
  646. Exchange,
  647. SendOptions,
  648. SubmitMdl,
  649. SmbLength);
  650. }
  651. }
  652. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange); //okay to finalize now that we're back
  653. if ( Status == STATUS_PENDING) {
  654. if ( Continuation != NULL ) {
  655. goto FINALLY;
  656. }
  657. UPDATE_OE_HISTORY_WITH_STATUS('1o');
  658. KeWaitForSingleObject(&SyncEvent,Executive, KernelMode, FALSE, NULL );
  659. OrdinaryExchange->pSmbCeSynchronizationEvent = NULL;
  660. ASSERT(RxMdlIsOwned(SubmitMdl));
  661. DbgDoit (
  662. //variables in the assert are only declared for DBG
  663. //asserts can be enabled separately
  664. ASSERT(
  665. LengthP == MmGetMdlByteCount(SubmitMdl) &&
  666. LengthF == MmGetMdlByteCount(HeaderFullMdl) );
  667. )
  668. } else {
  669. RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx\n",Status));
  670. DbgDoit (
  671. //variables in the assert are only declared for DBG
  672. //asserts can be enabled separately
  673. ASSERT(
  674. LengthP == MmGetMdlByteCount(SubmitMdl) &&
  675. LengthF == MmGetMdlByteCount(HeaderFullMdl) );
  676. )
  677. RxUnprotectMdlFromFree(SubmitMdl);
  678. RxUnprotectMdlFromFree(HeaderFullMdl);
  679. SmbPseOEAssertConsistentLinkage("nonpending return from transceive: ");
  680. // if it's an error, remove the references that i placed and get out
  681. if (NT_ERROR(Status)) {
  682. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  683. goto FINALLY;
  684. }
  685. }
  686. //at last, call the continuation........
  687. SmbPseOEAssertConsistentLinkage("just before continueOE: ");
  688. UPDATE_OE_HISTORY_WITH_STATUS('9b');
  689. Status = SmbPseContinueOrdinaryExchange( OrdinaryExchange );
  690. UPDATE_OE_HISTORY_WITH_STATUS('9o');
  691. FINALLY:
  692. RxDbgTrace(-1, Dbg, ("SmbPseOrdinaryExchange returning %08lx.\n", Status));
  693. return(Status);
  694. } // SmbPseOrdinaryExchange
  695. NTSTATUS
  696. __SmbPseCreateOrdinaryExchange (
  697. IN PRX_CONTEXT RxContext,
  698. IN PMRX_V_NET_ROOT VNetRoot,
  699. IN SMB_PSE_ORDINARY_EXCHANGE_ENTRYPOINTS EntryPoint,
  700. IN PSMB_PSE_OE_START_ROUTINE StartRoutine,
  701. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState OPTIONAL,
  702. OUT PSMB_PSE_ORDINARY_EXCHANGE *OrdinaryExchangePtr
  703. )
  704. /*++
  705. Routine Description:
  706. This routine allocates and initializes an SMB header buffer. Currently,
  707. we just allocate them from pool except when must_succeed is specified.
  708. Arguments:
  709. RxContext - the RDBSS context
  710. VNetRoot -
  711. DispatchVector -
  712. Return Value:
  713. A buffer ready to go, OR NULL.
  714. Notes:
  715. --*/
  716. {
  717. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  718. PSMBSTUFFER_BUFFER_STATE StufferState = NULL;
  719. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  720. PCHAR SmbBuffer = NULL;
  721. PMDL HeaderFullMdl = NULL;
  722. NTSTATUS Status = STATUS_SUCCESS;
  723. RxCaptureFobx;
  724. SMBFCB_HOLDING_STATE TempHoldingState = SmbFcb_NotHeld;
  725. PAGED_CODE();
  726. /*
  727. Other size improvement stuff: //CODE.IMPROVEMENT
  728. finalize renamed to transitiontoquiescent
  729. big fix - remove unwanted capture macros
  730. longname - delete top part of routine by using the studcode
  731. smbutils - we could reduce the table size by a factor of 2-3 by storing s 16bit representation of the ntstatus
  732. */
  733. RxDbgTrace(+1, Dbg, ("SmbPseCreateOrdinaryExchange\n") );
  734. if (SmbFcbHoldingState == NULL) {
  735. SmbFcbHoldingState = &TempHoldingState;
  736. }
  737. IF_NOT_MRXSMB_CSC_ENABLED{
  738. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  739. }
  740. OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)SmbMmAllocateExchange(ORDINARY_EXCHANGE,NULL);
  741. //we rely on the fact that SmbMmAllocate Zeros the exchange.............
  742. if (OrdinaryExchange == NULL) {
  743. Status = STATUS_INSUFFICIENT_RESOURCES;
  744. goto UNWIND;
  745. }
  746. StufferState = &OrdinaryExchange->AssociatedStufferState;
  747. StufferState->NodeTypeCode = SMB_NTC_STUFFERSTATE;
  748. StufferState->NodeByteSize = sizeof(SMBSTUFFER_BUFFER_STATE);
  749. StufferState->Exchange = &OrdinaryExchange->Exchange;
  750. DbgDoit(OrdinaryExchange->SerialNumber = RxContext->SerialNumber); //CODE.IMPROVEMENT should this be in the SMB_EXCHANGE?
  751. //
  752. // Initialize the exchange packet
  753. //
  754. Status = SmbCeInitializeExchange(
  755. &StufferState->Exchange,
  756. RxContext,
  757. (PMRX_V_NET_ROOT)VNetRoot,
  758. ORDINARY_EXCHANGE,
  759. &SmbPseOEDispatch);
  760. if (StufferState->Exchange != NULL) {
  761. SmbCeReferenceExchange(StufferState->Exchange);
  762. RxDbgTrace(0, Dbg, (" exchng=%08lx,type=%08lx\n",&StufferState->Exchange,StufferState->Exchange->Type));
  763. }
  764. StufferState->RxContext = RxContext;
  765. //place a reference on the rxcontext until we are finished
  766. InterlockedIncrement( &RxContext->ReferenceCount );
  767. OrdinaryExchange->StufferStateDbgPtr = StufferState;
  768. OrdinaryExchange->RxContext = RxContext;
  769. OrdinaryExchange->EntryPoint = EntryPoint;
  770. OrdinaryExchange->StartRoutine = StartRoutine;
  771. OrdinaryExchange->SmbBufSize = MAXIMUM_SMB_BUFFER_SIZE;
  772. DbgDoit(OrdinaryExchange->RxContextCapturedRequestPacket = RxContext->CurrentIrp;);
  773. //note: create path must turn this flag on.
  774. OrdinaryExchange->SmbCeFlags &= ~(SMBCE_EXCHANGE_ATTEMPT_RECONNECTS);
  775. ASSERT( (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_OE))
  776. || (OrdinaryExchange->Flags == 0) );
  777. ASSERT( OrdinaryExchange->SendOptions == 0 );
  778. ASSERT( OrdinaryExchange->DataPartialMdl == NULL );
  779. pMRxSmbContext->pExchange = &OrdinaryExchange->Exchange;
  780. pMRxSmbContext->pStufferState = StufferState;
  781. if (capFobx != NULL) {
  782. if (BooleanFlagOn(capFobx->Flags,FOBX_FLAG_DFS_OPEN)) {
  783. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG);
  784. }
  785. } else if (BooleanFlagOn(VNetRoot->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT) &&
  786. (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))) {
  787. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG);
  788. }
  789. if (Status != STATUS_SUCCESS) {
  790. goto UNWIND;
  791. }
  792. //
  793. // Allocate the SmbBuffer
  794. //
  795. if (SmbBuffer == NULL) {
  796. SmbBuffer = (PCHAR)RxAllocatePoolWithTag(
  797. PagedPool,
  798. OrdinaryExchange->SmbBufSize +
  799. TRANSPORT_HEADER_SIZE,
  800. 'BMSx' );
  801. }
  802. if ( SmbBuffer == NULL ) {
  803. Status = STATUS_INSUFFICIENT_RESOURCES;
  804. goto UNWIND;
  805. }
  806. RxDbgTrace(0, Dbg, (" smbbuf=%08lx,stfstate=%08lx\n",SmbBuffer,StufferState));
  807. StufferState->ActualBufferBase = SmbBuffer;
  808. (PBYTE) SmbBuffer += TRANSPORT_HEADER_SIZE;
  809. StufferState->BufferBase = SmbBuffer;
  810. StufferState->BufferLimit = SmbBuffer + OrdinaryExchange->SmbBufSize;
  811. //
  812. // Init the HeaderMdl
  813. //
  814. HeaderFullMdl = StufferState->HeaderMdl = &OrdinaryExchange->HeaderMdl.Mdl;
  815. RxInitializeHeaderMdl(HeaderFullMdl,SmbBuffer, OrdinaryExchange->SmbBufSize);
  816. RxDbgTrace(
  817. 0,
  818. Dbg,
  819. (" --> smbbufsize %08lx, mdllength %08lx\n",
  820. OrdinaryExchange->SmbBufSize,
  821. MmGetMdlByteCount(HeaderFullMdl)));
  822. //finally, lock down the smbbuf taking different paths according to whether
  823. // we are must-succeed or not
  824. ASSERT( !RxMdlIsLocked(HeaderFullMdl) );
  825. ASSERT( HeaderFullMdl->Next == NULL );
  826. RxDbgTrace( 0, Dbg, (" --> LOCKING %08lx\n",HeaderFullMdl));
  827. RxProbeAndLockHeaderPages(
  828. HeaderFullMdl,
  829. KernelMode,
  830. IoModifyAccess,
  831. Status );
  832. if (Status != STATUS_SUCCESS) {
  833. RxDbgTrace( 0, Dbg, (" --> LOCKING FAILED\n"));
  834. goto UNWIND;
  835. }
  836. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED);
  837. if (MmGetSystemAddressForMdlSafe(HeaderFullMdl,LowPagePriority) == NULL) {
  838. Status = STATUS_INSUFFICIENT_RESOURCES;
  839. goto UNWIND;
  840. }
  841. //
  842. // No initialization is required for the partial...just set the pointer
  843. StufferState->HeaderPartialMdl = &OrdinaryExchange->HeaderPartialMdl.Mdl;
  844. RxDbgTrace( -1, Dbg, (" --> exiting w!\n") );
  845. *OrdinaryExchangePtr = OrdinaryExchange;
  846. return Status;
  847. UNWIND:
  848. RxDbgTrace( -1, Dbg, (" --> exiting w/o!\n") );
  849. if (OrdinaryExchange != NULL ) {
  850. SmbPseFinalizeOrdinaryExchange( OrdinaryExchange );
  851. }
  852. *OrdinaryExchangePtr = NULL;
  853. return Status;
  854. } // SmbPseCreateOrdinaryExchange
  855. #if DBG
  856. ULONG MRxSmbFinalizeStfStateTraceLevel = 1200;
  857. #define FINALIZESS_LEVEL MRxSmbFinalizeStfStateTraceLevel
  858. #define FINALIZE_TRACKING_SETUP() \
  859. struct { \
  860. ULONG marker1; \
  861. ULONG finalstate; \
  862. ULONG marker2; \
  863. } Tracking = {'ereh',0,'ereh'};
  864. #define FINALIZE_TRACKING(x) {\
  865. Tracking.finalstate |= x; \
  866. }
  867. #define FINALIZE_TRACE(x) SmbPseFinalizeOETrace(x,Tracking.finalstate)
  868. VOID
  869. SmbPseFinalizeOETrace(PSZ text,ULONG finalstate)
  870. {
  871. PAGED_CODE();
  872. RxDbgTraceLV(0, Dbg, FINALIZESS_LEVEL,
  873. ("MRxSmbFinalizeSmbStufferState --> %s(%08lx)\n",text,finalstate));
  874. }
  875. #else
  876. #define FINALIZE_TRACKING_SETUP()
  877. #define FINALIZE_TRACKING(x)
  878. #define FINALIZE_TRACE(x)
  879. #endif
  880. BOOLEAN
  881. SmbPseFinalizeOrdinaryExchange (
  882. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  883. )
  884. /*++
  885. Routine Description:
  886. This finalizes an OE.
  887. Arguments:
  888. OrdinaryExchange - pointer to the OE to be dismantled.
  889. Return Value:
  890. TRUE if finalization occurs otherwise FALSE.
  891. Notes:
  892. --*/
  893. {
  894. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  895. PSMBSTUFFER_BUFFER_STATE StufferState;
  896. LONG result;
  897. ULONG OrdinaryExchangeFlags = OrdinaryExchange->Flags;
  898. FINALIZE_TRACKING_SETUP()
  899. PAGED_CODE();
  900. SmbPseOEAssertConsistentLinkageFromOEwithFlags(
  901. "SmbPseFinalizeOrdinaryExchange:",
  902. OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK);
  903. StufferState = &OrdinaryExchange->AssociatedStufferState;
  904. pMRxSmbContext = MRxSmbGetMinirdrContext(StufferState->RxContext);
  905. RxDbgTraceLV(+1, Dbg, 1000, ("MRxSmbFinalizeSmbStufferState\n"));
  906. result = SmbCeDereferenceExchange(&OrdinaryExchange->Exchange);
  907. if ( result != 0 ) {
  908. RxDbgTraceLV(
  909. -1,
  910. Dbg,
  911. 1000,
  912. ("MRxSmbFinalizeSmbStufferState -- returning w/o finalizing (%d)\n",
  913. result));
  914. return FALSE;
  915. }
  916. #if 0
  917. RxLog((">>>OE %lx %lx %lx %lx %lx",
  918. OrdinaryExchange,
  919. OrdinaryExchange->DataPartialMdl,
  920. StufferState->HeaderPartialMdl,
  921. StufferState->HeaderMdl,
  922. OrdinaryExchange->Flags
  923. ));
  924. #endif
  925. FINALIZE_TRACKING( 0x10000000 );
  926. FINALIZE_TRACE("ready to freedatapartial");
  927. if (OrdinaryExchange->CopyDataPendingOperations != 0 ||
  928. OrdinaryExchange->SendCompletePendingOperations != 0) {
  929. DbgBreakPoint();
  930. }
  931. SmbPseVerifyDataPartialAllocationPerFlags(OrdinaryExchange);
  932. if ( OrdinaryExchange->DataPartialMdl ) {
  933. if (!FlagOn(OrdinaryExchangeFlags, SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_SMBBUF)) {
  934. IoFreeMdl( OrdinaryExchange->DataPartialMdl );
  935. FINALIZE_TRACKING( 0x8000000 );
  936. }
  937. }
  938. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED)) {
  939. RxUnlockHeaderPages(StufferState->HeaderMdl);
  940. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED);
  941. MmPrepareMdlForReuse( StufferState->HeaderMdl );
  942. FINALIZE_TRACKING( 0x4000000 );
  943. }
  944. FINALIZE_TRACE("ready to uninit hdr partial");
  945. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED)) {
  946. MmPrepareMdlForReuse( StufferState->HeaderPartialMdl ); //no harm in calling this multiple times
  947. FINALIZE_TRACKING( 0x300000 );
  948. } else {
  949. FINALIZE_TRACKING( 0xf00000 );
  950. }
  951. if (!FlagOn(OrdinaryExchangeFlags, SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_SMBBUF)) {
  952. FINALIZE_TRACE("ready to freepool actualbuffer");
  953. if ( StufferState->ActualBufferBase != NULL ) {
  954. RxFreePool( StufferState->ActualBufferBase );
  955. FINALIZE_TRACKING( 0x5000 );
  956. } else {
  957. FINALIZE_TRACKING( 0xf000 );
  958. }
  959. }
  960. if ( StufferState->RxContext != NULL ) {
  961. //get rid of the reference on the RxContext....if i'm the last guy this will finalize
  962. RxDereferenceAndDeleteRxContext( StufferState->RxContext );//CODE.IMPROVEMENT Capture rxcontext earlier
  963. FINALIZE_TRACKING( 0x600 );
  964. } else {
  965. FINALIZE_TRACKING( 0xf00 );
  966. }
  967. FINALIZE_TRACE("ready to discard exchange");
  968. SmbCeDiscardExchange(OrdinaryExchange);
  969. FINALIZE_TRACKING( 0x2000000 );
  970. FINALIZE_TRACKING( 0x8 );
  971. RxDbgTraceLV(-1, Dbg, 1000, ("MRxSmbFinalizeSmbStufferState --> exit finalstate=%x\n",Tracking.finalstate));
  972. return(TRUE);
  973. } // MRxSmbFinalizeSmbStufferState
  974. NTSTATUS
  975. SmbPseExchangeFinalize_default(
  976. IN OUT PSMB_EXCHANGE pExchange,
  977. OUT BOOLEAN *pPostFinalize
  978. )
  979. /*++
  980. Routine Description:
  981. Arguments:
  982. pExchange - the exchange instance
  983. Return Value:
  984. RXSTATUS - The return status for the operation
  985. --*/
  986. {
  987. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  988. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  989. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  990. UPDATE_OE_HISTORY_WITH_STATUS('ff');
  991. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeFinalize_default: ");
  992. if (OrdinaryExchange->SmbStatus != STATUS_SUCCESS) {
  993. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus;
  994. }
  995. if (OrdinaryExchange->AsyncResumptionRoutine != NULL) {
  996. NTSTATUS PostStatus;
  997. RxDbgTraceLV(0, Dbg, 1000, ("Resume with post-to-async\n"));
  998. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_AWAITING_DISPATCH);
  999. IF_DEBUG {
  1000. //fill the workqueue structure with deadbeef....all the better to diagnose
  1001. //a failed post
  1002. ULONG i;
  1003. for (i=0;i+sizeof(ULONG)-1<sizeof(OrdinaryExchange->WorkQueueItem);i+=sizeof(ULONG)) {
  1004. //*((PULONG)(((PBYTE)&OrdinaryExchange->WorkQueueItem)+i)) = 0xdeadbeef;
  1005. PBYTE BytePtr = ((PBYTE)&OrdinaryExchange->WorkQueueItem)+i;
  1006. PULONG UlongPtr = (PULONG)BytePtr;
  1007. *UlongPtr = 0xdeadbeef;
  1008. }
  1009. }
  1010. PostStatus = RxPostToWorkerThread(
  1011. MRxSmbDeviceObject,
  1012. CriticalWorkQueue,
  1013. &OrdinaryExchange->WorkQueueItem,
  1014. SmbPseContinueOrdinaryExchange,
  1015. OrdinaryExchange);
  1016. ASSERT(PostStatus == STATUS_SUCCESS);
  1017. } else {
  1018. RxDbgTraceLV(0, Dbg, 1000, ("sync resume\n"));
  1019. KeSetEvent(OrdinaryExchange->pSmbCeSynchronizationEvent, 0, FALSE);
  1020. }
  1021. *pPostFinalize = FALSE;
  1022. return STATUS_SUCCESS;
  1023. }
  1024. NTSTATUS
  1025. SmbPseExchangeSendCallbackHandler_default(
  1026. IN PSMB_EXCHANGE pExchange,
  1027. IN PMDL pXmitBuffer,
  1028. IN NTSTATUS SendCompletionStatus
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This is the send call back indication handling routine for ordinary
  1033. exchanges.
  1034. Arguments:
  1035. pExchange - the exchange instance
  1036. pXmitBuffer - pointer to the transmit buffer MDL
  1037. BytesSent - number of bytes transmitted
  1038. SendCompletionStatus - status for the send
  1039. Return Value:
  1040. RXSTATUS - The return status for the operation
  1041. --*/
  1042. {
  1043. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1044. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1045. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeSendCallbackHandler_default: ");
  1046. UPDATE_OE_HISTORY_WITH_STATUS('cs');
  1047. OrdinaryExchange->SendCompletionStatus = SendCompletionStatus;
  1048. if (!NT_SUCCESS(SendCompletionStatus)) {
  1049. //sometimes we use exchange-status, sometimes exchange->smbstatus
  1050. //set them both
  1051. pExchange->Status = SendCompletionStatus;
  1052. pExchange->SmbStatus = SendCompletionStatus;
  1053. }
  1054. SmbPseDbgRunMdlChain(
  1055. OrdinaryExchange->AssociatedStufferState.HeaderPartialMdl,
  1056. OrdinaryExchange->SaveLengthForDebug,
  1057. OrdinaryExchange,
  1058. "SmbPseExchangeSendCallbackHandler_default");
  1059. return STATUS_SUCCESS;
  1060. } // SmbPseExchangeSendCallbackHandler_default
  1061. NTSTATUS
  1062. SmbPseExchangeStart_default(
  1063. IN PSMB_EXCHANGE pExchange
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This is the start routine for ordinary exchanges. irght now this is just a simple wrapper.
  1068. Arguments:
  1069. pExchange - the exchange instance NOT an Ordinary Exchange
  1070. Return Value:
  1071. RXSTATUS - The return status for the operation
  1072. --*/
  1073. {
  1074. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1075. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1076. PAGED_CODE();
  1077. return OrdinaryExchange->StartRoutine(
  1078. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange,
  1079. pExchange->RxContext);
  1080. } // SmbPseExchangeStart_default
  1081. NTSTATUS
  1082. SmbPseExchangeCopyDataHandler_default(
  1083. IN PSMB_EXCHANGE pExchange,
  1084. IN PMDL pCopyDataBuffer,
  1085. IN ULONG CopyDataSize
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. This is the copy data handling routine for ordinary exchanges.
  1090. Arguments:
  1091. pExchange - the exchange instance
  1092. Return Value:
  1093. RXSTATUS - The return status for the operation
  1094. --*/
  1095. {
  1096. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1097. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1098. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeCopyDataHandler_default: ");
  1099. UPDATE_OE_HISTORY_WITH_STATUS('dd');
  1100. OrdinaryExchange->MessageLength = CopyDataSize;
  1101. pExchange->Status = STATUS_MORE_PROCESSING_REQUIRED;
  1102. return STATUS_SUCCESS;
  1103. } // SmbPseExchangeCopyDataHandler_default
  1104. NTSTATUS
  1105. SmbPseExchangeReceive_default(
  1106. IN struct _SMB_EXCHANGE *pExchange,
  1107. IN ULONG BytesIndicated,
  1108. IN ULONG BytesAvailable,
  1109. OUT ULONG *pBytesTaken,
  1110. IN PSMB_HEADER pSmbHeader,
  1111. OUT PMDL *pDataBufferPointer,
  1112. OUT PULONG pDataSize,
  1113. IN ULONG ReceiveFlags)
  1114. /*++
  1115. Routine Description:
  1116. This is the receive indication handling routine for ordinary exchanges
  1117. Arguments:
  1118. pExchange - the exchange instance
  1119. BytesIndicated - the number of bytes indicated
  1120. Bytes Available - the number of bytes available
  1121. pBytesTaken - the number of bytes consumed
  1122. pSmbHeader - pointer to the data buffer
  1123. pDataBufferPointer - pointer to the buffer Mdl into which the remaining
  1124. data is to be copied.
  1125. pDataSize - the buffer size.
  1126. Return Value:
  1127. RXSTATUS - The return status for the operation
  1128. Notes:
  1129. This routine is called at DPC level directly from the tdi receive event
  1130. handler. BUT, it is also called at task time from SmbPseContinueOrdinaryExchange.
  1131. Often, we cannot complete processing from DPClevel because fileobjects, fcbs,
  1132. srvopens, and fobx are pageable and not locked.
  1133. --*/
  1134. {
  1135. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1136. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1137. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1138. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1139. NTSTATUS SmbStatus;
  1140. NTSTATUS Status = STATUS_SUCCESS;
  1141. PGENERIC_ANDX CommandState;
  1142. UCHAR Command;
  1143. ULONG CopyBufferLength;
  1144. BOOLEAN ThisIsAReenter = BooleanFlagOn(OrdinaryExchange->Flags,
  1145. SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED);
  1146. PLOWIO_CONTEXT LowIoContext;
  1147. ULONG ByteCount;
  1148. ULONG Remain;
  1149. PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
  1150. PCHAR startVa;
  1151. SmbPseOEAssertConsistentLinkage("SmbPseExchangeReceive_default: ");
  1152. UPDATE_OE_HISTORY_WITH_STATUS(ThisIsAReenter?'00':'01');
  1153. RxDbgTrace (0, Dbg, ("SmbPseExchangeReceive_default av/ind=%08lx/%08lx\n",
  1154. BytesAvailable,BytesIndicated)
  1155. );
  1156. RxDbgTrace (0, Dbg, (" -->headermdl %08lx\n",StufferState->HeaderMdl));
  1157. ASSERT_ORDINARY_EXCHANGE( OrdinaryExchange );
  1158. CommandState = &OrdinaryExchange->ParseResumeState;
  1159. if ( !ThisIsAReenter ) {
  1160. OrdinaryExchange->BytesIndicatedCopy = BytesIndicated;
  1161. OrdinaryExchange->BytesAvailableCopy = BytesAvailable;
  1162. pExchange->Status = SmbCeParseSmbHeader(
  1163. pExchange,
  1164. pSmbHeader,
  1165. CommandState,
  1166. &OrdinaryExchange->SmbStatus,
  1167. BytesAvailable,
  1168. BytesIndicated,
  1169. pBytesTaken);
  1170. UPDATE_OE_HISTORY_WITH_STATUS('22');
  1171. if ( pExchange->Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1172. goto COPY_FOR_RESUME;
  1173. }
  1174. if ( (pExchange->Status != STATUS_SUCCESS) ||
  1175. ((Command = OrdinaryExchange->ParseResumeState.AndXCommand) == SMB_COM_NO_ANDX_COMMAND) ) {
  1176. goto FINALLY;
  1177. }
  1178. if (Command == SMB_COM_WRITE_ANDX) {
  1179. if (!FlagOn(pSmbHeader->Flags2,SMB_FLAGS2_COMPRESSED)) {
  1180. if (OrdinaryExchange->ReadWrite.CompressedRequestInProgress) {
  1181. OrdinaryExchange->ReadWrite.CompressedReadOrWrite = FALSE;
  1182. }
  1183. }
  1184. }
  1185. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED);
  1186. } else {
  1187. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus;
  1188. RxDbgTrace (0, Dbg, (" -->this is a reenter\n"));
  1189. Command = CommandState->AndXCommand;
  1190. }
  1191. SmbStatus = OrdinaryExchange->SmbStatus;
  1192. if ( (SmbStatus!=RX_MAP_STATUS(SUCCESS)) ) {
  1193. RxDbgTrace (0, Dbg, (" STATUS NOT SUCCESS = %08lx\n", SmbStatus));
  1194. }
  1195. for ( ; Command != SMB_COM_NO_ANDX_COMMAND ; ) {
  1196. PSMBPSE_RECEIVE_MODEL_PARAMETERS ReceiveModelParams = &SmbPseReceiveModelParameters[Command];
  1197. ULONG ReceiveModelParamsFlags;
  1198. UCHAR mappedCommand = Command;
  1199. PCHAR Response = (PCHAR)pSmbHeader + SmbGetUshort(&CommandState->AndXOffset);
  1200. if( Response > (PCHAR)pSmbHeader + BytesAvailable )
  1201. {
  1202. // Invalid Command
  1203. *pBytesTaken = BytesAvailable;
  1204. *pDataBufferPointer = NULL;
  1205. *pDataSize = 0;
  1206. Status = STATUS_SUCCESS;
  1207. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1208. goto FINALLY;
  1209. }
  1210. OrdinaryExchange->LastSmbCommand = Command; //this is used to multiplex in finish routines
  1211. UPDATE_OE_HISTORY_WITH_STATUS('88');
  1212. //
  1213. // Case on the Smb Command Type
  1214. //
  1215. ReceiveModelParamsFlags = ReceiveModelParams->Flags;
  1216. if (ReceiveModelParamsFlags!=0) {
  1217. //map this onto read_andx....which is the arm of the switch that implements the model
  1218. mappedCommand = SMB_COM_READ_ANDX;
  1219. } else {
  1220. //
  1221. // If there's a continuation, then copy&post. it used to always do this.
  1222. // now, we're going to do it unless the command is modeled.
  1223. // the modeling code will take care of correctly deciding to post/nopost.
  1224. //
  1225. if ( (OrdinaryExchange->AsyncResumptionRoutine != NULL) &&
  1226. !ThisIsAReenter) {
  1227. goto COPY_FOR_RESUME;
  1228. }
  1229. }
  1230. switch (mappedCommand) {
  1231. case SMB_COM_READ_ANDX:
  1232. {
  1233. NTSTATUS FinishStatus = RX_MAP_STATUS(SUCCESS);
  1234. NTSTATUS FinalStatus = RX_MAP_STATUS(SUCCESS);
  1235. BOOLEAN ThisIsAnAndX = BooleanFlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_THIS_IS_ANDX);
  1236. BOOLEAN ThisWouldBeMyError = (IM_THE_LAST_GUY || !ThisIsAnAndX);
  1237. RxDbgTrace( 0, Dbg, (" *(ind) %s, smbstatus=%08lx\n",ReceiveModelParams->IndicationString,SmbStatus) );
  1238. IF_DEBUG {
  1239. BOOLEAN BadType = FALSE;
  1240. DbgDoit(BadType = (OrdinaryExchange->OEType < ReceiveModelParams->LowType)
  1241. || (OrdinaryExchange->OEType > ReceiveModelParams->HighType) );
  1242. if (BadType) {
  1243. DbgPrint("Bad OEType....%u,Cmd=%02lx,Exch=%08lx\n",OrdinaryExchange->OEType,Command,OrdinaryExchange);
  1244. ASSERT(!"proceed???");
  1245. }
  1246. }
  1247. // If this is an error and it's an error for this guy of the AndX
  1248. // chain then finishup If it's a warning tho, continue according
  1249. // to the Flags
  1250. if ( NT_ERROR(SmbStatus) && ThisWouldBeMyError ) {
  1251. SmbPseDiscardProtocol( SmbStatus );
  1252. RxDbgTrace( 0, Dbg, ("--->discard1\n"));
  1253. goto FINALLY;
  1254. } else if ( (SmbStatus != RX_MAP_STATUS(SUCCESS)) && ThisWouldBeMyError ) {
  1255. if (!FlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_WARNINGS_OK)) {
  1256. SmbPseDiscardProtocol(SmbStatus);
  1257. RxDbgTrace( 0, Dbg, ("--->discard1\n"));
  1258. goto FINALLY;
  1259. } else {
  1260. FinalStatus = SmbStatus;
  1261. }
  1262. }
  1263. // if there's no nocopy handler then do things the old way
  1264. if (!FlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_NOCOPY_HANDLER)) {
  1265. // TEMPORARY!!!!!!
  1266. // If there's a continuation, then copy&post. it used to always do this. now, we're
  1267. // going to do it unless the command is modeled. the modeling code will take care of
  1268. // correctly deciding to post/nopost.
  1269. //
  1270. if ((OrdinaryExchange->AsyncResumptionRoutine != NULL) &&
  1271. !ThisIsAReenter ) {
  1272. goto COPY_FOR_RESUME;
  1273. }
  1274. //
  1275. // Some operations can be completed only in the context of the thread
  1276. // originating the request. (for example CREATE.)
  1277. //
  1278. if( FlagOn( ReceiveModelParamsFlags, SMBPSE_RMP_FORCE_SYNC ) &&
  1279. !ThisIsAReenter ) {
  1280. goto COPY_FOR_RESUME;
  1281. }
  1282. //eventually, we'll finish from here but for now copy
  1283. //CODE.IMPROVEMENT.ASHAMED....this is really mandatory.......
  1284. if (RxShouldPostCompletion()) {
  1285. goto COPY_FOR_RESUME;
  1286. }
  1287. if (ReceiveModelParams->ReceiveHandlerToken < SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM){
  1288. PSMBPSE_RECEIVE_HANDLER ReceiveHandler = SmbPseReceiveHandlers[ReceiveModelParams->ReceiveHandlerToken];
  1289. FinishStatus = ReceiveHandler( OrdinaryExchange, Response);
  1290. }
  1291. } else {
  1292. PSMBPSE_NOCOPY_RECEIVE_HANDLER NoCopyReceiveHandler =
  1293. (PSMBPSE_NOCOPY_RECEIVE_HANDLER)(SmbPseReceiveHandlers[ReceiveModelParams->ReceiveHandlerToken]);
  1294. UCHAR Action;
  1295. OrdinaryExchange->NoCopyFinalStatus = FinalStatus;
  1296. Action = NoCopyReceiveHandler(
  1297. OrdinaryExchange,
  1298. BytesIndicated,
  1299. BytesAvailable,
  1300. pBytesTaken,
  1301. pSmbHeader,
  1302. pDataBufferPointer,
  1303. pDataSize,
  1304. #if DBG
  1305. ThisIsAReenter,
  1306. #endif
  1307. Response );
  1308. switch(Action) {
  1309. case SMBPSE_NOCOPYACTION_NORMALFINISH:
  1310. NOTHING;
  1311. break;
  1312. case SMBPSE_NOCOPYACTION_MDLFINISH:
  1313. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1314. //note that whatever does this must be the last command in the
  1315. // packet unless we make continueOE more complicated
  1316. goto FINALLY;
  1317. case SMBPSE_NOCOPYACTION_COPY_FOR_RESUME:
  1318. goto COPY_FOR_RESUME;
  1319. case SMBPSE_NOCOPYACTION_DISCARD:
  1320. *pBytesTaken = BytesAvailable;
  1321. RxDbgTrace( 0, Dbg, ("--->discardX\n"));
  1322. goto FINALLY;
  1323. }
  1324. }
  1325. pExchange->Status = (FinishStatus==RX_MAP_STATUS(SUCCESS))
  1326. ? FinalStatus : FinishStatus;
  1327. if (!ThisIsAnAndX) {
  1328. Response = (PCHAR)&NullGenericAndX;
  1329. }
  1330. }//this corresponds to the top level of the switch
  1331. break;
  1332. default:
  1333. {
  1334. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  1335. RxDbgTrace( 0, Dbg, (" *(ind) Unimplemented cmd=%02lx,wct=%02lx\n",
  1336. Command,*Response) );
  1337. SmbCeTransportDisconnectIndicated(pServerEntry);
  1338. *pBytesTaken = BytesAvailable;
  1339. *pDataBufferPointer = NULL;
  1340. *pDataSize = 0;
  1341. Status = STATUS_SUCCESS;
  1342. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1343. goto FINALLY;
  1344. }
  1345. }
  1346. CommandState = (PGENERIC_ANDX)Response;
  1347. Command = CommandState->AndXCommand;
  1348. }
  1349. //
  1350. // If we get here then we're done.
  1351. // Make everyone happy by taking all the bytes.
  1352. //
  1353. //CODE.IMPROVEMENT: it is not clear to me that this is enough. some servers may send extra bytes
  1354. // on the end.
  1355. //
  1356. *pBytesTaken = BytesAvailable;
  1357. goto FINALLY;
  1358. COPY_FOR_RESUME:
  1359. //CODE.IMPROVEMENT even if we are taking by copy (as opposed to tail-MDL
  1360. // which is how reads should work) we shouldn't copy the whole packet -
  1361. // just the residue. of course, this is really only an issue when we have
  1362. // significant andXing.
  1363. CopyBufferLength = MmGetMdlByteCount(StufferState->HeaderMdl);
  1364. if (BytesAvailable > CopyBufferLength) {
  1365. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1366. *pBytesTaken = BytesAvailable;
  1367. Status = STATUS_SUCCESS;
  1368. } else if (!FlagOn(ReceiveFlags,TDI_RECEIVE_ENTIRE_MESSAGE) ||
  1369. (BytesAvailable > BytesIndicated) ||
  1370. (BytesAvailable > 127)) {
  1371. RxDbgTrace( 0, Dbg, ("Taking data through MDL\n") );
  1372. // Pass an MDL back in for copying the data
  1373. *pDataBufferPointer = StufferState->HeaderMdl;
  1374. *pDataSize = CopyBufferLength;
  1375. *pBytesTaken = 0;
  1376. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1377. } else {
  1378. // Copy the data and resume the exchange
  1379. ASSERT( BytesAvailable == BytesIndicated );
  1380. RxDbgTrace( 0, Dbg, ("Taking data through copying\n") );
  1381. *pBytesTaken = OrdinaryExchange->MessageLength = BytesAvailable;
  1382. RtlCopyMemory(StufferState->BufferBase,
  1383. pSmbHeader,BytesIndicated);
  1384. ASSERT(SmbGetUlong((PULONG)pSmbHeader->Protocol) == (ULONG)SMB_HEADER_PROTOCOL);
  1385. pExchange->Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED);
  1386. }
  1387. if (ThisIsAReenter) {
  1388. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1389. }
  1390. FINALLY:
  1391. OrdinaryExchange->ParseResumeState = *CommandState;
  1392. UPDATE_OE_HISTORY_WITH_STATUS('99');
  1393. return Status;
  1394. } // SmbPseExchangeReceive_default
  1395. #define SmbPseRIStringsBufferSize 500
  1396. CHAR SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferSize];
  1397. ULONG SmbPseRIStringsBufferUsed = 0;
  1398. VOID
  1399. __SmbPseRMTableEntry(
  1400. UCHAR SmbCommand,
  1401. UCHAR Flags,
  1402. SMBPSE_RECEIVE_HANDLER_TOKEN ReceiveHandlerToken,
  1403. PSMBPSE_RECEIVE_HANDLER ReceiveHandler
  1404. #if DBG
  1405. ,
  1406. PBYTE IndicationString,
  1407. SMB_PSE_ORDINARY_EXCHANGE_TYPE LowType,
  1408. SMB_PSE_ORDINARY_EXCHANGE_TYPE HighType
  1409. #endif
  1410. )
  1411. {
  1412. PSMBPSE_RECEIVE_MODEL_PARAMETERS r = &SmbPseReceiveModelParameters[SmbCommand];
  1413. #if DBG
  1414. ULONG ISlength = strlen(IndicationString)+1;
  1415. #endif
  1416. PAGED_CODE();
  1417. r->Flags = SMBPSE_RMP_MODELED | Flags;
  1418. r->ReceiveHandlerToken = (UCHAR)ReceiveHandlerToken;
  1419. if (ReceiveHandlerToken < SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM){
  1420. ASSERT((SmbPseReceiveHandlers[ReceiveHandlerToken] == ReceiveHandler)
  1421. || (SmbPseReceiveHandlers[ReceiveHandlerToken] == NULL));
  1422. SmbPseReceiveHandlers[ReceiveHandlerToken] = ReceiveHandler;
  1423. }
  1424. #if DBG
  1425. r->ReceiveHandler = ReceiveHandler;
  1426. r->LowType = LowType;
  1427. r->HighType = HighType;
  1428. if (SmbPseRIStringsBufferUsed+ISlength<=SmbPseRIStringsBufferSize) {
  1429. r->IndicationString = &SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferUsed];
  1430. RtlCopyMemory(r->IndicationString,IndicationString,ISlength);
  1431. } else {
  1432. if (SmbPseRIStringsBufferUsed<SmbPseRIStringsBufferSize) {
  1433. DbgPrint("Overflowing the indicationstringarray...%s\n",IndicationString);
  1434. ASSERT(!"fix it please");
  1435. }
  1436. r->IndicationString = &SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferUsed];
  1437. }
  1438. SmbPseRIStringsBufferUsed += ISlength;
  1439. #endif
  1440. }
  1441. #if DBG
  1442. #define SmbPseRMTableEntry(__smbcommand,b,c,token,__rcv,flags) \
  1443. __SmbPseRMTableEntry(SMB_COM_##__smbcommand,flags,token,__rcv \
  1444. ,#__smbcommand,b,c)
  1445. #else
  1446. #define SmbPseRMTableEntry(__smbcommand,b,c,token,__rcv,flags) \
  1447. __SmbPseRMTableEntry(SMB_COM_##__smbcommand,flags,token,__rcv \
  1448. )
  1449. #endif
  1450. VOID
  1451. SmbPseInitializeTables(
  1452. void
  1453. )
  1454. /*++
  1455. Routine Description:
  1456. This routine initializes tables that are used at various points by the
  1457. smbpse mechanisms. The must succeed structure(s) is(are) also initialized.
  1458. Arguments:
  1459. none
  1460. Return Value:
  1461. none
  1462. --*/
  1463. {
  1464. ULONG i;
  1465. PAGED_CODE();
  1466. for (i=0;i<256;i++) {
  1467. SmbPseReceiveModelParameters[i].Flags = 0;
  1468. SmbPseReceiveModelParameters[i].ReceiveHandlerToken =
  1469. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM;
  1470. }
  1471. for (i=0;i<SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM;i++) {
  1472. SmbPseReceiveHandlers[i] = NULL;
  1473. }
  1474. SmbPseRMTableEntry(
  1475. READ_ANDX,
  1476. SMBPSE_OETYPE_READ,
  1477. SMBPSE_OETYPE_READ,
  1478. SMBPSE_RECEIVE_HANDLER_TOKEN_READ_ANDX_HANDLER,
  1479. MRxSmbReceiveHandler_Read_NoCopy,
  1480. SMBPSE_RMP_THIS_IS_ANDX|SMBPSE_RMP_WARNINGS_OK|SMBPSE_RMP_NOCOPY_HANDLER);
  1481. SmbPseRMTableEntry(
  1482. READ,
  1483. SMBPSE_OETYPE_READ,
  1484. SMBPSE_OETYPE_READ,
  1485. SMBPSE_RECEIVE_HANDLER_TOKEN_READ_ANDX_HANDLER,
  1486. MRxSmbReceiveHandler_Read_NoCopy,
  1487. SMBPSE_RMP_WARNINGS_OK|SMBPSE_RMP_NOCOPY_HANDLER);
  1488. SmbPseRMTableEntry(
  1489. WRITE_ANDX,
  1490. SMBPSE_OETYPE_WRITE,
  1491. SMBPSE_OETYPE_EXTEND_WRITE,
  1492. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_ANDX_HANDLER,
  1493. MRxSmbReceiveHandler_WriteAndX,
  1494. SMBPSE_RMP_THIS_IS_ANDX);
  1495. SmbPseRMTableEntry(
  1496. WRITE,
  1497. SMBPSE_OETYPE_WRITE,
  1498. SMBPSE_OETYPE_CORETRUNCATE,
  1499. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_HANDLER,
  1500. MRxSmbReceiveHandler_CoreWrite,
  1501. 0);
  1502. SmbPseRMTableEntry(
  1503. WRITE_PRINT_FILE,
  1504. SMBPSE_OETYPE_WRITE,
  1505. SMBPSE_OETYPE_WRITE,
  1506. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_PRINTFILE_HANDLER,
  1507. MRxSmbReceiveHandler_WritePrintFile,
  1508. 0);
  1509. SmbPseRMTableEntry(
  1510. LOCKING_ANDX,
  1511. SMBPSE_OETYPE_LOCKS,
  1512. SMBPSE_OETYPE_ASSERTBUFFEREDLOCKS,
  1513. SMBPSE_RECEIVE_HANDLER_TOKEN_LOCKING_ANDX_HANDLER,
  1514. MRxSmbReceiveHandler_LockingAndX,
  1515. SMBPSE_RMP_THIS_IS_ANDX);
  1516. SmbPseRMTableEntry(
  1517. UNLOCK_BYTE_RANGE,
  1518. SMBPSE_OETYPE_LOCKS,
  1519. SMBPSE_OETYPE_LOCKS,
  1520. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1521. NULL,
  1522. 0);
  1523. SmbPseRMTableEntry(
  1524. LOCK_BYTE_RANGE,
  1525. SMBPSE_OETYPE_LOCKS,
  1526. SMBPSE_OETYPE_LOCKS,
  1527. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1528. NULL,
  1529. 0);
  1530. SmbPseRMTableEntry(
  1531. OPEN_PRINT_FILE,
  1532. SMBPSE_OETYPE_CREATEPRINTFILE,
  1533. SMBPSE_OETYPE_CREATEPRINTFILE,
  1534. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_PRINTFILE_HANDLER,
  1535. MRxSmbReceiveHandler_OpenPrintFile,
  1536. 0);
  1537. SmbPseRMTableEntry(
  1538. QUERY_INFORMATION2,
  1539. SMBPSE_OETYPE_GFA,
  1540. SMBPSE_OETYPE_GFA,
  1541. SMBPSE_RECEIVE_HANDLER_TOKEN_GFA_HANDLER,
  1542. MRxSmbReceiveHandler_GetFileAttributes,
  1543. 0);
  1544. SmbPseRMTableEntry(
  1545. CLOSE_PRINT_FILE,
  1546. SMBPSE_OETYPE_CLOSE,
  1547. SMBPSE_OETYPE_CLOSE,
  1548. SMBPSE_RECEIVE_HANDLER_TOKEN_CLOSE_HANDLER,
  1549. MRxSmbReceiveHandler_Close,
  1550. 0);
  1551. SmbPseRMTableEntry(
  1552. NT_CREATE_ANDX,
  1553. SMBPSE_OETYPE_LATENT_HEADEROPS,
  1554. SMBPSE_OETYPE_CREATE,
  1555. SMBPSE_RECEIVE_HANDLER_TOKEN_NTCREATE_ANDX_HANDLER,
  1556. MRxSmbReceiveHandler_NTCreateAndX,
  1557. SMBPSE_RMP_THIS_IS_ANDX | SMBPSE_RMP_FORCE_SYNC);
  1558. SmbPseRMTableEntry(
  1559. OPEN_ANDX,
  1560. SMBPSE_OETYPE_LATENT_HEADEROPS,
  1561. SMBPSE_OETYPE_CREATE,
  1562. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_ANDX_HANDLER,
  1563. MRxSmbReceiveHandler_OpenAndX,
  1564. SMBPSE_RMP_THIS_IS_ANDX | SMBPSE_RMP_FORCE_SYNC);
  1565. SmbPseRMTableEntry(
  1566. OPEN,
  1567. SMBPSE_OETYPE_COREOPEN,
  1568. SMBPSE_OETYPE_COREOPEN,
  1569. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_HANDLER,
  1570. MRxSmbReceiveHandler_CoreOpen,
  1571. SMBPSE_RMP_FORCE_SYNC);
  1572. SmbPseRMTableEntry(
  1573. CREATE,
  1574. SMBPSE_OETYPE_CORECREATE,
  1575. SMBPSE_OETYPE_CORECREATE,
  1576. SMBPSE_RECEIVE_HANDLER_TOKEN_CREATE_HANDLER,
  1577. MRxSmbReceiveHandler_CoreCreate,
  1578. SMBPSE_RMP_FORCE_SYNC);
  1579. SmbPseRMTableEntry(
  1580. CREATE_NEW,
  1581. SMBPSE_OETYPE_CORECREATE,
  1582. SMBPSE_OETYPE_CORECREATE,
  1583. SMBPSE_RECEIVE_HANDLER_TOKEN_CREATE_HANDLER,
  1584. MRxSmbReceiveHandler_CoreCreate,
  1585. SMBPSE_RMP_FORCE_SYNC);
  1586. SmbPseRMTableEntry(
  1587. CLOSE,
  1588. SMBPSE_OETYPE_CLOSE,
  1589. SMBPSE_OETYPE_CLOSEAFTERCORECREATE,
  1590. SMBPSE_RECEIVE_HANDLER_TOKEN_CLOSE_HANDLER,
  1591. MRxSmbReceiveHandler_Close,
  1592. 0);
  1593. SmbPseRMTableEntry(
  1594. QUERY_INFORMATION,
  1595. 0,
  1596. SMBPSE_OETYPE_MAXIMUM,
  1597. SMBPSE_RECEIVE_HANDLER_TOKEN_GFA_HANDLER,
  1598. MRxSmbReceiveHandler_GetFileAttributes,
  1599. 0);
  1600. SmbPseRMTableEntry(
  1601. TRANSACTION2,
  1602. SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO,
  1603. SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO,
  1604. SMBPSE_RECEIVE_HANDLER_TOKEN_TRANS2_ANDX_HANDLER,
  1605. MRxSmbReceiveHandler_Transact2,
  1606. 0);
  1607. SmbPseRMTableEntry(
  1608. TRANSACTION2_SECONDARY,
  1609. SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO,
  1610. SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO,
  1611. SMBPSE_RECEIVE_HANDLER_TOKEN_TRANS2_ANDX_HANDLER,
  1612. MRxSmbReceiveHandler_Transact2,
  1613. 0);
  1614. SmbPseRMTableEntry(
  1615. SEARCH,
  1616. SMBPSE_OETYPE_COREQUERYLABEL,
  1617. SMBPSE_OETYPE_CORESEARCHFORCHECKEMPTY,
  1618. SMBPSE_RECEIVE_HANDLER_TOKEN_SEARCH_HANDLER,
  1619. MRxSmbReceiveHandler_Search,
  1620. 0);
  1621. SmbPseRMTableEntry(
  1622. QUERY_INFORMATION_DISK,
  1623. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES,
  1624. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES,
  1625. SMBPSE_RECEIVE_HANDLER_TOKEN_QUERYDISKINFO_HANDLER,
  1626. MRxSmbReceiveHandler_QueryDiskInfo,
  1627. 0);
  1628. SmbPseRMTableEntry(
  1629. DELETE,
  1630. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1631. SMBPSE_OETYPE_DELETE_FOR_RENAME,
  1632. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1633. NULL,
  1634. 0);
  1635. SmbPseRMTableEntry(
  1636. DELETE_DIRECTORY,
  1637. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1638. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1639. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1640. NULL,
  1641. 0);
  1642. SmbPseRMTableEntry(
  1643. CHECK_DIRECTORY,
  1644. SMBPSE_OETYPE_CORECHECKDIRECTORY,
  1645. SMBPSE_OETYPE_CORECHECKDIRECTORY,
  1646. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1647. NULL,
  1648. 0);
  1649. SmbPseRMTableEntry(
  1650. SET_INFORMATION,
  1651. SMBPSE_OETYPE_SFA,
  1652. SMBPSE_OETYPE_SFA,
  1653. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1654. NULL,
  1655. 0);
  1656. SmbPseRMTableEntry(
  1657. SET_INFORMATION2,
  1658. SMBPSE_OETYPE_SFA2,
  1659. SMBPSE_OETYPE_SFA2,
  1660. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1661. NULL,
  1662. 0);
  1663. SmbPseRMTableEntry(
  1664. CREATE_DIRECTORY,
  1665. SMBPSE_OETYPE_CORECREATEDIRECTORY,
  1666. SMBPSE_OETYPE_CORECREATEDIRECTORY,
  1667. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1668. NULL,
  1669. 0);
  1670. SmbPseRMTableEntry(
  1671. FLUSH,
  1672. SMBPSE_OETYPE_FLUSH,
  1673. SMBPSE_OETYPE_FLUSH,
  1674. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1675. NULL,
  1676. 0);
  1677. SmbPseRMTableEntry(
  1678. FIND_CLOSE2,
  1679. SMBPSE_OETYPE_FINDCLOSE,
  1680. SMBPSE_OETYPE_FINDCLOSE,
  1681. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1682. NULL,
  1683. 0);
  1684. SmbPseRMTableEntry(
  1685. RENAME,
  1686. SMBPSE_OETYPE_RENAME,
  1687. SMBPSE_OETYPE_RENAME,
  1688. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1689. NULL,
  1690. 0);
  1691. SmbPseRMTableEntry(
  1692. NT_RENAME,
  1693. SMBPSE_OETYPE_RENAME,
  1694. SMBPSE_OETYPE_RENAME,
  1695. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1696. NULL,
  1697. 0);
  1698. SmbPseRMTableEntry(
  1699. IOCTL,
  1700. SMBPSE_OETYPE_IOCTL,
  1701. SMBPSE_OETYPE_IOCTL,
  1702. SMBPSE_RECEIVE_HANDLER_TOKEN_IOCTL_HANDLER,
  1703. MRxSmbReceiveHandler_Ioctl,
  1704. 0);
  1705. }
  1706. #ifdef WIN9X
  1707. NTSTATUS
  1708. MRxSmbQueryDosVolumeInformation(
  1709. IN OUT PRX_CONTEXT RxContext,
  1710. IN OUT PVOID pBuffer,
  1711. IN OUT PULONG pBufferLength
  1712. )
  1713. /*++
  1714. Routine Description:
  1715. This routine queries the volume information
  1716. Arguments:
  1717. pRxContext - the RDBSS context
  1718. FsInformationClass - the kind of Fs information desired.
  1719. pBuffer - the buffer for copying the information
  1720. pBufferLength - the buffer length ( set to buffer length on input and set
  1721. to the remaining length on output)
  1722. Return Value:
  1723. RXSTATUS - The return status for the operation
  1724. --*/
  1725. {
  1726. PAGED_CODE();
  1727. TURN_BACK_ASYNCHRONOUS_OPERATIONS();
  1728. return MRxSmbVolumeInformation(RxContext, 0, pBuffer, pBufferLength);
  1729. }
  1730. #endif
  1731. #ifndef RX_NO_DBGFIELD_HLPRS
  1732. #define DECLARE_FIELD_HLPR(x) ULONG SmbPseOeField_##x = FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,x);
  1733. #define DECLARE_FIELD_HLPR2(x,y) ULONG SmbPseOeField_##x##y = FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,x.y);
  1734. DECLARE_FIELD_HLPR(RxContext);
  1735. DECLARE_FIELD_HLPR(ReferenceCount);
  1736. DECLARE_FIELD_HLPR(AssociatedStufferState);
  1737. DECLARE_FIELD_HLPR(Flags);
  1738. DECLARE_FIELD_HLPR(ReadWrite);
  1739. DECLARE_FIELD_HLPR(Transact2);
  1740. DECLARE_FIELD_HLPR2(Create,FileInfo);
  1741. DECLARE_FIELD_HLPR2(Create,smbSrvOpen);
  1742. DECLARE_FIELD_HLPR2(ReadWrite,RemainingByteCount);
  1743. DECLARE_FIELD_HLPR2(Info,FileInfo);
  1744. DECLARE_FIELD_HLPR2(Info,Buffer);
  1745. #endif
  1746.