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.

1028 lines
42 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. Stuffer.c
  5. Abstract:
  6. This module implements the SMBstuffer formating primitives. the following controlstring
  7. characters are defined for the stuffer: (** means nyi...**d means downlevel part not implemented)
  8. 0 placeholder for the wct
  9. 1 pad to word boundary
  10. X placeholderfor&X
  11. W,w format a word from the next parameter
  12. D,d format the next parameter as a Dword
  13. Y,y format the next parameter as a byte
  14. L,l the next parameter is a PLARGE_INTEGER; format it in
  15. M,m format a zero byte
  16. ** 2 the next parameter points to a tagged dialect ASCIZI string to be copied in
  17. ** 3 the next parameter points to a tagged devicename ASCIIZ string
  18. 4 the next parameter is either 04-tagged ASCIIZ or UNICODEZ as determined by flags2
  19. > the next parameters is ASCIIZ or UNICODEZ as determined by flags2; it is to be appended
  20. to the previous 04-tagged item by backing up over the previous null.
  21. A,a the next parameter is an ASCIIZ string
  22. U,u the next parameter is a UNICODEZ string
  23. V,v the next parameter is a UNICODEnoZ string
  24. z the next parameter is a PUNICODE_STRING to be stringed as ASCIZI
  25. or UNICODEZ as determined by flags2
  26. N,n the next parameter is a PNET_ROOT whose name is to be stringed as ASCIIZ
  27. or UNICODEZ as determined by flags2
  28. R,r the next 2 parameters are a PBYTE* and a size; reserve the region and store the pointer
  29. Q,q the current position is the data offset WORD...remember it
  30. 5 the current position is the start of the data; fill in the data pointer
  31. P,p the current position is the parameter offset WORD...remember it
  32. 6 the current position is the start of the parameters; fill in the param pointer
  33. B,b the current position is the Bcc WORD...remember it; also, fill in wct
  34. s the next parameter has the alignment information....pad accordingly
  35. S pad to DWORD
  36. c the next 2 parameters are count/addr...copy in the data.
  37. ! End of this protocol; fill in the bcc field
  38. ? next parameter is BOOLEAN_ULONG; 0=>immediate return
  39. . NOOP
  40. For controls with a upper/lowercase pair, the uppercase version indicates that a position tag
  41. is supplied in the checked version.
  42. Author:
  43. Joe Linn 3-3-95
  44. Revision History:
  45. --*/
  46. #include "precomp.h"
  47. #pragma hdrstop
  48. #include <stdio.h>
  49. #include <stdarg.h>
  50. #ifdef ALLOC_PRAGMA
  51. #pragma alloc_text(PAGE, SmbStuffWrapRtlAssert)
  52. #pragma alloc_text(PAGE, SmbMrxInitializeStufferFacilities)
  53. #pragma alloc_text(PAGE, SmbMrxFinalizeStufferFacilities)
  54. #pragma alloc_text(PAGE, MRxSmbSetInitialSMB)
  55. #pragma alloc_text(PAGE, MRxSmbStartSMBCommand)
  56. #pragma alloc_text(PAGE, MrxSMBWillThisFit)
  57. #pragma alloc_text(PAGE, MRxSmbStuffSMB)
  58. #pragma alloc_text(PAGE, MRxSmbStuffAppendRawData)
  59. #pragma alloc_text(PAGE, MRxSmbStuffAppendSmbData)
  60. #pragma alloc_text(PAGE, MRxSmbStuffSetByteCount)
  61. #endif
  62. //
  63. // The local debug trace level
  64. //
  65. #define Dbg (DEBUG_TRACE_ALWAYS)
  66. #define MRXSMB_INITIAL_WCT (0xcc)
  67. #define MRXSMB_INITIAL_BCC (0xface)
  68. #define MRXSMB_INITIAL_DATAOFFSET (0xd0ff)
  69. #define MRXSMB_INITIAL_PARAMOFFSET (0xb0ff)
  70. #define MRXSMB_INITIAL_ANDX (0xdede00ff)
  71. #if 0
  72. //this is old...........
  73. #if DBG
  74. // a little presto-changeo to get assert messages in user mode
  75. // the key is that MRxSmbRxImports->pRxNetNameTable will not be NULL...
  76. // it will point to the netnametable. this
  77. // seems like a small enough price to pay on the way to an rtl assert!
  78. VOID
  79. SmbStuffWrapRtlAssert(
  80. IN PVOID FailedAssertion,
  81. IN PVOID FileName,
  82. IN ULONG LineNumber,
  83. IN PCHAR Message
  84. )
  85. {
  86. char STARS[] = "**************************************";
  87. PAGED_CODE();
  88. if (MRxSmbRxImports->pRxNetNameTable == NULL){
  89. // do our own thing
  90. RxDbgTrace(0,Dbg,("%s\n%s\n",STARS,STARS));
  91. RxDbgTrace (0,Dbg,("Failed Assertion %s\n",FailedAssertion));
  92. RxDbgTrace(0,Dbg,("%s at line %lu\n",FileName,LineNumber));
  93. if (Message) {
  94. RxDbgTrace (0,Dbg,("%s\n",Message));
  95. }
  96. RxDbgTrace(0,Dbg,("%s\n%s\n",STARS,STARS));
  97. } else RtlAssert(FailedAssertion,FileName,LineNumber,Message);
  98. }
  99. #ifdef RtlAssert
  100. #undef RtlAssert
  101. #endif //ifdef RtlAssert
  102. #define RtlAssert SmbStuffWrapRtlAssert
  103. #endif
  104. #endif //if 0
  105. NTSTATUS
  106. SmbMrxInitializeStufferFacilities(
  107. void
  108. )
  109. /*++
  110. Routine Description:
  111. This routine initializes things for the SMB minirdr. we will allocate enough stuff
  112. to get us going. right now....we do nothing.
  113. Arguments:
  114. Return Value:
  115. RXSTATUS - The return status for the operation
  116. --*/
  117. {
  118. PAGED_CODE();
  119. return(RX_MAP_STATUS(SUCCESS));
  120. }
  121. NTSTATUS
  122. SmbMrxFinalizeStufferFacilities(
  123. void
  124. )
  125. /*++
  126. Routine Description:
  127. This routine finalizes things for the SMB minirdr. we give back everything that
  128. we have allocated. right now....we do nothing.
  129. Arguments:
  130. Return Value:
  131. RXSTATUS - The return status for the operation
  132. --*/
  133. {
  134. PAGED_CODE();
  135. return(RX_MAP_STATUS(SUCCESS));
  136. }
  137. #if DBG
  138. #define BUILD_HEADER_ROUTINE BuildHeaderRoutine
  139. typedef
  140. NTSTATUS
  141. (NTAPI *PMRXSMB_BUILD_HEADER_ROUTINE) (
  142. PSMB_EXCHANGE pExchange,
  143. PVOID pBuffer,
  144. ULONG BufferLength,
  145. PULONG pBufferConsumed,
  146. PUCHAR pLastCommandInHeader,
  147. PUCHAR *pNextCommandPtr
  148. );
  149. #else
  150. #define BUILD_HEADER_ROUTINE SmbCeBuildSmbHeader
  151. #endif
  152. NTSTATUS
  153. MRxSmbSetInitialSMB (
  154. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState
  155. STUFFERTRACE_CONTROLPOINT_ARGS
  156. )
  157. {
  158. NTSTATUS Status;
  159. PNT_SMB_HEADER NtSmbHeader;
  160. ULONG BufferConsumed;
  161. PBYTE ScanPosition;
  162. PUCHAR pCommand;
  163. #if DBG
  164. PMRXSMB_BUILD_HEADER_ROUTINE BUILD_HEADER_ROUTINE = SmbCeBuildSmbHeader;
  165. #endif //if DBG
  166. PAGED_CODE();
  167. ASSERT ( StufferState != NULL ); //CODE.IMPROVEMENT shouldn't we have a nodetype??
  168. ASSERT ( sizeof(NT_SMB_HEADER) == sizeof(SMB_HEADER) );
  169. //RxDbgTrace(0, Dbg, ("MrxSMBSetInitialSMB base=%08lx,limit=%08lx\n",
  170. // StufferState->BufferBase,StufferState->BufferLimit));
  171. ASSERT ( (StufferState->BufferLimit - StufferState->BufferBase) > sizeof(SMB_HEADER));
  172. NtSmbHeader = (PNT_SMB_HEADER)(StufferState->BufferBase);
  173. RtlZeroMemory(NtSmbHeader,sizeof(NT_SMB_HEADER));
  174. //this stuff is reinitialized
  175. StufferState->DataMdl = NULL; //note that this is not finalized or anything
  176. StufferState->DataSize = 0;
  177. StufferState->CurrentWct = NULL;
  178. StufferState->PreviousCommand = SMB_COM_NO_ANDX_COMMAND;
  179. StufferState->CurrentCommand = SMB_COM_NO_ANDX_COMMAND;
  180. StufferState->FlagsCopy = 0;
  181. StufferState->Flags2Copy = 0;
  182. StufferState->CurrentPosition = ((PBYTE)NtSmbHeader);
  183. RxDbgTraceDoit(
  184. StufferState->ControlPoint = ControlPoint;
  185. StufferState->PrintCLoop = FALSE;
  186. StufferState->PrintFLoop = FALSE;
  187. while (EnablePrints) {
  188. ULONG c = EnablePrints & 0xff;
  189. EnablePrints >>= 8;
  190. if (c=='C') StufferState->PrintCLoop = TRUE;
  191. if (c=='F') StufferState->PrintFLoop = TRUE;
  192. if (c=='X') BUILD_HEADER_ROUTINE = MRxSmbBuildSmbHeaderTestSurrogate;
  193. }
  194. )
  195. Status = BUILD_HEADER_ROUTINE(
  196. StufferState->Exchange,
  197. NtSmbHeader,
  198. (ULONG)(StufferState->BufferLimit - StufferState->BufferBase),
  199. &BufferConsumed,
  200. &StufferState->PreviousCommand,
  201. &pCommand);
  202. if (Status!=RX_MAP_STATUS(SUCCESS)) {
  203. RxDbgTrace(0, Dbg, ("MrxSMBSetInitialSMB buildhdr failure st=%08lx\n",Status));
  204. RxLog(("BuildHdr failed %lx %lx",StufferState->Exchange,Status));
  205. SmbLog(LOG,
  206. MRxSmbSetInitialSMB,
  207. LOGPTR(StufferState->Exchange)
  208. LOGULONG(Status));
  209. return Status;
  210. }
  211. //copy the flags
  212. StufferState->FlagsCopy = NtSmbHeader->Flags;
  213. StufferState->Flags2Copy = SmbGetAlignedUshort(&NtSmbHeader->Flags2);
  214. if (StufferState->Exchange->Type == ORDINARY_EXCHANGE) {
  215. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)StufferState->Exchange;
  216. if (BooleanFlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG)) {
  217. StufferState->Flags2Copy |= SMB_FLAGS2_DFS;
  218. SmbPutUshort(&NtSmbHeader->Flags2,(USHORT)StufferState->Flags2Copy);
  219. }
  220. }
  221. StufferState->CurrentPosition += BufferConsumed;
  222. if (BufferConsumed > sizeof(SMB_HEADER)) {
  223. if (pCommand != NULL) {
  224. *pCommand = SMB_COM_NO_ANDX_COMMAND;
  225. }
  226. StufferState->CurrentWct = StufferState->CurrentPosition;
  227. }
  228. return Status;
  229. }
  230. #define RETURN_A_START_PROBLEM(xxyy) {\
  231. RxDbgTrace(0,Dbg,("MRxSmbStartSMBCommand gotta problem= %lu\n",xxyy)); \
  232. StufferState->SpecificProblem = xxyy; \
  233. return(RX_MAP_STATUS(INVALID_PARAMETER)); \
  234. }
  235. NTSTATUS
  236. MRxSmbStartSMBCommand (
  237. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  238. IN INITIAL_SMBBUG_DISPOSITION InitialSMBDisposition,
  239. IN UCHAR Command, //joejoe this next four params could come from a table...2offset and you're smaller
  240. IN ULONG MaximumBufferUsed,
  241. IN ULONG MaximumSize,
  242. IN ULONG InitialAlignment,
  243. IN ULONG MaximumResponseHeader,
  244. IN UCHAR Flags,
  245. IN UCHAR FlagsMask,
  246. IN USHORT Flags2,
  247. IN USHORT Flags2Mask
  248. STUFFERTRACE_CONTROLPOINT_ARGS
  249. )
  250. /*++
  251. Routine Description:
  252. The routine checks to see if the condition is stable. If not, it
  253. goes into a wait loop alternately getting the resource and then
  254. waiting on the event.
  255. Arguments:
  256. joejoe review this
  257. StufferState - the header buffer being used
  258. InitialSMBDisposition tells when/if to reinit the stuffer state
  259. Command - the smb command being set up
  260. MaximumBufferUsed - the amount of the header buffer that will be used (as opposed to the data)
  261. this has to be conjured up in advance. if you're not willing to do this, then
  262. just push out the current smb. this value should include any data pads!
  263. MaximumSize - the size of the data. this is to keep from overrunning the srv's smbbuf
  264. InitialAlignment - a compound argument (i.e. you get it from a constant) the top half
  265. tells the alignment unit and the bottom gives the spacing within
  266. MaximumResponseHeader - how much of the srv's response buffer this will use up
  267. Flags - the required flags settings
  268. FlagsMask - which bits of the flags are important
  269. Flags2 - the required flags2 settings
  270. Flags2Mask - which flags2 bits are important
  271. Return Value:
  272. none.
  273. --*/
  274. {
  275. UCHAR NewFlags;
  276. USHORT NewFlags2;
  277. PBYTE *CurrentPosition = &(StufferState->CurrentPosition);
  278. PNT_SMB_HEADER NtSmbHeader = (PNT_SMB_HEADER)(StufferState->BufferBase);
  279. ULONG AlignmentUnit = InitialAlignment >> 16;
  280. ULONG StufferStateRequirement = MaximumBufferUsed + AlignmentUnit;
  281. #if DBG
  282. PBYTE OriginalPosition = *CurrentPosition;
  283. #endif
  284. PAGED_CODE();
  285. if (StufferState->DataSize) {
  286. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  287. return(RX_MAP_STATUS(INVALID_PARAMETER));
  288. }
  289. if ((InitialSMBDisposition==SetInitialSMB_yyUnconditionally)
  290. || ((InitialSMBDisposition==SetInitialSMB_ForReuse)&&(StufferState->Started))) {
  291. MRxSmbSetInitialSMB( StufferState STUFFERTRACE_NOPREFIX(ControlPoint,EnablePrints) );
  292. }
  293. StufferState->Started = TRUE;
  294. //joejoe temporary hack
  295. switch (StufferState->CurrentCommand) {
  296. case SMB_COM_LOCKING_ANDX:
  297. case SMB_COM_OPEN_ANDX:
  298. case SMB_COM_READ_ANDX:
  299. case SMB_COM_WRITE_ANDX:
  300. case SMB_COM_SESSION_SETUP_ANDX:
  301. //case SMB_COM_LOGOFF_ANDX:
  302. case SMB_COM_TREE_CONNECT_ANDX:
  303. case SMB_COM_NT_CREATE_ANDX:
  304. case SMB_COM_NO_ANDX_COMMAND:
  305. break;
  306. default:
  307. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  308. return(RX_MAP_STATUS(INVALID_PARAMETER));
  309. }
  310. if (*CurrentPosition+StufferStateRequirement >= StufferState->BufferLimit ) {
  311. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  312. return(RX_MAP_STATUS(INVALID_PARAMETER));
  313. }
  314. if (StufferState->RxContext) {
  315. PRX_CONTEXT RxContext = StufferState->RxContext;
  316. PMRX_SRV_CALL SrvCall;
  317. ULONG CurrentOffset;
  318. if (RxContext->MajorFunction != IRP_MJ_CREATE) {
  319. SrvCall = RxContext->pFcb->pNetRoot->pSrvCall; //joejoe cache it?
  320. } else {
  321. SrvCall = RxContext->Create.pSrvCall;
  322. }
  323. ASSERT(SrvCall);
  324. CurrentOffset = (ULONG)(*CurrentPosition - StufferState->BufferBase);
  325. if (CurrentOffset+StufferStateRequirement+MaximumSize
  326. > GetServerMaximumBufferSize(SrvCall) ) {
  327. StufferState->SpecificProblem = xSMBbufSTATUS_SERVER_OVERRUN;
  328. return(RX_MAP_STATUS(INVALID_PARAMETER));
  329. }
  330. }
  331. NewFlags = Flags | (UCHAR)(StufferState->FlagsCopy);
  332. NewFlags2 = Flags2 | (USHORT)(StufferState->Flags2Copy);
  333. if ( ((NewFlags&FlagsMask)!=Flags) ||
  334. ((NewFlags2&Flags2Mask)!=Flags2) ) {
  335. StufferState->SpecificProblem = xSMBbufSTATUS_FLAGS_CONFLICT;
  336. return(RX_MAP_STATUS(INVALID_PARAMETER));
  337. }
  338. StufferState->FlagsCopy = NtSmbHeader->Flags = NewFlags;
  339. StufferState->Flags2Copy = NewFlags2;
  340. SmbPutAlignedUshort(&NtSmbHeader->Flags2, NewFlags2);
  341. if (!StufferState->CurrentWct) {
  342. NtSmbHeader->Command = Command;
  343. } else {
  344. PGENERIC_ANDX GenericAndX = (PGENERIC_ANDX)StufferState->CurrentWct;
  345. if (AlignmentUnit) {
  346. ULONG AlignmentMask = (AlignmentUnit-1);
  347. ULONG AlignmentResidue = InitialAlignment&AlignmentMask;
  348. RxDbgTrace(0, Dbg, ("Aligning start of smb cp&m,m,r=%08lx %08lx %08lx\n",
  349. ((ULONG)(ULONG_PTR)(*CurrentPosition))&AlignmentMask,
  350. AlignmentMask, AlignmentResidue)
  351. );
  352. for (;(((ULONG_PTR)(*CurrentPosition))&AlignmentMask)!=AlignmentResidue;) {
  353. **CurrentPosition = ',';
  354. *CurrentPosition += 1;
  355. }
  356. }
  357. GenericAndX->AndXCommand = Command;
  358. GenericAndX->AndXReserved = 0;
  359. SmbPutUshort (&GenericAndX->AndXOffset,
  360. (USHORT)(*CurrentPosition - StufferState->BufferBase));
  361. }
  362. StufferState->CurrentWct = *CurrentPosition;
  363. StufferState->CurrentCommand = Command;
  364. StufferState->CurrentDataOffset = 0;
  365. return RX_MAP_STATUS(SUCCESS);
  366. }
  367. BOOLEAN
  368. MrxSMBWillThisFit(
  369. IN PSMBSTUFFER_BUFFER_STATE StufferState,
  370. IN ULONG AlignmentUnit,
  371. IN ULONG DataSize
  372. )
  373. {
  374. //joejoe actually some stuff will fit that this says no...........
  375. return(StufferState->CurrentPosition+AlignmentUnit+DataSize<StufferState->BufferLimit);
  376. }
  377. #if RDBSSTRACE
  378. #define StufferFLoopTrace(Z) { if (StufferState->PrintFLoop) {RxDbgTraceLV__norx(0,StufferState->ControlPoint,900,Z);}}
  379. #define StufferCLoopTrace(Z) { if (StufferState->PrintCLoop) {RxDbgTraceLV__norx(0,StufferState->ControlPoint,800,Z);}}
  380. #else // DBG
  381. #define StufferFLoopTrace(Z)
  382. #define StufferCLoopTrace(Z)
  383. #endif // DBG
  384. NTSTATUS
  385. MRxSmbStuffSMB (
  386. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  387. ...
  388. )
  389. {
  390. va_list AP;
  391. PBYTE BufferBase = (StufferState->BufferBase);
  392. PBYTE *CurrentPosition = &(StufferState->CurrentPosition);
  393. PBYTE *CurrentWct = &(StufferState->CurrentWct);
  394. PBYTE *CurrentBcc = &(StufferState->CurrentBcc);
  395. PBYTE *CurrentDataOffset = &(StufferState->CurrentDataOffset);
  396. PBYTE *CurrentParamOffset = &(StufferState->CurrentParamOffset);
  397. SMB_STUFFER_CONTROLS CurrentStufferControl = STUFFER_CTL_NORMAL;
  398. PSMB_HEADER SmbHeader = (PSMB_HEADER)BufferBase;
  399. PSZ CurrentFormatString = NULL;
  400. ULONG arg;
  401. UCHAR WordCount;
  402. USHORT ByteCount;
  403. //joejoe change this to zero later.....apparently some servers croak on nonzero pad
  404. #define PADBYTE ((UCHAR)0xee)
  405. PBYTE CopyPtr; ULONG CopyCount,EarlyReturn;
  406. PBYTE *RegionPtr;
  407. PUNICODE_STRING Zstring;
  408. PSZ Astring;
  409. PNET_ROOT NetRoot;
  410. PLARGE_INTEGER LargeInteger;
  411. PBYTE PreviousPosition;
  412. #if DBG
  413. ULONG offset, required_WCT;
  414. ULONG CurrentOffset_tmp;
  415. #endif
  416. PAGED_CODE();
  417. va_start(AP,StufferState);
  418. for (;;) {
  419. switch (CurrentStufferControl) {
  420. case STUFFER_CTL_SKIP:
  421. case STUFFER_CTL_NORMAL:
  422. CurrentFormatString = va_arg(AP,PSZ);
  423. StufferCLoopTrace(("StufferAC = %s\n",CurrentFormatString));
  424. ASSERT (CurrentFormatString);
  425. for (;*CurrentFormatString;CurrentFormatString++) {
  426. char CurrentFormatChar = *CurrentFormatString;
  427. #if DBG
  428. { char msgbuf[80];
  429. switch (CurrentFormatChar) {
  430. case 'W': case 'w':
  431. case 'D': case 'd':
  432. case 'Y': case 'y':
  433. case 'M': case 'm':
  434. case 'L': case 'l':
  435. case 'c': case '4': case '>':
  436. case '!':
  437. //this guys are skipable
  438. break;
  439. default:
  440. if (CurrentStufferControl != STUFFER_CTL_SKIP) break;
  441. DbgPrint("Bad skip char '%c'\n",*CurrentFormatString);
  442. //DbgBreakPoint();
  443. }}
  444. //these are the ones that we do the offset check for
  445. { char msgbuf[80];
  446. #ifndef WIN9X
  447. RxSprintf(msgbuf,"control char '%c'\n",*CurrentFormatString);
  448. #endif
  449. switch (CurrentFormatChar) {
  450. case 'W': case 'D': case 'Y': case 'M': case 'B':
  451. case 'Q': case 'A': case 'U': case 'V':
  452. case 'N':
  453. case 'L':
  454. case 'R':
  455. case 'P':
  456. offset = va_arg(AP,ULONG);
  457. required_WCT = offset>>16;
  458. offset = offset & 0xffff;
  459. CurrentOffset_tmp = (ULONG)(*CurrentPosition-*CurrentWct);
  460. if (offset && (offset != CurrentOffset_tmp)){
  461. DbgPrint("Bad offset %d; should be %d\n",offset,CurrentOffset_tmp);
  462. //DbgBreakPoint();
  463. }
  464. break;
  465. default:
  466. break;
  467. }}
  468. #endif
  469. switch (CurrentFormatChar) {
  470. case '0':
  471. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(UCHAR)) {
  472. return(STATUS_BUFFER_OVERFLOW);
  473. }
  474. StufferFLoopTrace((" StufferFloop '0'\n",0));
  475. //just do the wct field...
  476. **CurrentPosition = (UCHAR)MRXSMB_INITIAL_WCT;
  477. *CurrentPosition+=1;
  478. break;
  479. case 'X':
  480. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(ULONG)) {
  481. return(STATUS_BUFFER_OVERFLOW);
  482. }
  483. StufferFLoopTrace((" StufferFloop 'X'\n",0));
  484. //do the wct field and the &x
  485. **CurrentPosition = (UCHAR)MRXSMB_INITIAL_WCT;
  486. *CurrentPosition+=1;
  487. SmbPutUlong (*CurrentPosition, (ULONG)MRXSMB_INITIAL_ANDX);
  488. *CurrentPosition+=sizeof(ULONG);
  489. break;
  490. case 'W':
  491. case 'w':
  492. arg = va_arg(AP,ULONG);
  493. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  494. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(USHORT)) {
  495. return(STATUS_BUFFER_OVERFLOW);
  496. }
  497. StufferFLoopTrace((" StufferFloop 'w' arg=%lu\n",arg));
  498. SmbPutUshort (*CurrentPosition, (USHORT)arg);
  499. *CurrentPosition+=sizeof(USHORT);
  500. break;
  501. case 'Y':
  502. case 'y':
  503. arg = va_arg(AP,UCHAR);
  504. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  505. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(UCHAR)) {
  506. return(STATUS_BUFFER_OVERFLOW);
  507. }
  508. StufferFLoopTrace((" StufferFloop 'y' arg=%lu\n",arg));
  509. **CurrentPosition = (UCHAR)arg;
  510. *CurrentPosition+=sizeof(UCHAR);
  511. break;
  512. case 'M':
  513. case 'm':
  514. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  515. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(UCHAR)) {
  516. return(STATUS_BUFFER_OVERFLOW);
  517. }
  518. StufferFLoopTrace((" StufferFloop 'm'\n",0));
  519. **CurrentPosition = 0;
  520. *CurrentPosition+=sizeof(UCHAR);
  521. break;
  522. case 'D':
  523. case 'd':
  524. arg = va_arg(AP,ULONG);
  525. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  526. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(ULONG)) {
  527. return(STATUS_BUFFER_OVERFLOW);
  528. }
  529. StufferFLoopTrace((" StufferFloop 'd' arg=%lu\n",arg));
  530. SmbPutUlong (*CurrentPosition, arg);
  531. *CurrentPosition+=sizeof(ULONG);
  532. break;
  533. case 'L':
  534. case 'l':
  535. LargeInteger = va_arg(AP,PLARGE_INTEGER);
  536. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  537. if (*CurrentPosition >= StufferState->BufferLimit - 2*sizeof(ULONG)) {
  538. return(STATUS_BUFFER_OVERFLOW);
  539. }
  540. StufferFLoopTrace((" StufferFloop 'l' arg=%0lx %0lx\n",
  541. LargeInteger->HighPart, LargeInteger->LowPart));
  542. SmbPutUlong (*CurrentPosition, LargeInteger->LowPart);
  543. SmbPutUlong (*CurrentPosition, LargeInteger->HighPart);
  544. *CurrentPosition+=2*sizeof(ULONG);
  545. break;
  546. case 'B':
  547. case 'b':
  548. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(USHORT)) {
  549. return(STATUS_BUFFER_OVERFLOW);
  550. }
  551. ASSERT (**CurrentWct == MRXSMB_INITIAL_WCT);
  552. WordCount = (UCHAR)((*CurrentPosition-*CurrentWct)>>1); //the one gets shifted off
  553. StufferFLoopTrace((" StufferFloop 'b' Wct=%lu\n",WordCount));
  554. DbgDoit( ASSERT(!required_WCT || (WordCount == (required_WCT&0x7fff))); )
  555. **CurrentWct = (UCHAR)WordCount;
  556. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_BCC);
  557. *CurrentBcc = *CurrentPosition;
  558. *CurrentPosition+=sizeof(USHORT);
  559. break;
  560. case 'Q':
  561. case 'q':
  562. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(USHORT)) {
  563. return(STATUS_BUFFER_OVERFLOW);
  564. }
  565. StufferFLoopTrace((" StufferFloop 'q' \n",0));
  566. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_DATAOFFSET);
  567. *CurrentDataOffset = *CurrentPosition;
  568. *CurrentPosition+=sizeof(USHORT);
  569. break;
  570. case '5':
  571. //fill in the data offset
  572. ASSERT (SmbGetUshort (*CurrentDataOffset) == MRXSMB_INITIAL_DATAOFFSET);
  573. ByteCount = (USHORT)(*CurrentPosition-BufferBase);
  574. StufferFLoopTrace((" StufferFloop '5' offset=%lu\n",ByteCount));
  575. SmbPutUshort (*CurrentDataOffset, (USHORT)ByteCount);
  576. break;
  577. case 'P':
  578. case 'p':
  579. if (*CurrentPosition >= StufferState->BufferLimit - sizeof(USHORT)) {
  580. return(STATUS_BUFFER_OVERFLOW);
  581. }
  582. StufferFLoopTrace((" StufferFloop 'p' \n",0));
  583. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_PARAMOFFSET);
  584. *CurrentParamOffset = *CurrentPosition;
  585. *CurrentPosition+=sizeof(USHORT);
  586. break;
  587. case '6':
  588. //fill in the data offset
  589. ASSERT (SmbGetUshort (*CurrentParamOffset) == MRXSMB_INITIAL_PARAMOFFSET);
  590. ByteCount = (USHORT)(*CurrentPosition-BufferBase);
  591. StufferFLoopTrace((" StufferFloop '6' offset=%lu\n",ByteCount));
  592. SmbPutUshort (*CurrentParamOffset, (USHORT)ByteCount);
  593. break;
  594. case 'S':
  595. // pad to ULONG; we loop behind instead of adding so we can clear
  596. // out behind ourselves; apparently, some server croak on nonzero padding
  597. StufferFLoopTrace((" StufferFloop 'S' \n",0));
  598. PreviousPosition = *CurrentPosition;
  599. *CurrentPosition = (PBYTE)QuadAlignPtr(*CurrentPosition);
  600. if (*CurrentPosition >= StufferState->BufferLimit) {
  601. return(STATUS_BUFFER_OVERFLOW);
  602. }
  603. for (;PreviousPosition!=*CurrentPosition;) {
  604. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  605. *PreviousPosition++ = PADBYTE;
  606. }
  607. break;
  608. case 's':
  609. // pad to arg; we loop behind instead of adding so we can clear
  610. // out behind ourselves; apparently, some server croak on nonzero padding
  611. arg = va_arg(AP,ULONG);
  612. StufferFLoopTrace((" StufferFloop 's' arg=\n",arg));
  613. PreviousPosition = *CurrentPosition;
  614. *CurrentPosition += arg-1;
  615. *CurrentPosition = (PBYTE)( ((ULONG_PTR)(*CurrentPosition)) & ~((LONG)(arg-1)) );
  616. if (*CurrentPosition >= StufferState->BufferLimit) {
  617. return(STATUS_BUFFER_OVERFLOW);
  618. }
  619. for (;PreviousPosition!=*CurrentPosition;) {
  620. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  621. *PreviousPosition++ = PADBYTE;
  622. }
  623. break;
  624. case '1':
  625. // pad to USHORT; we loop behind instead of adding so we can clear
  626. // out behind ourselves; apparently, some server croak on nonzero padding
  627. StufferFLoopTrace((" StufferFloop '1' Curr=%08lx \n",*CurrentPosition));
  628. PreviousPosition = *CurrentPosition;
  629. *CurrentPosition += sizeof(USHORT)-1;
  630. StufferFLoopTrace((" Curr=%08lx \n",*CurrentPosition));
  631. *CurrentPosition = (PBYTE)( ((ULONG_PTR)(*CurrentPosition)) & ~((LONG)(sizeof(USHORT)-1)) );
  632. StufferFLoopTrace((" Curr=%08lx \n",*CurrentPosition));
  633. if (*CurrentPosition >= StufferState->BufferLimit) {
  634. return(STATUS_BUFFER_OVERFLOW);
  635. }
  636. for (;PreviousPosition!=*CurrentPosition;) {
  637. StufferFLoopTrace((" StufferFloop '1' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  638. *PreviousPosition++ = PADBYTE;
  639. }
  640. break;
  641. case 'c':
  642. // copy in the bytes....used a lot in transact
  643. CopyCount = va_arg(AP,ULONG);
  644. CopyPtr = va_arg(AP,PBYTE);
  645. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  646. StufferFLoopTrace((" StufferFloop 'c' copycount = %lu\n", CopyCount));
  647. PreviousPosition = *CurrentPosition;
  648. *CurrentPosition += CopyCount;
  649. if (*CurrentPosition >= StufferState->BufferLimit) {
  650. return(STATUS_BUFFER_OVERFLOW);
  651. }
  652. for (;PreviousPosition!=*CurrentPosition;) {
  653. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  654. *PreviousPosition++ = *CopyPtr++;
  655. }
  656. break;
  657. case 'R':
  658. case 'r':
  659. // copy in the bytes....used a lot in transact
  660. RegionPtr = va_arg(AP,PBYTE*);
  661. CopyCount = va_arg(AP,ULONG);
  662. StufferFLoopTrace((" StufferFloop 'r' regionsize = %lu\n", CopyCount));
  663. *RegionPtr = *CurrentPosition;
  664. *CurrentPosition += CopyCount;
  665. if (*CurrentPosition >= StufferState->BufferLimit) {
  666. return(STATUS_BUFFER_OVERFLOW);
  667. }
  668. IF_DEBUG {
  669. PreviousPosition = *RegionPtr;
  670. for (;PreviousPosition!=*CurrentPosition;) {
  671. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  672. *PreviousPosition++ = '-';
  673. }
  674. }
  675. break;
  676. case 'A':
  677. case 'a':
  678. //copy byte from an asciiz including the trailing NULL
  679. Astring = va_arg(AP,PSZ);
  680. StufferFLoopTrace((" StufferFloop 'a' stringing = %s\n", Astring));
  681. CopyCount = strlen(Astring)+1;
  682. //if (((ULONG)(*CurrentPosition))&1) {
  683. // StufferFLoopTrace((" StufferFloop 'a' aligning\n", 0));
  684. // *CurrentPosition+=1;
  685. //}
  686. PreviousPosition = *CurrentPosition;
  687. *CurrentPosition += CopyCount;
  688. if (*CurrentPosition >= StufferState->BufferLimit) {
  689. StufferFLoopTrace((" StufferFloop 'a' bufferoverrun\n", 0));
  690. ASSERT(!"BufferOverrun");
  691. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  692. }
  693. RtlCopyMemory(PreviousPosition,Astring,CopyCount);
  694. break;
  695. case 'z':
  696. case '4':
  697. case '>':
  698. Zstring = va_arg(AP,PUNICODE_STRING);
  699. StufferFLoopTrace((" StufferFloop '4/z/>' stringing = %wZ, cp=\n", Zstring,*CurrentPosition ));
  700. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  701. if (CurrentFormatChar=='4') {
  702. if (*CurrentPosition >= StufferState->BufferLimit - 1) {
  703. return(STATUS_BUFFER_OVERFLOW);
  704. }
  705. //first lay down a x'04' and then copy either a asciiz or a unicodez depending on the flags setting
  706. **CurrentPosition = (UCHAR)4; //ascii marker
  707. *CurrentPosition+=1;
  708. } else if (CurrentFormatChar=='>'){
  709. //back up over the previous NULL
  710. //
  711. *CurrentPosition-=(FlagOn(SmbHeader->Flags2,SMB_FLAGS2_UNICODE)?sizeof(WCHAR):sizeof(char));
  712. StufferFLoopTrace((" StufferFloop '4/z/>' afterroolback, cp=\n", *CurrentPosition ));
  713. }
  714. if (FlagOn(SmbHeader->Flags2,SMB_FLAGS2_UNICODE)){
  715. if (((ULONG_PTR)(*CurrentPosition))&1) {
  716. StufferFLoopTrace((" StufferFloop '4/z/>' aligning\n", 0));
  717. *CurrentPosition+=1;
  718. }
  719. PreviousPosition = *CurrentPosition;
  720. *CurrentPosition += (Zstring->Length + sizeof(WCHAR));
  721. if (*CurrentPosition >= StufferState->BufferLimit) {
  722. StufferFLoopTrace((" StufferFloop '4/z/>' bufferoverrun\n", 0));
  723. ASSERT(!"BufferOverrun");
  724. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  725. }
  726. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  727. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  728. } else {
  729. NTSTATUS Status;
  730. OEM_STRING OemString;
  731. OemString.Length =
  732. OemString.MaximumLength =
  733. (USHORT)( StufferState->BufferLimit - *CurrentPosition - sizeof(CHAR));
  734. OemString.Buffer = *CurrentPosition;
  735. if (FlagOn(SmbHeader->Flags,SMB_FLAGS_CASE_INSENSITIVE) &&
  736. !FlagOn(SmbHeader->Flags2,SMB_FLAGS2_KNOWS_LONG_NAMES)) {
  737. Status = RtlUpcaseUnicodeStringToOemString(
  738. &OemString,
  739. Zstring,
  740. FALSE);
  741. } else {
  742. Status = RtlUnicodeStringToOemString(
  743. &OemString,
  744. Zstring,
  745. FALSE);
  746. }
  747. if (!NT_SUCCESS(Status)) {
  748. StufferFLoopTrace((" StufferFloop '4/z/>' bufferoverrun(ascii)\n", 0));
  749. ASSERT(!"BufferOverrun");
  750. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  751. }
  752. *CurrentPosition += OemString.Length + 1;
  753. *(*CurrentPosition-1) = 0;
  754. }
  755. break;
  756. case 'U':
  757. case 'u':
  758. //copy bytes from an UNICODE string including a trailing NULL
  759. Zstring = va_arg(AP,PUNICODE_STRING);
  760. StufferFLoopTrace((" StufferFloop 'u' stringing = %wZ\n", Zstring));
  761. if (((ULONG_PTR)(*CurrentPosition))&1) {
  762. StufferFLoopTrace((" StufferFloop 'u' aligning\n", 0));
  763. *CurrentPosition+=1;
  764. }
  765. PreviousPosition = *CurrentPosition;
  766. *CurrentPosition += (Zstring->Length + sizeof(WCHAR));
  767. if (*CurrentPosition >= StufferState->BufferLimit) {
  768. StufferFLoopTrace((" StufferFloop 'u' bufferoverrun\n", 0));
  769. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  770. }
  771. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  772. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  773. break;
  774. case 'V':
  775. case 'v':
  776. //copy bytes from an UNICODE string no trailing NUL
  777. Zstring = va_arg(AP,PUNICODE_STRING);
  778. StufferFLoopTrace((" StufferFloop 'v' stringing = %wZ\n", Zstring));
  779. if (((ULONG_PTR)(*CurrentPosition))&1) {
  780. StufferFLoopTrace((" StufferFloop 'v' aligning\n", 0));
  781. *CurrentPosition+=1;
  782. }
  783. PreviousPosition = *CurrentPosition;
  784. *CurrentPosition += Zstring->Length;
  785. if (*CurrentPosition >= StufferState->BufferLimit) {
  786. StufferFLoopTrace((" StufferFloop 'v' bufferoverrun\n", 0));
  787. ASSERT(!"BufferOverrun");
  788. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  789. }
  790. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  791. break;
  792. case 'N':
  793. case 'n':
  794. //copy bytes from a NetRoot name....w null
  795. //joejoe we need to do the # thing here
  796. NetRoot = va_arg(AP,PNET_ROOT);
  797. ASSERT(NodeType(NetRoot)==RDBSS_NTC_NETROOT);
  798. Zstring = &NetRoot->PrefixEntry.Prefix;
  799. StufferFLoopTrace((" StufferFloop 'n' stringing = %wZ\n", Zstring));
  800. if (StufferState->Flags2Copy&SMB_FLAGS2_UNICODE) {
  801. if (((ULONG_PTR)(*CurrentPosition))&1) {
  802. StufferFLoopTrace((" StufferFloop 'n' aligning\n", 0));
  803. *CurrentPosition+=1;
  804. }
  805. PreviousPosition = *CurrentPosition;
  806. *CurrentPosition += (Zstring->Length + 2 * sizeof(WCHAR)); //extra \ plus a nul
  807. if (*CurrentPosition >= StufferState->BufferLimit) {
  808. StufferFLoopTrace((" StufferFloop 'n' bufferoverrun\n", 0));
  809. ASSERT(!"BufferOverrun");
  810. return(RX_MAP_STATUS(BUFFER_OVERFLOW));
  811. }
  812. *((PWCHAR)PreviousPosition) = '\\';
  813. RtlCopyMemory(PreviousPosition+sizeof(WCHAR),Zstring->Buffer,Zstring->Length);
  814. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  815. }
  816. break;
  817. case '?':
  818. //early out....used in transact to do the setup
  819. EarlyReturn = va_arg(AP,ULONG);
  820. StufferFLoopTrace((" StufferFloop '?' out if 0==%08lx\n",EarlyReturn));
  821. if (EarlyReturn==0) return RX_MAP_STATUS(SUCCESS);
  822. break;
  823. case '.':
  824. //noop...used to reenter without a real formatting string
  825. StufferFLoopTrace((" StufferFloop '.'\n",0));
  826. break;
  827. case '!':
  828. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  829. ASSERT (SmbGetUshort (*CurrentBcc) == MRXSMB_INITIAL_BCC);
  830. ByteCount = (USHORT)(*CurrentPosition-*CurrentBcc-sizeof(USHORT));
  831. StufferFLoopTrace((" StufferFloop '!' arg=%lu\n",ByteCount));
  832. SmbPutUshort (*CurrentBcc, (USHORT)ByteCount);
  833. return RX_MAP_STATUS(SUCCESS);
  834. default:
  835. StufferFLoopTrace((" StufferFloop '%c' BADBADBAD\n",*CurrentFormatString));
  836. ASSERT(!"Illegal Controlstring character\n");
  837. } //switch
  838. }//for
  839. break;
  840. case 0:
  841. return RX_MAP_STATUS(SUCCESS);
  842. default:
  843. StufferCLoopTrace((" StufferCloop %u BADBADBAD\n",CurrentStufferControl));
  844. ASSERT(!"IllegalStufferControl\n");
  845. }//switch
  846. CurrentStufferControl = va_arg(AP,SMB_STUFFER_CONTROLS);
  847. StufferCLoopTrace((" StufferCloop NewStufferControl=%u \n",CurrentStufferControl));
  848. } //for
  849. return RX_MAP_STATUS(SUCCESS);
  850. }
  851. VOID
  852. MRxSmbStuffAppendRawData(
  853. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  854. IN PMDL Mdl
  855. )
  856. {
  857. PMDL pMdl;
  858. PAGED_CODE();
  859. ASSERT(!StufferState->DataMdl);
  860. pMdl = StufferState->DataMdl = Mdl;
  861. StufferState->DataSize = 0;
  862. while (pMdl != NULL) {
  863. StufferState->DataSize += pMdl->ByteCount;
  864. pMdl = pMdl->Next;
  865. }
  866. return;
  867. }
  868. VOID
  869. MRxSmbStuffAppendSmbData(
  870. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  871. IN PMDL Mdl
  872. )
  873. {
  874. ULONG Offset;
  875. PAGED_CODE();
  876. ASSERT(!StufferState->DataMdl);
  877. StufferState->DataMdl = Mdl;
  878. StufferState->DataSize = Mdl->ByteCount;
  879. //now reach back into the buffer and set the SMB data offset; if it is already set...just get out
  880. if (SmbGetUshort (StufferState->CurrentDataOffset) == MRXSMB_INITIAL_DATAOFFSET){
  881. Offset = (ULONG)(StufferState->CurrentPosition - StufferState->BufferBase);
  882. RxDbgTrace(0, Dbg,("MRxSmbStuffAppendSmbData offset=%lu\n",Offset));
  883. SmbPutUshort (StufferState->CurrentDataOffset, (USHORT)Offset);
  884. }
  885. return;
  886. }
  887. VOID
  888. MRxSmbStuffSetByteCount(
  889. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState
  890. )
  891. {
  892. ULONG ByteCount;
  893. PAGED_CODE();
  894. ASSERT (SmbGetUshort (StufferState->CurrentBcc) == MRXSMB_INITIAL_BCC);
  895. ByteCount = (ULONG)(StufferState->CurrentPosition
  896. - StufferState->CurrentBcc
  897. - sizeof(USHORT)
  898. + StufferState->DataSize);
  899. RxDbgTrace(0, Dbg,("MRxSmbStuffSetByteCount ByteCount=%lu\n",ByteCount));
  900. SmbPutUshort (StufferState->CurrentBcc, (USHORT)ByteCount);
  901. return;
  902. }