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.

2065 lines
65 KiB

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