Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2206 lines
67 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. SmbPseContinueOrdinaryExchange(
  335. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  336. )
  337. /*++
  338. Routine Description:
  339. This routine resumes processing on an exchange. This is called when work is
  340. required to finish processing a request that cannot be completed at DPC
  341. level. This happens either because the parse routine needs access to
  342. structures that are not locks OR because the operation if asynchronous and
  343. there maybe more work to be done.
  344. The two cases are regularized by delaying the parse if we know that we're
  345. going to post: this is indicated by the presense of a resume routine.
  346. Arguments:
  347. RxContext - the context of the operation. .
  348. Return Value:
  349. NTSTATUS - The return status for the operation
  350. Notes:
  351. --*/
  352. {
  353. NTSTATUS Status;
  354. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  355. RxCaptureFobx;
  356. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  357. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  358. PMDL SubmitMdl, HeaderFullMdl;
  359. BOOLEAN InvokeContinuationRoutine = FALSE;
  360. PAGED_CODE();
  361. RxDbgTrace(+1, Dbg, ("SmbPseContinueOrdinaryExchange entering........OE=%08lx\n",OrdinaryExchange));
  362. Status = Exchange->Status;
  363. if (OrdinaryExchange->OpSpecificState !=
  364. SmbPseOEInnerIoStates_OperationCompleted) {
  365. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_AWAITING_DISPATCH);
  366. SmbPseOEAssertConsistentLinkageFromOE("SmbPseContinueOrdinaryExchange:");
  367. UPDATE_OE_HISTORY_WITH_STATUS('0c');
  368. SubmitMdl = StufferState->HeaderPartialMdl;
  369. HeaderFullMdl = StufferState->HeaderMdl;
  370. ASSERT(FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED));
  371. SmbPseOEAssertConsistentLinkage("Top of OE continue: ");
  372. RxUnprotectMdlFromFree(SubmitMdl);
  373. RxUnprotectMdlFromFree(HeaderFullMdl);
  374. SmbPseDbgCheckOEMdls(
  375. OrdinaryExchange,"SmbPseContinueOrdinaryExchange(top)");
  376. SmbPseDbgRunMdlChain(
  377. SubmitMdl,
  378. OrdinaryExchange->SaveLengthForDebug,
  379. OrdinaryExchange,
  380. "SmbPseContinueOrdinaryExchange(top)");
  381. MmPrepareMdlForReuse(SubmitMdl);
  382. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED);
  383. SmbPseVerifyDataPartialAllocationPerFlags(OrdinaryExchange);
  384. if ( OrdinaryExchange->DataPartialMdl ) {
  385. MmPrepareMdlForReuse( OrdinaryExchange->DataPartialMdl );
  386. }
  387. RxDbgTrace( 0, Dbg, (" --> P4Reuse %08lx, full %08lx is no longer unlocked here\n"
  388. ,SubmitMdl,HeaderFullMdl));
  389. }
  390. if (OrdinaryExchange->ContinuationRoutine == NULL) {
  391. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  392. ULONG BytesTaken;
  393. ULONG DataSize = 0;
  394. ULONG MessageLength = OrdinaryExchange->MessageLength;
  395. PMDL DataBufferPointer = NULL;
  396. PSMB_HEADER SmbHeader = (PSMB_HEADER)StufferState->BufferBase;
  397. Status = SMB_EXCHANGE_DISPATCH(
  398. Exchange,
  399. Receive,
  400. (
  401. Exchange, // IN struct SMB_EXCHANGE *pExchange,
  402. MessageLength, // IN ULONG BytesIndicated,
  403. MessageLength, // IN ULONG BytesAvailable,
  404. &BytesTaken, // OUT ULONG *pBytesTaken,
  405. SmbHeader, // IN PSMB_HEADER pSmbHeader,
  406. &DataBufferPointer, // OUT PMDL *pDataBufferPointer,
  407. &DataSize, // OUT PULONG pDataSize)
  408. TDI_RECEIVE_ENTIRE_MESSAGE
  409. ));
  410. if (Status == STATUS_SUCCESS) {
  411. Status = Exchange->Status;
  412. UPDATE_OE_HISTORY_WITH_STATUS('2c');
  413. } else {
  414. UPDATE_OE_HISTORY_WITH_STATUS('dd');
  415. }
  416. if (DataSize != 0 ||
  417. DataBufferPointer != NULL ||
  418. BytesTaken != MessageLength ||
  419. Status == STATUS_MORE_PROCESSING_REQUIRED) {
  420. Status = STATUS_INVALID_NETWORK_RESPONSE;
  421. }
  422. InvokeContinuationRoutine = TRUE;
  423. }
  424. } else {
  425. InvokeContinuationRoutine = TRUE;
  426. }
  427. if (InvokeContinuationRoutine) {
  428. if ( OrdinaryExchange->ContinuationRoutine != NULL ) {
  429. if ( Status == STATUS_MORE_PROCESSING_REQUIRED){
  430. Exchange->Status = STATUS_SUCCESS;
  431. }
  432. Status = OrdinaryExchange->ContinuationRoutine( OrdinaryExchange );
  433. UPDATE_OE_HISTORY_WITH_STATUS('1c');
  434. if (Status != STATUS_PENDING) {
  435. Exchange->Status = Status;
  436. OrdinaryExchange->ContinuationRoutine = NULL;
  437. }
  438. }
  439. }
  440. if (Status != STATUS_PENDING) {
  441. if (Status != STATUS_SUCCESS) {
  442. if (RxContext->MajorFunction != IRP_MJ_CLOSE) {
  443. // There is no point in transitioning CLOSE operations since
  444. // the context is lost anycase.
  445. Status = CscTransitionVNetRootForDisconnectedOperation(
  446. RxContext,
  447. SmbCeGetExchangeVNetRoot(
  448. (PSMB_EXCHANGE)OrdinaryExchange),
  449. Status);
  450. }
  451. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus = Status;
  452. }
  453. if (OrdinaryExchange->AsyncResumptionRoutine ) {
  454. //call the continuation is it's async
  455. Status = OrdinaryExchange->AsyncResumptionRoutine(
  456. OrdinaryExchange,
  457. RxContext );
  458. UPDATE_OE_HISTORY_WITH_STATUS('3c');
  459. }
  460. //remove my references, if i'm the last guy then do the putaway...
  461. UPDATE_OE_HISTORY_WITH_STATUS('4c');
  462. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  463. }
  464. RxDbgTrace(-1, Dbg, ("SmbPseContinueOrdinaryExchange returning %08lx.\n", Status));
  465. return(Status);
  466. } // SmbPseContinueOrdinaryExchange
  467. NTSTATUS
  468. SmbPseOrdinaryExchange(
  469. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  470. IN SMB_PSE_ORDINARY_EXCHANGE_TYPE OEType
  471. )
  472. /*++
  473. Routine Description:
  474. This routine implements an ordinary exchange as viewed by the protocol
  475. selection routines.
  476. Arguments:
  477. OrdinaryExchange - the exchange to be conducted.
  478. OEType - Ordinary Exchange Type
  479. Return Value:
  480. NTSTATUS - The return status for the operation
  481. Notes:
  482. --*/
  483. {
  484. NTSTATUS Status;
  485. RxCaptureFobx;
  486. RxCaptureFcb;
  487. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  488. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  489. PSMBSTUFFER_BUFFER_STATE StufferState;
  490. PSMB_PSE_OE_START_ROUTINE Continuation;
  491. ULONG SmbLength;
  492. PMDL SubmitMdl,HeaderFullMdl;
  493. ULONG SendOptions;
  494. DEBUG_ONLY_DECL( ULONG LengthP; ULONG LengthF; )
  495. KEVENT SyncEvent;
  496. PAGED_CODE();
  497. RxDbgTrace(+1, Dbg, ("SmbPseOrdinaryExchange entering.......OE=%08lx\n",OrdinaryExchange));
  498. SmbPseOEAssertConsistentLinkageFromOE("SmbPseOrdinaryExchange:");
  499. OrdinaryExchange->OEType = OEType;
  500. StufferState = &OrdinaryExchange->AssociatedStufferState;
  501. KeInitializeEvent(
  502. &SyncEvent,
  503. NotificationEvent,
  504. FALSE );
  505. HeaderFullMdl = StufferState->HeaderMdl;
  506. ASSERT( HeaderFullMdl != NULL );
  507. SmbLength = (ULONG)(StufferState->CurrentPosition - StufferState->BufferBase);
  508. SubmitMdl = StufferState->HeaderPartialMdl;
  509. ASSERT(RxMdlIsOwned(SubmitMdl));
  510. RxBuildPartialHeaderMdl(
  511. StufferState->HeaderMdl,
  512. SubmitMdl,
  513. StufferState->BufferBase,
  514. SmbLength );
  515. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED);
  516. //
  517. // If there is a data MDL associated with this request, then
  518. // we'll have to chain it.
  519. //
  520. SubmitMdl->Next = StufferState->DataMdl;
  521. if (StufferState->DataMdl) {
  522. SmbLength += StufferState->DataSize;
  523. }
  524. DbgDoit(
  525. SmbPseDbgRunMdlChain(
  526. SubmitMdl,
  527. SmbLength,
  528. OrdinaryExchange,
  529. "SmbPseOrdinaryExchange(before)");
  530. OrdinaryExchange->SaveDataMdlForDebug = SubmitMdl->Next;
  531. OrdinaryExchange->SaveLengthForDebug = SmbLength;
  532. if (OrdinaryExchange->RxContextCapturedRequestPacket != NULL) {
  533. OrdinaryExchange->SaveIrpMdlForDebug =
  534. OrdinaryExchange->RxContextCapturedRequestPacket->MdlAddress;
  535. }
  536. )
  537. RxDbgTrace(
  538. 0,
  539. Dbg,
  540. (" --> mdllength/smblength %08lx/%08lx headermdl %08lx\n",
  541. MmGetMdlByteCount(SubmitMdl), SmbLength, StufferState->HeaderMdl) );
  542. ClearFlag(
  543. OrdinaryExchange->Flags,
  544. (SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED |
  545. SMBPSE_OE_FLAG_OE_ALREADY_RESUMED) );
  546. SendOptions = OrdinaryExchange->SendOptions;
  547. SmbCeReferenceExchange( Exchange ); //this one is taken away in ContinueOE
  548. SmbCeReferenceExchange( Exchange ); //this one is taken away below...
  549. //i must NOT finalize before SmbCe returns
  550. SmbCeResetExchange(Exchange);
  551. Continuation = OrdinaryExchange->AsyncResumptionRoutine;
  552. if (((OrdinaryExchange->OEType == SMBPSE_OETYPE_WRITE) ||
  553. (OrdinaryExchange->OEType == SMBPSE_OETYPE_READ) ||
  554. (OrdinaryExchange->OEType == SMBPSE_OETYPE_LOCKS)) &&
  555. BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION)
  556. ) {
  557. ASSERT(Continuation!=NULL);
  558. }
  559. if (Continuation == NULL) {
  560. OrdinaryExchange->pSmbCeSynchronizationEvent = &SyncEvent;
  561. }
  562. DbgDoit((LengthP = MmGetMdlByteCount(SubmitMdl),LengthF = MmGetMdlByteCount(HeaderFullMdl)));
  563. RxProtectMdlFromFree(SubmitMdl);
  564. RxProtectMdlFromFree(HeaderFullMdl);
  565. SmbPseOEAssertConsistentLinkage("just before transceive: ");
  566. UPDATE_OE_HISTORY_2SHORTS('eo',(Continuation!=NULL)?'!!':0);
  567. DbgDoit( InterlockedIncrement(&OrdinaryExchange->History.Submits); )
  568. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_VALIDATE_FID)) {
  569. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  570. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  571. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(OrdinaryExchange);
  572. if (smbSrvOpen->Version == pServerEntry->Server.Version) {
  573. Status = STATUS_SUCCESS;
  574. } else {
  575. Exchange->Status = Exchange->SmbStatus = Status = STATUS_CONNECTION_DISCONNECTED;
  576. capFcb->fShouldBeOrphaned = TRUE;
  577. }
  578. IF_DEBUG {
  579. PSMB_HEADER pSmbHeader = (PSMB_HEADER)MmGetSystemAddressForMdlSafe(SubmitMdl,LowPagePriority);
  580. USHORT Flags2 = 0;
  581. if (pSmbHeader) {
  582. Flags2 = SmbGetUshort(&pSmbHeader->Flags2);
  583. }
  584. RxDbgTrace(0, Dbg, ("Flags2 Value for Exchange %lx is %lx\n",Exchange,Flags2));
  585. }
  586. } else {
  587. Status = STATUS_SUCCESS;
  588. }
  589. if (Status == STATUS_SUCCESS) {
  590. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_NO_RESPONSE_EXPECTED)) {
  591. Status = SmbCeSend(
  592. Exchange,
  593. SendOptions,
  594. SubmitMdl,
  595. SmbLength);
  596. } else {
  597. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(OrdinaryExchange);
  598. Status = SmbCeTranceive(
  599. Exchange,
  600. SendOptions,
  601. SubmitMdl,
  602. SmbLength);
  603. }
  604. }
  605. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange); //okay to finalize now that we're back
  606. if ( Status == STATUS_PENDING) {
  607. if ( Continuation != NULL ) {
  608. goto FINALLY;
  609. }
  610. UPDATE_OE_HISTORY_WITH_STATUS('1o');
  611. KeWaitForSingleObject(&SyncEvent,Executive, KernelMode, FALSE, NULL );
  612. OrdinaryExchange->pSmbCeSynchronizationEvent = NULL;
  613. ASSERT(RxMdlIsOwned(SubmitMdl));
  614. DbgDoit (
  615. //variables in the assert are only declared for DBG
  616. //asserts can be enabled separately
  617. ASSERT(
  618. LengthP == MmGetMdlByteCount(SubmitMdl) &&
  619. LengthF == MmGetMdlByteCount(HeaderFullMdl) );
  620. )
  621. } else {
  622. RxDbgTrace (0, Dbg, (" -->Status after transceive %08lx\n",Status));
  623. DbgDoit (
  624. //variables in the assert are only declared for DBG
  625. //asserts can be enabled separately
  626. ASSERT(
  627. LengthP == MmGetMdlByteCount(SubmitMdl) &&
  628. LengthF == MmGetMdlByteCount(HeaderFullMdl) );
  629. )
  630. RxUnprotectMdlFromFree(SubmitMdl);
  631. RxUnprotectMdlFromFree(HeaderFullMdl);
  632. SmbPseOEAssertConsistentLinkage("nonpending return from transceive: ");
  633. // if it's an error, remove the references that i placed and get out
  634. if (NT_ERROR(Status)) {
  635. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  636. goto FINALLY;
  637. }
  638. }
  639. //at last, call the continuation........
  640. SmbPseOEAssertConsistentLinkage("just before continueOE: ");
  641. UPDATE_OE_HISTORY_WITH_STATUS('9b');
  642. Status = SmbPseContinueOrdinaryExchange( OrdinaryExchange );
  643. UPDATE_OE_HISTORY_WITH_STATUS('9o');
  644. FINALLY:
  645. RxDbgTrace(-1, Dbg, ("SmbPseOrdinaryExchange returning %08lx.\n", Status));
  646. return(Status);
  647. } // SmbPseOrdinaryExchange
  648. NTSTATUS
  649. __SmbPseCreateOrdinaryExchange (
  650. IN PRX_CONTEXT RxContext,
  651. IN PMRX_V_NET_ROOT VNetRoot,
  652. IN SMB_PSE_ORDINARY_EXCHANGE_ENTRYPOINTS EntryPoint,
  653. IN PSMB_PSE_OE_START_ROUTINE StartRoutine,
  654. IN OUT SMBFCB_HOLDING_STATE *SmbFcbHoldingState OPTIONAL,
  655. OUT PSMB_PSE_ORDINARY_EXCHANGE *OrdinaryExchangePtr
  656. )
  657. /*++
  658. Routine Description:
  659. This routine allocates and initializes an SMB header buffer. Currently,
  660. we just allocate them from pool except when must_succeed is specified.
  661. Arguments:
  662. RxContext - the RDBSS context
  663. VNetRoot -
  664. DispatchVector -
  665. Return Value:
  666. A buffer ready to go, OR NULL.
  667. Notes:
  668. --*/
  669. {
  670. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  671. PSMBSTUFFER_BUFFER_STATE StufferState = NULL;
  672. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  673. PCHAR SmbBuffer = NULL;
  674. PMDL HeaderFullMdl = NULL;
  675. NTSTATUS Status = STATUS_SUCCESS;
  676. RxCaptureFobx;
  677. SMBFCB_HOLDING_STATE TempHoldingState = SmbFcb_NotHeld;
  678. PAGED_CODE();
  679. /*
  680. Other size improvement stuff: //CODE.IMPROVEMENT
  681. finalize renamed to transitiontoquiescent
  682. big fix - remove unwanted capture macros
  683. longname - delete top part of routine by using the studcode
  684. smbutils - we could reduce the table size by a factor of 2-3 by storing s 16bit representation of the ntstatus
  685. */
  686. RxDbgTrace(+1, Dbg, ("SmbPseCreateOrdinaryExchange\n") );
  687. if (SmbFcbHoldingState == NULL) {
  688. SmbFcbHoldingState = &TempHoldingState;
  689. }
  690. IF_NOT_MRXSMB_CSC_ENABLED{
  691. ASSERT(*SmbFcbHoldingState == SmbFcb_NotHeld);
  692. }
  693. OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)SmbMmAllocateExchange(ORDINARY_EXCHANGE,NULL);
  694. //we rely on the fact that SmbMmAllocate Zeros the exchange.............
  695. if (OrdinaryExchange == NULL) {
  696. Status = STATUS_INSUFFICIENT_RESOURCES;
  697. goto UNWIND;
  698. }
  699. StufferState = &OrdinaryExchange->AssociatedStufferState;
  700. StufferState->NodeTypeCode = SMB_NTC_STUFFERSTATE;
  701. StufferState->NodeByteSize = sizeof(SMBSTUFFER_BUFFER_STATE);
  702. StufferState->Exchange = &OrdinaryExchange->Exchange;
  703. DbgDoit(OrdinaryExchange->SerialNumber = RxContext->SerialNumber); //CODE.IMPROVEMENT should this be in the SMB_EXCHANGE?
  704. //
  705. // Initialize the exchange packet
  706. //
  707. Status = SmbCeInitializeExchange(
  708. &StufferState->Exchange,
  709. RxContext,
  710. (PMRX_V_NET_ROOT)VNetRoot,
  711. ORDINARY_EXCHANGE,
  712. &SmbPseOEDispatch);
  713. if (StufferState->Exchange != NULL) {
  714. SmbCeReferenceExchange(StufferState->Exchange);
  715. RxDbgTrace(0, Dbg, (" exchng=%08lx,type=%08lx\n",&StufferState->Exchange,StufferState->Exchange->Type));
  716. }
  717. StufferState->RxContext = RxContext;
  718. //place a reference on the rxcontext until we are finished
  719. InterlockedIncrement( &RxContext->ReferenceCount );
  720. OrdinaryExchange->StufferStateDbgPtr = StufferState;
  721. OrdinaryExchange->RxContext = RxContext;
  722. OrdinaryExchange->EntryPoint = EntryPoint;
  723. OrdinaryExchange->StartRoutine = StartRoutine;
  724. OrdinaryExchange->SmbBufSize = MAXIMUM_SMB_BUFFER_SIZE;
  725. DbgDoit(OrdinaryExchange->RxContextCapturedRequestPacket = RxContext->CurrentIrp;);
  726. //note: create path must turn this flag on.
  727. OrdinaryExchange->SmbCeFlags &= ~(SMBCE_EXCHANGE_ATTEMPT_RECONNECTS);
  728. ASSERT( (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_OE))
  729. || (OrdinaryExchange->Flags == 0) );
  730. ASSERT( OrdinaryExchange->SendOptions == 0 );
  731. ASSERT( OrdinaryExchange->DataPartialMdl == NULL );
  732. pMRxSmbContext->pExchange = &OrdinaryExchange->Exchange;
  733. pMRxSmbContext->pStufferState = StufferState;
  734. if (capFobx != NULL) {
  735. if (BooleanFlagOn(capFobx->Flags,FOBX_FLAG_DFS_OPEN)) {
  736. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG);
  737. }
  738. } else if (BooleanFlagOn(VNetRoot->pNetRoot->Flags,NETROOT_FLAG_DFS_AWARE_NETROOT) &&
  739. (RxContext->Create.NtCreateParameters.DfsContext == UIntToPtr(DFS_OPEN_CONTEXT))) {
  740. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG);
  741. }
  742. if (Status != STATUS_SUCCESS) {
  743. goto UNWIND;
  744. }
  745. //
  746. // Allocate the SmbBuffer
  747. //
  748. if (SmbBuffer == NULL) {
  749. SmbBuffer = (PCHAR)RxAllocatePoolWithTag(
  750. PagedPool,
  751. OrdinaryExchange->SmbBufSize +
  752. TRANSPORT_HEADER_SIZE,
  753. 'BMSx' );
  754. }
  755. if ( SmbBuffer == NULL ) {
  756. Status = STATUS_INSUFFICIENT_RESOURCES;
  757. goto UNWIND;
  758. }
  759. RxDbgTrace(0, Dbg, (" smbbuf=%08lx,stfstate=%08lx\n",SmbBuffer,StufferState));
  760. StufferState->ActualBufferBase = SmbBuffer;
  761. (PBYTE) SmbBuffer += TRANSPORT_HEADER_SIZE;
  762. StufferState->BufferBase = SmbBuffer;
  763. StufferState->BufferLimit = SmbBuffer + OrdinaryExchange->SmbBufSize;
  764. //
  765. // Init the HeaderMdl
  766. //
  767. HeaderFullMdl = StufferState->HeaderMdl = &OrdinaryExchange->HeaderMdl.Mdl;
  768. RxInitializeHeaderMdl(HeaderFullMdl,SmbBuffer, OrdinaryExchange->SmbBufSize);
  769. RxDbgTrace(
  770. 0,
  771. Dbg,
  772. (" --> smbbufsize %08lx, mdllength %08lx\n",
  773. OrdinaryExchange->SmbBufSize,
  774. MmGetMdlByteCount(HeaderFullMdl)));
  775. //finally, lock down the smbbuf taking different paths according to whether
  776. // we are must-succeed or not
  777. ASSERT( !RxMdlIsLocked(HeaderFullMdl) );
  778. ASSERT( HeaderFullMdl->Next == NULL );
  779. RxDbgTrace( 0, Dbg, (" --> LOCKING %08lx\n",HeaderFullMdl));
  780. RxProbeAndLockHeaderPages(
  781. HeaderFullMdl,
  782. KernelMode,
  783. IoModifyAccess,
  784. Status );
  785. if (Status != STATUS_SUCCESS) {
  786. RxDbgTrace( 0, Dbg, (" --> LOCKING FAILED\n"));
  787. goto UNWIND;
  788. }
  789. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED);
  790. if (MmGetSystemAddressForMdlSafe(HeaderFullMdl,LowPagePriority) == NULL) {
  791. Status = STATUS_INSUFFICIENT_RESOURCES;
  792. goto UNWIND;
  793. }
  794. //
  795. // No initialization is required for the partial...just set the pointer
  796. StufferState->HeaderPartialMdl = &OrdinaryExchange->HeaderPartialMdl.Mdl;
  797. RxDbgTrace( -1, Dbg, (" --> exiting w!\n") );
  798. *OrdinaryExchangePtr = OrdinaryExchange;
  799. return Status;
  800. UNWIND:
  801. RxDbgTrace( -1, Dbg, (" --> exiting w/o!\n") );
  802. if (OrdinaryExchange != NULL ) {
  803. SmbPseFinalizeOrdinaryExchange( OrdinaryExchange );
  804. }
  805. *OrdinaryExchangePtr = NULL;
  806. return Status;
  807. } // SmbPseCreateOrdinaryExchange
  808. #if DBG
  809. ULONG MRxSmbFinalizeStfStateTraceLevel = 1200;
  810. #define FINALIZESS_LEVEL MRxSmbFinalizeStfStateTraceLevel
  811. #define FINALIZE_TRACKING_SETUP() \
  812. struct { \
  813. ULONG marker1; \
  814. ULONG finalstate; \
  815. ULONG marker2; \
  816. } Tracking = {'ereh',0,'ereh'};
  817. #define FINALIZE_TRACKING(x) {\
  818. Tracking.finalstate |= x; \
  819. }
  820. #define FINALIZE_TRACE(x) SmbPseFinalizeOETrace(x,Tracking.finalstate)
  821. VOID
  822. SmbPseFinalizeOETrace(PSZ text,ULONG finalstate)
  823. {
  824. PAGED_CODE();
  825. RxDbgTraceLV(0, Dbg, FINALIZESS_LEVEL,
  826. ("MRxSmbFinalizeSmbStufferState --> %s(%08lx)\n",text,finalstate));
  827. }
  828. #else
  829. #define FINALIZE_TRACKING_SETUP()
  830. #define FINALIZE_TRACKING(x)
  831. #define FINALIZE_TRACE(x)
  832. #endif
  833. BOOLEAN
  834. SmbPseFinalizeOrdinaryExchange (
  835. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange
  836. )
  837. /*++
  838. Routine Description:
  839. This finalizes an OE.
  840. Arguments:
  841. OrdinaryExchange - pointer to the OE to be dismantled.
  842. Return Value:
  843. TRUE if finalization occurs otherwise FALSE.
  844. Notes:
  845. --*/
  846. {
  847. PMRXSMB_RX_CONTEXT pMRxSmbContext;
  848. PSMBSTUFFER_BUFFER_STATE StufferState;
  849. LONG result;
  850. ULONG OrdinaryExchangeFlags = OrdinaryExchange->Flags;
  851. FINALIZE_TRACKING_SETUP()
  852. PAGED_CODE();
  853. SmbPseOEAssertConsistentLinkageFromOEwithFlags(
  854. "SmbPseFinalizeOrdinaryExchange:",
  855. OECHKLINKAGE_FLAG_NO_REQPCKT_CHECK);
  856. StufferState = &OrdinaryExchange->AssociatedStufferState;
  857. pMRxSmbContext = MRxSmbGetMinirdrContext(StufferState->RxContext);
  858. RxDbgTraceLV(+1, Dbg, 1000, ("MRxSmbFinalizeSmbStufferState\n"));
  859. result = SmbCeDereferenceExchange(&OrdinaryExchange->Exchange);
  860. if ( result != 0 ) {
  861. RxDbgTraceLV(
  862. -1,
  863. Dbg,
  864. 1000,
  865. ("MRxSmbFinalizeSmbStufferState -- returning w/o finalizing (%d)\n",
  866. result));
  867. return FALSE;
  868. }
  869. #if 0
  870. RxLog((">>>OE %lx %lx %lx %lx %lx",
  871. OrdinaryExchange,
  872. OrdinaryExchange->DataPartialMdl,
  873. StufferState->HeaderPartialMdl,
  874. StufferState->HeaderMdl,
  875. OrdinaryExchange->Flags
  876. ));
  877. #endif
  878. FINALIZE_TRACKING( 0x10000000 );
  879. FINALIZE_TRACE("ready to freedatapartial");
  880. if (OrdinaryExchange->CopyDataPendingOperations != 0 ||
  881. OrdinaryExchange->SendCompletePendingOperations != 0) {
  882. DbgBreakPoint();
  883. }
  884. SmbPseVerifyDataPartialAllocationPerFlags(OrdinaryExchange);
  885. if ( OrdinaryExchange->DataPartialMdl ) {
  886. if (!FlagOn(OrdinaryExchangeFlags, SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_SMBBUF)) {
  887. IoFreeMdl( OrdinaryExchange->DataPartialMdl );
  888. FINALIZE_TRACKING( 0x8000000 );
  889. }
  890. }
  891. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED)) {
  892. RxUnlockHeaderPages(StufferState->HeaderMdl);
  893. ClearFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_LOCKED);
  894. MmPrepareMdlForReuse( StufferState->HeaderMdl );
  895. FINALIZE_TRACKING( 0x4000000 );
  896. }
  897. FINALIZE_TRACE("ready to uninit hdr partial");
  898. if (FlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_HDR_PARTIAL_INITIALIZED)) {
  899. MmPrepareMdlForReuse( StufferState->HeaderPartialMdl ); //no harm in calling this multiple times
  900. FINALIZE_TRACKING( 0x300000 );
  901. } else {
  902. FINALIZE_TRACKING( 0xf00000 );
  903. }
  904. if (!FlagOn(OrdinaryExchangeFlags, SMBPSE_OE_FLAG_MUST_SUCCEED_ALLOCATED_SMBBUF)) {
  905. FINALIZE_TRACE("ready to freepool actualbuffer");
  906. if ( StufferState->ActualBufferBase != NULL ) {
  907. RxFreePool( StufferState->ActualBufferBase );
  908. FINALIZE_TRACKING( 0x5000 );
  909. } else {
  910. FINALIZE_TRACKING( 0xf000 );
  911. }
  912. }
  913. if ( StufferState->RxContext != NULL ) {
  914. //get rid of the reference on the RxContext....if i'm the last guy this will finalize
  915. RxDereferenceAndDeleteRxContext( StufferState->RxContext );//CODE.IMPROVEMENT Capture rxcontext earlier
  916. FINALIZE_TRACKING( 0x600 );
  917. } else {
  918. FINALIZE_TRACKING( 0xf00 );
  919. }
  920. FINALIZE_TRACE("ready to discard exchange");
  921. SmbCeDiscardExchange(OrdinaryExchange);
  922. FINALIZE_TRACKING( 0x2000000 );
  923. FINALIZE_TRACKING( 0x8 );
  924. RxDbgTraceLV(-1, Dbg, 1000, ("MRxSmbFinalizeSmbStufferState --> exit finalstate=%x\n",Tracking.finalstate));
  925. return(TRUE);
  926. } // MRxSmbFinalizeSmbStufferState
  927. NTSTATUS
  928. SmbPseExchangeFinalize_default(
  929. IN OUT PSMB_EXCHANGE pExchange,
  930. OUT BOOLEAN *pPostFinalize
  931. )
  932. /*++
  933. Routine Description:
  934. Arguments:
  935. pExchange - the exchange instance
  936. Return Value:
  937. RXSTATUS - The return status for the operation
  938. --*/
  939. {
  940. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  941. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  942. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  943. UPDATE_OE_HISTORY_WITH_STATUS('ff');
  944. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeFinalize_default: ");
  945. if (OrdinaryExchange->SmbStatus != STATUS_SUCCESS) {
  946. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus;
  947. }
  948. if (OrdinaryExchange->AsyncResumptionRoutine != NULL) {
  949. NTSTATUS PostStatus;
  950. RxDbgTraceLV(0, Dbg, 1000, ("Resume with post-to-async\n"));
  951. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_OE_AWAITING_DISPATCH);
  952. IF_DEBUG {
  953. //fill the workqueue structure with deadbeef....all the better to diagnose
  954. //a failed post
  955. ULONG i;
  956. for (i=0;i+sizeof(ULONG)-1<sizeof(OrdinaryExchange->WorkQueueItem);i+=sizeof(ULONG)) {
  957. //*((PULONG)(((PBYTE)&OrdinaryExchange->WorkQueueItem)+i)) = 0xdeadbeef;
  958. PBYTE BytePtr = ((PBYTE)&OrdinaryExchange->WorkQueueItem)+i;
  959. PULONG UlongPtr = (PULONG)BytePtr;
  960. *UlongPtr = 0xdeadbeef;
  961. }
  962. }
  963. PostStatus = RxPostToWorkerThread(
  964. MRxSmbDeviceObject,
  965. CriticalWorkQueue,
  966. &OrdinaryExchange->WorkQueueItem,
  967. SmbPseContinueOrdinaryExchange,
  968. OrdinaryExchange);
  969. ASSERT(PostStatus == STATUS_SUCCESS);
  970. } else {
  971. RxDbgTraceLV(0, Dbg, 1000, ("sync resume\n"));
  972. KeSetEvent(OrdinaryExchange->pSmbCeSynchronizationEvent, 0, FALSE);
  973. }
  974. *pPostFinalize = FALSE;
  975. return STATUS_SUCCESS;
  976. }
  977. NTSTATUS
  978. SmbPseExchangeSendCallbackHandler_default(
  979. IN PSMB_EXCHANGE pExchange,
  980. IN PMDL pXmitBuffer,
  981. IN NTSTATUS SendCompletionStatus
  982. )
  983. /*++
  984. Routine Description:
  985. This is the send call back indication handling routine for ordinary
  986. exchanges.
  987. Arguments:
  988. pExchange - the exchange instance
  989. pXmitBuffer - pointer to the transmit buffer MDL
  990. BytesSent - number of bytes transmitted
  991. SendCompletionStatus - status for the send
  992. Return Value:
  993. RXSTATUS - The return status for the operation
  994. --*/
  995. {
  996. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  997. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  998. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeSendCallbackHandler_default: ");
  999. UPDATE_OE_HISTORY_WITH_STATUS('cs');
  1000. OrdinaryExchange->SendCompletionStatus = SendCompletionStatus;
  1001. if (!NT_SUCCESS(SendCompletionStatus)) {
  1002. //sometimes we use exchange-status, sometimes exchange->smbstatus
  1003. //set them both
  1004. pExchange->Status = SendCompletionStatus;
  1005. pExchange->SmbStatus = SendCompletionStatus;
  1006. }
  1007. SmbPseDbgRunMdlChain(
  1008. OrdinaryExchange->AssociatedStufferState.HeaderPartialMdl,
  1009. OrdinaryExchange->SaveLengthForDebug,
  1010. OrdinaryExchange,
  1011. "SmbPseExchangeSendCallbackHandler_default");
  1012. return STATUS_SUCCESS;
  1013. } // SmbPseExchangeSendCallbackHandler_default
  1014. NTSTATUS
  1015. SmbPseExchangeStart_default(
  1016. IN PSMB_EXCHANGE pExchange
  1017. )
  1018. /*++
  1019. Routine Description:
  1020. This is the start routine for ordinary exchanges. irght now this is just a simple wrapper.
  1021. Arguments:
  1022. pExchange - the exchange instance NOT an Ordinary Exchange
  1023. Return Value:
  1024. RXSTATUS - The return status for the operation
  1025. --*/
  1026. {
  1027. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1028. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1029. PAGED_CODE();
  1030. return OrdinaryExchange->StartRoutine(
  1031. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange,
  1032. pExchange->RxContext);
  1033. } // SmbPseExchangeStart_default
  1034. NTSTATUS
  1035. SmbPseExchangeCopyDataHandler_default(
  1036. IN PSMB_EXCHANGE pExchange,
  1037. IN PMDL pCopyDataBuffer,
  1038. IN ULONG CopyDataSize
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This is the copy data handling routine for ordinary exchanges.
  1043. Arguments:
  1044. pExchange - the exchange instance
  1045. Return Value:
  1046. RXSTATUS - The return status for the operation
  1047. --*/
  1048. {
  1049. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1050. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1051. SmbPseOEAssertConsistentLinkageFromOE("SmbPseExchangeCopyDataHandler_default: ");
  1052. UPDATE_OE_HISTORY_WITH_STATUS('dd');
  1053. OrdinaryExchange->MessageLength = CopyDataSize;
  1054. pExchange->Status = STATUS_MORE_PROCESSING_REQUIRED;
  1055. return STATUS_SUCCESS;
  1056. } // SmbPseExchangeCopyDataHandler_default
  1057. NTSTATUS
  1058. SmbPseExchangeReceive_default(
  1059. IN struct _SMB_EXCHANGE *pExchange,
  1060. IN ULONG BytesIndicated,
  1061. IN ULONG BytesAvailable,
  1062. OUT ULONG *pBytesTaken,
  1063. IN PSMB_HEADER pSmbHeader,
  1064. OUT PMDL *pDataBufferPointer,
  1065. OUT PULONG pDataSize,
  1066. IN ULONG ReceiveFlags)
  1067. /*++
  1068. Routine Description:
  1069. This is the receive indication handling routine for ordinary exchanges
  1070. Arguments:
  1071. pExchange - the exchange instance
  1072. BytesIndicated - the number of bytes indicated
  1073. Bytes Available - the number of bytes available
  1074. pBytesTaken - the number of bytes consumed
  1075. pSmbHeader - pointer to the data buffer
  1076. pDataBufferPointer - pointer to the buffer Mdl into which the remaining
  1077. data is to be copied.
  1078. pDataSize - the buffer size.
  1079. Return Value:
  1080. RXSTATUS - The return status for the operation
  1081. Notes:
  1082. This routine is called at DPC level directly from the tdi receive event
  1083. handler. BUT, it is also called at task time from SmbPseContinueOrdinaryExchange.
  1084. Often, we cannot complete processing from DPClevel because fileobjects, fcbs,
  1085. srvopens, and fobx are pageable and not locked.
  1086. --*/
  1087. {
  1088. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  1089. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  1090. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1091. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1092. NTSTATUS SmbStatus;
  1093. NTSTATUS Status = STATUS_SUCCESS;
  1094. PGENERIC_ANDX CommandState;
  1095. UCHAR Command;
  1096. ULONG CopyBufferLength;
  1097. BOOLEAN ThisIsAReenter = BooleanFlagOn(OrdinaryExchange->Flags,
  1098. SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED);
  1099. PLOWIO_CONTEXT LowIoContext;
  1100. ULONG ByteCount;
  1101. ULONG Remain;
  1102. PSMB_PSE_OE_READWRITE rw = &OrdinaryExchange->ReadWrite;
  1103. PCHAR startVa;
  1104. SmbPseOEAssertConsistentLinkage("SmbPseExchangeReceive_default: ");
  1105. UPDATE_OE_HISTORY_WITH_STATUS(ThisIsAReenter?'00':'01');
  1106. RxDbgTrace (0, Dbg, ("SmbPseExchangeReceive_default av/ind=%08lx/%08lx\n",
  1107. BytesAvailable,BytesIndicated)
  1108. );
  1109. RxDbgTrace (0, Dbg, (" -->headermdl %08lx\n",StufferState->HeaderMdl));
  1110. ASSERT_ORDINARY_EXCHANGE( OrdinaryExchange );
  1111. CommandState = &OrdinaryExchange->ParseResumeState;
  1112. if ( !ThisIsAReenter ) {
  1113. OrdinaryExchange->BytesIndicatedCopy = BytesIndicated;
  1114. OrdinaryExchange->BytesAvailableCopy = BytesAvailable;
  1115. pExchange->Status = SmbCeParseSmbHeader(
  1116. pExchange,
  1117. pSmbHeader,
  1118. CommandState,
  1119. &OrdinaryExchange->SmbStatus,
  1120. BytesAvailable,
  1121. BytesIndicated,
  1122. pBytesTaken);
  1123. UPDATE_OE_HISTORY_WITH_STATUS('22');
  1124. if ( pExchange->Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1125. goto COPY_FOR_RESUME;
  1126. }
  1127. if ( (pExchange->Status != STATUS_SUCCESS) ||
  1128. ((Command = OrdinaryExchange->ParseResumeState.AndXCommand) == SMB_COM_NO_ANDX_COMMAND) ) {
  1129. goto FINALLY;
  1130. }
  1131. if (Command == SMB_COM_WRITE_ANDX) {
  1132. if (!FlagOn(pSmbHeader->Flags2,SMB_FLAGS2_COMPRESSED)) {
  1133. if (OrdinaryExchange->ReadWrite.CompressedRequestInProgress) {
  1134. OrdinaryExchange->ReadWrite.CompressedReadOrWrite = FALSE;
  1135. }
  1136. }
  1137. }
  1138. SetFlag(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_HEADER_ALREADY_PARSED);
  1139. } else {
  1140. OrdinaryExchange->Status = OrdinaryExchange->SmbStatus;
  1141. RxDbgTrace (0, Dbg, (" -->this is a reenter\n"));
  1142. Command = CommandState->AndXCommand;
  1143. }
  1144. SmbStatus = OrdinaryExchange->SmbStatus;
  1145. if ( (SmbStatus!=RX_MAP_STATUS(SUCCESS)) ) {
  1146. RxDbgTrace (0, Dbg, (" STATUS NOT SUCCESS = %08lx\n", SmbStatus));
  1147. }
  1148. for ( ; Command != SMB_COM_NO_ANDX_COMMAND ; ) {
  1149. PSMBPSE_RECEIVE_MODEL_PARAMETERS ReceiveModelParams = &SmbPseReceiveModelParameters[Command];
  1150. ULONG ReceiveModelParamsFlags;
  1151. UCHAR mappedCommand = Command;
  1152. PCHAR Response = (PCHAR)pSmbHeader + SmbGetUshort(&CommandState->AndXOffset);
  1153. if( Response > (PCHAR)pSmbHeader + BytesAvailable )
  1154. {
  1155. // Invalid Command
  1156. *pBytesTaken = BytesAvailable;
  1157. *pDataBufferPointer = NULL;
  1158. *pDataSize = 0;
  1159. Status = STATUS_SUCCESS;
  1160. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1161. goto FINALLY;
  1162. }
  1163. OrdinaryExchange->LastSmbCommand = Command; //this is used to multiplex in finish routines
  1164. UPDATE_OE_HISTORY_WITH_STATUS('88');
  1165. //
  1166. // Case on the Smb Command Type
  1167. //
  1168. ReceiveModelParamsFlags = ReceiveModelParams->Flags;
  1169. if (ReceiveModelParamsFlags!=0) {
  1170. //map this onto read_andx....which is the arm of the switch that implements the model
  1171. mappedCommand = SMB_COM_READ_ANDX;
  1172. } else {
  1173. //
  1174. // If there's a continuation, then copy&post. it used to always do this.
  1175. // now, we're going to do it unless the command is modeled.
  1176. // the modeling code will take care of correctly deciding to post/nopost.
  1177. //
  1178. if ( (OrdinaryExchange->AsyncResumptionRoutine != NULL) &&
  1179. !ThisIsAReenter) {
  1180. goto COPY_FOR_RESUME;
  1181. }
  1182. }
  1183. switch (mappedCommand) {
  1184. case SMB_COM_READ_ANDX:
  1185. {
  1186. NTSTATUS FinishStatus = RX_MAP_STATUS(SUCCESS);
  1187. NTSTATUS FinalStatus = RX_MAP_STATUS(SUCCESS);
  1188. BOOLEAN ThisIsAnAndX = BooleanFlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_THIS_IS_ANDX);
  1189. BOOLEAN ThisWouldBeMyError = (IM_THE_LAST_GUY || !ThisIsAnAndX);
  1190. RxDbgTrace( 0, Dbg, (" *(ind) %s, smbstatus=%08lx\n",ReceiveModelParams->IndicationString,SmbStatus) );
  1191. IF_DEBUG {
  1192. BOOLEAN BadType = FALSE;
  1193. DbgDoit(BadType = (OrdinaryExchange->OEType < ReceiveModelParams->LowType)
  1194. || (OrdinaryExchange->OEType > ReceiveModelParams->HighType) );
  1195. if (BadType) {
  1196. DbgPrint("Bad OEType....%u,Cmd=%02lx,Exch=%08lx\n",OrdinaryExchange->OEType,Command,OrdinaryExchange);
  1197. ASSERT(!"proceed???");
  1198. }
  1199. }
  1200. // If this is an error and it's an error for this guy of the AndX
  1201. // chain then finishup If it's a warning tho, continue according
  1202. // to the Flags
  1203. if ( NT_ERROR(SmbStatus) && ThisWouldBeMyError ) {
  1204. SmbPseDiscardProtocol( SmbStatus );
  1205. RxDbgTrace( 0, Dbg, ("--->discard1\n"));
  1206. goto FINALLY;
  1207. } else if ( (SmbStatus != RX_MAP_STATUS(SUCCESS)) && ThisWouldBeMyError ) {
  1208. if (!FlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_WARNINGS_OK)) {
  1209. SmbPseDiscardProtocol(SmbStatus);
  1210. RxDbgTrace( 0, Dbg, ("--->discard1\n"));
  1211. goto FINALLY;
  1212. } else {
  1213. FinalStatus = SmbStatus;
  1214. }
  1215. }
  1216. // if there's no nocopy handler then do things the old way
  1217. if (!FlagOn(ReceiveModelParamsFlags,SMBPSE_RMP_NOCOPY_HANDLER)) {
  1218. // TEMPORARY!!!!!!
  1219. // If there's a continuation, then copy&post. it used to always do this. now, we're
  1220. // going to do it unless the command is modeled. the modeling code will take care of
  1221. // correctly deciding to post/nopost.
  1222. //
  1223. if ((OrdinaryExchange->AsyncResumptionRoutine != NULL) &&
  1224. !ThisIsAReenter ) {
  1225. goto COPY_FOR_RESUME;
  1226. }
  1227. //eventually, we'll finish from here but for now copy
  1228. //CODE.IMPROVEMENT.ASHAMED....this is really mandatory.......
  1229. if (RxShouldPostCompletion()) {
  1230. goto COPY_FOR_RESUME;
  1231. }
  1232. if (ReceiveModelParams->ReceiveHandlerToken < SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM){
  1233. PSMBPSE_RECEIVE_HANDLER ReceiveHandler = SmbPseReceiveHandlers[ReceiveModelParams->ReceiveHandlerToken];
  1234. FinishStatus = ReceiveHandler( OrdinaryExchange, Response);
  1235. }
  1236. } else {
  1237. PSMBPSE_NOCOPY_RECEIVE_HANDLER NoCopyReceiveHandler =
  1238. (PSMBPSE_NOCOPY_RECEIVE_HANDLER)(SmbPseReceiveHandlers[ReceiveModelParams->ReceiveHandlerToken]);
  1239. UCHAR Action;
  1240. OrdinaryExchange->NoCopyFinalStatus = FinalStatus;
  1241. Action = NoCopyReceiveHandler(
  1242. OrdinaryExchange,
  1243. BytesIndicated,
  1244. BytesAvailable,
  1245. pBytesTaken,
  1246. pSmbHeader,
  1247. pDataBufferPointer,
  1248. pDataSize,
  1249. #if DBG
  1250. ThisIsAReenter,
  1251. #endif
  1252. Response );
  1253. switch(Action) {
  1254. case SMBPSE_NOCOPYACTION_NORMALFINISH:
  1255. NOTHING;
  1256. break;
  1257. case SMBPSE_NOCOPYACTION_MDLFINISH:
  1258. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1259. //note that whatever does this must be the last command in the
  1260. // packet unless we make continueOE more complicated
  1261. goto FINALLY;
  1262. case SMBPSE_NOCOPYACTION_COPY_FOR_RESUME:
  1263. goto COPY_FOR_RESUME;
  1264. case SMBPSE_NOCOPYACTION_DISCARD:
  1265. *pBytesTaken = BytesAvailable;
  1266. RxDbgTrace( 0, Dbg, ("--->discardX\n"));
  1267. goto FINALLY;
  1268. }
  1269. }
  1270. pExchange->Status = (FinishStatus==RX_MAP_STATUS(SUCCESS))
  1271. ? FinalStatus : FinishStatus;
  1272. if (!ThisIsAnAndX) {
  1273. Response = (PCHAR)&NullGenericAndX;
  1274. }
  1275. }//this corresponds to the top level of the switch
  1276. break;
  1277. default:
  1278. {
  1279. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  1280. RxDbgTrace( 0, Dbg, (" *(ind) Unimplemented cmd=%02lx,wct=%02lx\n",
  1281. Command,*Response) );
  1282. SmbCeTransportDisconnectIndicated(pServerEntry);
  1283. *pBytesTaken = BytesAvailable;
  1284. *pDataBufferPointer = NULL;
  1285. *pDataSize = 0;
  1286. Status = STATUS_SUCCESS;
  1287. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1288. goto FINALLY;
  1289. }
  1290. }
  1291. CommandState = (PGENERIC_ANDX)Response;
  1292. Command = CommandState->AndXCommand;
  1293. }
  1294. //
  1295. // If we get here then we're done.
  1296. // Make everyone happy by taking all the bytes.
  1297. //
  1298. //CODE.IMPROVEMENT: it is not clear to me that this is enough. some servers may send extra bytes
  1299. // on the end.
  1300. //
  1301. *pBytesTaken = BytesAvailable;
  1302. goto FINALLY;
  1303. COPY_FOR_RESUME:
  1304. //CODE.IMPROVEMENT even if we are taking by copy (as opposed to tail-MDL
  1305. // which is how reads should work) we shouldn't copy the whole packet -
  1306. // just the residue. of course, this is really only an issue when we have
  1307. // significant andXing.
  1308. CopyBufferLength = MmGetMdlByteCount(StufferState->HeaderMdl);
  1309. ASSERT( BytesAvailable <= CopyBufferLength );
  1310. if (!FlagOn(ReceiveFlags,TDI_RECEIVE_ENTIRE_MESSAGE) ||
  1311. (BytesAvailable > BytesIndicated) ||
  1312. (BytesAvailable > 127)) {
  1313. RxDbgTrace( 0, Dbg, ("Taking data through MDL\n") );
  1314. // Pass an MDL back in for copying the data
  1315. *pDataBufferPointer = StufferState->HeaderMdl;
  1316. *pDataSize = CopyBufferLength;
  1317. *pBytesTaken = 0;
  1318. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1319. } else {
  1320. // Copy the data and resume the exchange
  1321. ASSERT( BytesAvailable == BytesIndicated );
  1322. RxDbgTrace( 0, Dbg, ("Taking data through copying\n") );
  1323. *pBytesTaken = OrdinaryExchange->MessageLength = BytesAvailable;
  1324. RtlCopyMemory(StufferState->BufferBase,
  1325. pSmbHeader,BytesIndicated);
  1326. ASSERT(SmbGetUlong((PULONG)pSmbHeader->Protocol) == (ULONG)SMB_HEADER_PROTOCOL);
  1327. pExchange->Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED);
  1328. }
  1329. if (ThisIsAReenter) {
  1330. pExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1331. }
  1332. FINALLY:
  1333. OrdinaryExchange->ParseResumeState = *CommandState;
  1334. UPDATE_OE_HISTORY_WITH_STATUS('99');
  1335. return Status;
  1336. } // SmbPseExchangeReceive_default
  1337. #define SmbPseRIStringsBufferSize 500
  1338. CHAR SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferSize];
  1339. ULONG SmbPseRIStringsBufferUsed = 0;
  1340. VOID
  1341. __SmbPseRMTableEntry(
  1342. UCHAR SmbCommand,
  1343. UCHAR Flags,
  1344. SMBPSE_RECEIVE_HANDLER_TOKEN ReceiveHandlerToken,
  1345. PSMBPSE_RECEIVE_HANDLER ReceiveHandler
  1346. #if DBG
  1347. ,
  1348. PBYTE IndicationString,
  1349. SMB_PSE_ORDINARY_EXCHANGE_TYPE LowType,
  1350. SMB_PSE_ORDINARY_EXCHANGE_TYPE HighType
  1351. #endif
  1352. )
  1353. {
  1354. PSMBPSE_RECEIVE_MODEL_PARAMETERS r = &SmbPseReceiveModelParameters[SmbCommand];
  1355. #if DBG
  1356. ULONG ISlength = strlen(IndicationString)+1;
  1357. #endif
  1358. PAGED_CODE();
  1359. r->Flags = SMBPSE_RMP_MODELED | Flags;
  1360. r->ReceiveHandlerToken = (UCHAR)ReceiveHandlerToken;
  1361. if (ReceiveHandlerToken < SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM){
  1362. ASSERT((SmbPseReceiveHandlers[ReceiveHandlerToken] == ReceiveHandler)
  1363. || (SmbPseReceiveHandlers[ReceiveHandlerToken] == NULL));
  1364. SmbPseReceiveHandlers[ReceiveHandlerToken] = ReceiveHandler;
  1365. }
  1366. #if DBG
  1367. r->ReceiveHandler = ReceiveHandler;
  1368. r->LowType = LowType;
  1369. r->HighType = HighType;
  1370. if (SmbPseRIStringsBufferUsed+ISlength<=SmbPseRIStringsBufferSize) {
  1371. r->IndicationString = &SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferUsed];
  1372. RtlCopyMemory(r->IndicationString,IndicationString,ISlength);
  1373. } else {
  1374. if (SmbPseRIStringsBufferUsed<SmbPseRIStringsBufferSize) {
  1375. DbgPrint("Overflowing the indicationstringarray...%s\n",IndicationString);
  1376. ASSERT(!"fix it please");
  1377. }
  1378. r->IndicationString = &SmbPseReceiveIndicationStringsBuffer[SmbPseRIStringsBufferUsed];
  1379. }
  1380. SmbPseRIStringsBufferUsed += ISlength;
  1381. #endif
  1382. }
  1383. #if DBG
  1384. #define SmbPseRMTableEntry(__smbcommand,b,c,token,__rcv,flags) \
  1385. __SmbPseRMTableEntry(SMB_COM_##__smbcommand,flags,token,__rcv \
  1386. ,#__smbcommand,b,c)
  1387. #else
  1388. #define SmbPseRMTableEntry(__smbcommand,b,c,token,__rcv,flags) \
  1389. __SmbPseRMTableEntry(SMB_COM_##__smbcommand,flags,token,__rcv \
  1390. )
  1391. #endif
  1392. VOID
  1393. SmbPseInitializeTables(
  1394. void
  1395. )
  1396. /*++
  1397. Routine Description:
  1398. This routine initializes tables that are used at various points by the
  1399. smbpse mechanisms. The must succeed structure(s) is(are) also initialized.
  1400. Arguments:
  1401. none
  1402. Return Value:
  1403. none
  1404. --*/
  1405. {
  1406. ULONG i;
  1407. PAGED_CODE();
  1408. for (i=0;i<256;i++) {
  1409. SmbPseReceiveModelParameters[i].Flags = 0;
  1410. SmbPseReceiveModelParameters[i].ReceiveHandlerToken =
  1411. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM;
  1412. }
  1413. for (i=0;i<SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM;i++) {
  1414. SmbPseReceiveHandlers[i] = NULL;
  1415. }
  1416. SmbPseRMTableEntry(
  1417. READ_ANDX,
  1418. SMBPSE_OETYPE_READ,
  1419. SMBPSE_OETYPE_READ,
  1420. SMBPSE_RECEIVE_HANDLER_TOKEN_READ_ANDX_HANDLER,
  1421. MRxSmbReceiveHandler_Read_NoCopy,
  1422. SMBPSE_RMP_THIS_IS_ANDX|SMBPSE_RMP_WARNINGS_OK|SMBPSE_RMP_NOCOPY_HANDLER);
  1423. SmbPseRMTableEntry(
  1424. READ,
  1425. SMBPSE_OETYPE_READ,
  1426. SMBPSE_OETYPE_READ,
  1427. SMBPSE_RECEIVE_HANDLER_TOKEN_READ_ANDX_HANDLER,
  1428. MRxSmbReceiveHandler_Read_NoCopy,
  1429. SMBPSE_RMP_WARNINGS_OK|SMBPSE_RMP_NOCOPY_HANDLER);
  1430. SmbPseRMTableEntry(
  1431. WRITE_ANDX,
  1432. SMBPSE_OETYPE_WRITE,
  1433. SMBPSE_OETYPE_EXTEND_WRITE,
  1434. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_ANDX_HANDLER,
  1435. MRxSmbReceiveHandler_WriteAndX,
  1436. SMBPSE_RMP_THIS_IS_ANDX);
  1437. SmbPseRMTableEntry(
  1438. WRITE,
  1439. SMBPSE_OETYPE_WRITE,
  1440. SMBPSE_OETYPE_CORETRUNCATE,
  1441. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_HANDLER,
  1442. MRxSmbReceiveHandler_CoreWrite,
  1443. 0);
  1444. SmbPseRMTableEntry(
  1445. WRITE_PRINT_FILE,
  1446. SMBPSE_OETYPE_WRITE,
  1447. SMBPSE_OETYPE_WRITE,
  1448. SMBPSE_RECEIVE_HANDLER_TOKEN_WRITE_PRINTFILE_HANDLER,
  1449. MRxSmbReceiveHandler_WritePrintFile,
  1450. 0);
  1451. SmbPseRMTableEntry(
  1452. LOCKING_ANDX,
  1453. SMBPSE_OETYPE_LOCKS,
  1454. SMBPSE_OETYPE_ASSERTBUFFEREDLOCKS,
  1455. SMBPSE_RECEIVE_HANDLER_TOKEN_LOCKING_ANDX_HANDLER,
  1456. MRxSmbReceiveHandler_LockingAndX,
  1457. SMBPSE_RMP_THIS_IS_ANDX);
  1458. SmbPseRMTableEntry(
  1459. UNLOCK_BYTE_RANGE,
  1460. SMBPSE_OETYPE_LOCKS,
  1461. SMBPSE_OETYPE_LOCKS,
  1462. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1463. NULL,
  1464. 0);
  1465. SmbPseRMTableEntry(
  1466. LOCK_BYTE_RANGE,
  1467. SMBPSE_OETYPE_LOCKS,
  1468. SMBPSE_OETYPE_LOCKS,
  1469. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1470. NULL,
  1471. 0);
  1472. SmbPseRMTableEntry(
  1473. OPEN_PRINT_FILE,
  1474. SMBPSE_OETYPE_CREATEPRINTFILE,
  1475. SMBPSE_OETYPE_CREATEPRINTFILE,
  1476. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_PRINTFILE_HANDLER,
  1477. MRxSmbReceiveHandler_OpenPrintFile,
  1478. 0);
  1479. SmbPseRMTableEntry(
  1480. QUERY_INFORMATION2,
  1481. SMBPSE_OETYPE_GFA,
  1482. SMBPSE_OETYPE_GFA,
  1483. SMBPSE_RECEIVE_HANDLER_TOKEN_GFA_HANDLER,
  1484. MRxSmbReceiveHandler_GetFileAttributes,
  1485. 0);
  1486. SmbPseRMTableEntry(
  1487. CLOSE_PRINT_FILE,
  1488. SMBPSE_OETYPE_CLOSE,
  1489. SMBPSE_OETYPE_CLOSE,
  1490. SMBPSE_RECEIVE_HANDLER_TOKEN_CLOSE_HANDLER,
  1491. MRxSmbReceiveHandler_Close,
  1492. 0);
  1493. SmbPseRMTableEntry(
  1494. NT_CREATE_ANDX,
  1495. SMBPSE_OETYPE_LATENT_HEADEROPS,
  1496. SMBPSE_OETYPE_CREATE,
  1497. SMBPSE_RECEIVE_HANDLER_TOKEN_NTCREATE_ANDX_HANDLER,
  1498. MRxSmbReceiveHandler_NTCreateAndX,
  1499. SMBPSE_RMP_THIS_IS_ANDX);
  1500. SmbPseRMTableEntry(
  1501. OPEN_ANDX,
  1502. SMBPSE_OETYPE_LATENT_HEADEROPS,
  1503. SMBPSE_OETYPE_CREATE,
  1504. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_ANDX_HANDLER,
  1505. MRxSmbReceiveHandler_OpenAndX,
  1506. SMBPSE_RMP_THIS_IS_ANDX);
  1507. SmbPseRMTableEntry(
  1508. OPEN,
  1509. SMBPSE_OETYPE_COREOPEN,
  1510. SMBPSE_OETYPE_COREOPEN,
  1511. SMBPSE_RECEIVE_HANDLER_TOKEN_OPEN_HANDLER,
  1512. MRxSmbReceiveHandler_CoreOpen,
  1513. 0);
  1514. SmbPseRMTableEntry(
  1515. CREATE,
  1516. SMBPSE_OETYPE_CORECREATE,
  1517. SMBPSE_OETYPE_CORECREATE,
  1518. SMBPSE_RECEIVE_HANDLER_TOKEN_CREATE_HANDLER,
  1519. MRxSmbReceiveHandler_CoreCreate,
  1520. 0);
  1521. SmbPseRMTableEntry(
  1522. CREATE_NEW,
  1523. SMBPSE_OETYPE_CORECREATE,
  1524. SMBPSE_OETYPE_CORECREATE,
  1525. SMBPSE_RECEIVE_HANDLER_TOKEN_CREATE_HANDLER,
  1526. MRxSmbReceiveHandler_CoreCreate,
  1527. 0);
  1528. SmbPseRMTableEntry(
  1529. CLOSE,
  1530. SMBPSE_OETYPE_CLOSE,
  1531. SMBPSE_OETYPE_CLOSEAFTERCORECREATE,
  1532. SMBPSE_RECEIVE_HANDLER_TOKEN_CLOSE_HANDLER,
  1533. MRxSmbReceiveHandler_Close,
  1534. 0);
  1535. SmbPseRMTableEntry(
  1536. QUERY_INFORMATION,
  1537. 0,
  1538. SMBPSE_OETYPE_MAXIMUM,
  1539. SMBPSE_RECEIVE_HANDLER_TOKEN_GFA_HANDLER,
  1540. MRxSmbReceiveHandler_GetFileAttributes,
  1541. 0);
  1542. SmbPseRMTableEntry(
  1543. TRANSACTION2,
  1544. SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO,
  1545. SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO,
  1546. SMBPSE_RECEIVE_HANDLER_TOKEN_TRANS2_ANDX_HANDLER,
  1547. MRxSmbReceiveHandler_Transact2,
  1548. 0);
  1549. SmbPseRMTableEntry(
  1550. TRANSACTION2_SECONDARY,
  1551. SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO,
  1552. SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO,
  1553. SMBPSE_RECEIVE_HANDLER_TOKEN_TRANS2_ANDX_HANDLER,
  1554. MRxSmbReceiveHandler_Transact2,
  1555. 0);
  1556. SmbPseRMTableEntry(
  1557. SEARCH,
  1558. SMBPSE_OETYPE_COREQUERYLABEL,
  1559. SMBPSE_OETYPE_CORESEARCHFORCHECKEMPTY,
  1560. SMBPSE_RECEIVE_HANDLER_TOKEN_SEARCH_HANDLER,
  1561. MRxSmbReceiveHandler_Search,
  1562. 0);
  1563. SmbPseRMTableEntry(
  1564. QUERY_INFORMATION_DISK,
  1565. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES,
  1566. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES,
  1567. SMBPSE_RECEIVE_HANDLER_TOKEN_QUERYDISKINFO_HANDLER,
  1568. MRxSmbReceiveHandler_QueryDiskInfo,
  1569. 0);
  1570. SmbPseRMTableEntry(
  1571. DELETE,
  1572. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1573. SMBPSE_OETYPE_DELETE_FOR_RENAME,
  1574. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1575. NULL,
  1576. 0);
  1577. SmbPseRMTableEntry(
  1578. DELETE_DIRECTORY,
  1579. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1580. SMBPSE_OETYPE_DELETEFORSUPERSEDEORCLOSE,
  1581. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1582. NULL,
  1583. 0);
  1584. SmbPseRMTableEntry(
  1585. CHECK_DIRECTORY,
  1586. SMBPSE_OETYPE_CORECHECKDIRECTORY,
  1587. SMBPSE_OETYPE_CORECHECKDIRECTORY,
  1588. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1589. NULL,
  1590. 0);
  1591. SmbPseRMTableEntry(
  1592. SET_INFORMATION,
  1593. SMBPSE_OETYPE_SFA,
  1594. SMBPSE_OETYPE_SFA,
  1595. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1596. NULL,
  1597. 0);
  1598. SmbPseRMTableEntry(
  1599. SET_INFORMATION2,
  1600. SMBPSE_OETYPE_SFA2,
  1601. SMBPSE_OETYPE_SFA2,
  1602. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1603. NULL,
  1604. 0);
  1605. SmbPseRMTableEntry(
  1606. CREATE_DIRECTORY,
  1607. SMBPSE_OETYPE_CORECREATEDIRECTORY,
  1608. SMBPSE_OETYPE_CORECREATEDIRECTORY,
  1609. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1610. NULL,
  1611. 0);
  1612. SmbPseRMTableEntry(
  1613. FLUSH,
  1614. SMBPSE_OETYPE_FLUSH,
  1615. SMBPSE_OETYPE_FLUSH,
  1616. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1617. NULL,
  1618. 0);
  1619. SmbPseRMTableEntry(
  1620. FIND_CLOSE2,
  1621. SMBPSE_OETYPE_FINDCLOSE,
  1622. SMBPSE_OETYPE_FINDCLOSE,
  1623. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1624. NULL,
  1625. 0);
  1626. SmbPseRMTableEntry(
  1627. RENAME,
  1628. SMBPSE_OETYPE_RENAME,
  1629. SMBPSE_OETYPE_RENAME,
  1630. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1631. NULL,
  1632. 0);
  1633. SmbPseRMTableEntry(
  1634. NT_RENAME,
  1635. SMBPSE_OETYPE_RENAME,
  1636. SMBPSE_OETYPE_RENAME,
  1637. SMBPSE_RECEIVE_HANDLER_TOKEN_MAXIMUM+1,
  1638. NULL,
  1639. 0);
  1640. SmbPseRMTableEntry(
  1641. IOCTL,
  1642. SMBPSE_OETYPE_IOCTL,
  1643. SMBPSE_OETYPE_IOCTL,
  1644. SMBPSE_RECEIVE_HANDLER_TOKEN_IOCTL_HANDLER,
  1645. MRxSmbReceiveHandler_Ioctl,
  1646. 0);
  1647. }
  1648. #ifdef WIN9X
  1649. NTSTATUS
  1650. MRxSmbQueryDosVolumeInformation(
  1651. IN OUT PRX_CONTEXT RxContext,
  1652. IN OUT PVOID pBuffer,
  1653. IN OUT PULONG pBufferLength
  1654. )
  1655. /*++
  1656. Routine Description:
  1657. This routine queries the volume information
  1658. Arguments:
  1659. pRxContext - the RDBSS context
  1660. FsInformationClass - the kind of Fs information desired.
  1661. pBuffer - the buffer for copying the information
  1662. pBufferLength - the buffer length ( set to buffer length on input and set
  1663. to the remaining length on output)
  1664. Return Value:
  1665. RXSTATUS - The return status for the operation
  1666. --*/
  1667. {
  1668. PAGED_CODE();
  1669. TURN_BACK_ASYNCHRONOUS_OPERATIONS();
  1670. return MRxSmbVolumeInformation(RxContext, 0, pBuffer, pBufferLength);
  1671. }
  1672. #endif
  1673. #ifndef RX_NO_DBGFIELD_HLPRS
  1674. #define DECLARE_FIELD_HLPR(x) ULONG SmbPseOeField_##x = FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,x);
  1675. #define DECLARE_FIELD_HLPR2(x,y) ULONG SmbPseOeField_##x##y = FIELD_OFFSET(SMB_PSE_ORDINARY_EXCHANGE,x.y);
  1676. DECLARE_FIELD_HLPR(RxContext);
  1677. DECLARE_FIELD_HLPR(ReferenceCount);
  1678. DECLARE_FIELD_HLPR(AssociatedStufferState);
  1679. DECLARE_FIELD_HLPR(Flags);
  1680. DECLARE_FIELD_HLPR(ReadWrite);
  1681. DECLARE_FIELD_HLPR(Transact2);
  1682. DECLARE_FIELD_HLPR2(Create,FileInfo);
  1683. DECLARE_FIELD_HLPR2(Create,smbSrvOpen);
  1684. DECLARE_FIELD_HLPR2(ReadWrite,RemainingByteCount);
  1685. DECLARE_FIELD_HLPR2(Info,FileInfo);
  1686. DECLARE_FIELD_HLPR2(Info,Buffer);
  1687. #endif
  1688.