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.

865 lines
36 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 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. --*/
  43. #include "precomp.h"
  44. #pragma hdrstop
  45. #include <stdio.h>
  46. #include <stdarg.h>
  47. #ifdef ALLOC_PRAGMA
  48. #pragma alloc_text(PAGE, SmbMrxInitializeStufferFacilities)
  49. #pragma alloc_text(PAGE, SmbMrxFinalizeStufferFacilities)
  50. #pragma alloc_text(PAGE, MRxSmbSetInitialSMB)
  51. #pragma alloc_text(PAGE, MRxSmbStartSMBCommand)
  52. #pragma alloc_text(PAGE, MrxSMBWillThisFit)
  53. #pragma alloc_text(PAGE, MRxSmbStuffSMB)
  54. #pragma alloc_text(PAGE, MRxSmbStuffAppendRawData)
  55. #pragma alloc_text(PAGE, MRxSmbStuffAppendSmbData)
  56. #pragma alloc_text(PAGE, MRxSmbStuffSetByteCount)
  57. #endif
  58. //
  59. // The local debug trace level
  60. //
  61. #define Dbg (DEBUG_TRACE_ALWAYS)
  62. #define MRXSMB_INITIAL_WCT (0xcc)
  63. #define MRXSMB_INITIAL_BCC (0xface)
  64. #define MRXSMB_INITIAL_DATAOFFSET (0xd0ff)
  65. #define MRXSMB_INITIAL_PARAMOFFSET (0xb0ff)
  66. #define MRXSMB_INITIAL_ANDX (0xdede00ff)
  67. NTSTATUS
  68. SmbMrxInitializeStufferFacilities(
  69. void
  70. )
  71. /*++
  72. Routine Description:
  73. This routine initializes things for the SMB minirdr. we will allocate enough stuff
  74. to get us going. right now....we do nothing.
  75. Arguments:
  76. Return Value:
  77. RXSTATUS - The return status for the operation
  78. --*/
  79. {
  80. PAGED_CODE();
  81. return(STATUS_SUCCESS);
  82. }
  83. NTSTATUS
  84. SmbMrxFinalizeStufferFacilities(
  85. void
  86. )
  87. /*++
  88. Routine Description:
  89. This routine finalizes things for the SMB minirdr. we give back everything that
  90. we have allocated. right now....we do nothing.
  91. Arguments:
  92. Return Value:
  93. RXSTATUS - The return status for the operation
  94. --*/
  95. {
  96. PAGED_CODE();
  97. return(STATUS_SUCCESS);
  98. }
  99. #define BUILD_HEADER_ROUTINE SmbCeBuildSmbHeader
  100. NTSTATUS
  101. MRxSmbSetInitialSMB (
  102. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState
  103. STUFFERTRACE_CONTROLPOINT_ARGS
  104. )
  105. {
  106. NTSTATUS Status;
  107. PNT_SMB_HEADER NtSmbHeader;
  108. ULONG BufferConsumed;
  109. PBYTE ScanPosition;
  110. PUCHAR pCommand;
  111. PAGED_CODE();
  112. ASSERT ( StufferState != NULL );
  113. ASSERT ( sizeof(NT_SMB_HEADER) == sizeof(SMB_HEADER) );
  114. //RxDbgTrace(0, Dbg, ("MrxSMBSetInitialSMB base=%08lx,limit=%08lx\n",
  115. // StufferState->BufferBase,StufferState->BufferLimit));
  116. ASSERT ( (StufferState->BufferLimit - StufferState->BufferBase) > sizeof(SMB_HEADER));
  117. NtSmbHeader = (PNT_SMB_HEADER)(StufferState->BufferBase);
  118. RtlZeroMemory(NtSmbHeader,sizeof(NT_SMB_HEADER));
  119. //this stuff is reinitialized
  120. StufferState->DataMdl = NULL; //note that this is not finalized or anything
  121. StufferState->DataSize = 0;
  122. StufferState->CurrentWct = NULL;
  123. StufferState->PreviousCommand = SMB_COM_NO_ANDX_COMMAND;
  124. StufferState->CurrentCommand = SMB_COM_NO_ANDX_COMMAND;
  125. StufferState->FlagsCopy = 0;
  126. StufferState->Flags2Copy = 0;
  127. StufferState->CurrentPosition = ((PBYTE)NtSmbHeader);
  128. Status = BUILD_HEADER_ROUTINE(
  129. StufferState->Exchange,
  130. NtSmbHeader,
  131. (ULONG)(StufferState->BufferLimit - StufferState->BufferBase),
  132. &BufferConsumed,
  133. &StufferState->PreviousCommand,
  134. &pCommand);
  135. if (Status!=STATUS_SUCCESS) {
  136. RxDbgTrace(0, Dbg, ("MrxSMBSetInitialSMB buildhdr failure st=%08lx\n",Status));
  137. RxLog(("BuildHdr failed %lx %lx",StufferState->Exchange,Status));
  138. return Status;
  139. }
  140. //copy the flags
  141. StufferState->FlagsCopy = NtSmbHeader->Flags;
  142. StufferState->Flags2Copy = SmbGetAlignedUshort(&NtSmbHeader->Flags2);
  143. if (StufferState->Exchange->Type == ORDINARY_EXCHANGE) {
  144. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = (PSMB_PSE_ORDINARY_EXCHANGE)StufferState->Exchange;
  145. if (BooleanFlagOn(OrdinaryExchange->Flags,SMBPSE_OE_FLAG_TURNON_DFS_FLAG)) {
  146. StufferState->Flags2Copy |= SMB_FLAGS2_DFS;
  147. SmbPutUshort(&NtSmbHeader->Flags2,(USHORT)StufferState->Flags2Copy);
  148. }
  149. }
  150. StufferState->CurrentPosition += BufferConsumed;
  151. if (BufferConsumed > sizeof(SMB_HEADER)) {
  152. if (pCommand != NULL) {
  153. *pCommand = SMB_COM_NO_ANDX_COMMAND;
  154. }
  155. StufferState->CurrentWct = StufferState->CurrentPosition;
  156. }
  157. return Status;
  158. }
  159. #define RETURN_A_START_PROBLEM(xxyy) {\
  160. RxDbgTrace(0,Dbg,("MRxSmbStartSMBCommand gotta problem= %lu\n",xxyy)); \
  161. StufferState->SpecificProblem = xxyy; \
  162. return(STATUS_INVALID_PARAMETER); \
  163. }
  164. NTSTATUS
  165. MRxSmbStartSMBCommand (
  166. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  167. IN INITIAL_SMBBUG_DISPOSITION InitialSMBDisposition,
  168. IN UCHAR Command,
  169. IN ULONG MaximumBufferUsed,
  170. IN ULONG MaximumSize,
  171. IN ULONG InitialAlignment,
  172. IN ULONG MaximumResponseHeader,
  173. IN UCHAR Flags,
  174. IN UCHAR FlagsMask,
  175. IN USHORT Flags2,
  176. IN USHORT Flags2Mask
  177. STUFFERTRACE_CONTROLPOINT_ARGS
  178. )
  179. /*++
  180. Routine Description:
  181. The routine checks to see if the condition is stable. If not, it
  182. goes into a wait loop alternately getting the resource and then
  183. waiting on the event.
  184. Arguments:
  185. StufferState - the header buffer being used
  186. InitialSMBDisposition tells when/if to reinit the stuffer state
  187. Command - the smb command being set up
  188. MaximumBufferUsed - the amount of the header buffer that will be used (as opposed to the data)
  189. this has to be conjured up in advance. if you're not willing to do this, then
  190. just push out the current smb. this value should include any data pads!
  191. MaximumSize - the size of the data. this is to keep from overrunning the srv's smbbuf
  192. InitialAlignment - a compound argument (i.e. you get it from a constant) the top half
  193. tells the alignment unit and the bottom gives the spacing within
  194. MaximumResponseHeader - how much of the srv's response buffer this will use up
  195. Flags - the required flags settings
  196. FlagsMask - which bits of the flags are important
  197. Flags2 - the required flags2 settings
  198. Flags2Mask - which flags2 bits are important
  199. Return Value:
  200. none.
  201. --*/
  202. {
  203. UCHAR NewFlags;
  204. USHORT NewFlags2;
  205. PBYTE *CurrentPosition = &(StufferState->CurrentPosition);
  206. PNT_SMB_HEADER NtSmbHeader = (PNT_SMB_HEADER)(StufferState->BufferBase);
  207. ULONG AlignmentUnit = InitialAlignment >> 16;
  208. ULONG StufferStateRequirement = MaximumBufferUsed + AlignmentUnit;
  209. #if DBG
  210. PBYTE OriginalPosition = *CurrentPosition;
  211. #endif
  212. PAGED_CODE();
  213. if (StufferState->DataSize) {
  214. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  215. return(STATUS_INVALID_PARAMETER);
  216. }
  217. if ((InitialSMBDisposition==SetInitialSMB_yyUnconditionally)
  218. || ((InitialSMBDisposition==SetInitialSMB_ForReuse)&&(StufferState->Started))) {
  219. MRxSmbSetInitialSMB( StufferState STUFFERTRACE_NOPREFIX(ControlPoint,EnablePrints) );
  220. }
  221. StufferState->Started = TRUE;
  222. switch (StufferState->CurrentCommand) {
  223. case SMB_COM_LOCKING_ANDX:
  224. case SMB_COM_OPEN_ANDX:
  225. case SMB_COM_READ_ANDX:
  226. case SMB_COM_WRITE_ANDX:
  227. case SMB_COM_SESSION_SETUP_ANDX:
  228. //case SMB_COM_LOGOFF_ANDX:
  229. case SMB_COM_TREE_CONNECT_ANDX:
  230. case SMB_COM_NT_CREATE_ANDX:
  231. case SMB_COM_NO_ANDX_COMMAND:
  232. break;
  233. default:
  234. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  235. return(STATUS_INVALID_PARAMETER);
  236. }
  237. if (*CurrentPosition+StufferStateRequirement >= StufferState->BufferLimit ) {
  238. StufferState->SpecificProblem = xSMBbufSTATUS_CANT_COMPOUND;
  239. return(STATUS_INVALID_PARAMETER);
  240. }
  241. if (StufferState->RxContext) {
  242. PRX_CONTEXT RxContext = StufferState->RxContext;
  243. PMRX_SRV_CALL SrvCall;
  244. ULONG CurrentOffset;
  245. if (RxContext->MajorFunction != IRP_MJ_CREATE) {
  246. SrvCall = RxContext->pFcb->pNetRoot->pSrvCall;
  247. } else {
  248. SrvCall = RxContext->Create.pSrvCall;
  249. }
  250. ASSERT(SrvCall);
  251. CurrentOffset = (ULONG)(*CurrentPosition - StufferState->BufferBase);
  252. if (CurrentOffset+StufferStateRequirement+MaximumSize
  253. > GetServerMaximumBufferSize(SrvCall) ) {
  254. StufferState->SpecificProblem = xSMBbufSTATUS_SERVER_OVERRUN;
  255. return(STATUS_INVALID_PARAMETER);
  256. }
  257. }
  258. NewFlags = Flags | (UCHAR)(StufferState->FlagsCopy);
  259. NewFlags2 = Flags2 | (USHORT)(StufferState->Flags2Copy);
  260. if ( ((NewFlags&FlagsMask)!=Flags) ||
  261. ((NewFlags2&Flags2Mask)!=Flags2) ) {
  262. StufferState->SpecificProblem = xSMBbufSTATUS_FLAGS_CONFLICT;
  263. return(STATUS_INVALID_PARAMETER);
  264. }
  265. StufferState->FlagsCopy = NtSmbHeader->Flags = NewFlags;
  266. StufferState->Flags2Copy = NewFlags2;
  267. SmbPutAlignedUshort(&NtSmbHeader->Flags2, NewFlags2);
  268. if (!StufferState->CurrentWct) {
  269. NtSmbHeader->Command = Command;
  270. } else {
  271. PGENERIC_ANDX GenericAndX = (PGENERIC_ANDX)StufferState->CurrentWct;
  272. if (AlignmentUnit) {
  273. ULONG AlignmentMask = (AlignmentUnit-1);
  274. ULONG AlignmentResidue = InitialAlignment&AlignmentMask;
  275. RxDbgTrace(0, Dbg, ("Aligning start of smb cp&m,m,r=%08lx %08lx %08lx\n",
  276. ((ULONG_PTR)(*CurrentPosition))&AlignmentMask,
  277. AlignmentMask, AlignmentResidue)
  278. );
  279. for (;(((ULONG_PTR)(*CurrentPosition))&AlignmentMask)!=AlignmentResidue;) {
  280. **CurrentPosition = ',';
  281. *CurrentPosition += 1;
  282. }
  283. }
  284. GenericAndX->AndXCommand = Command;
  285. GenericAndX->AndXReserved = 0;
  286. SmbPutUshort (&GenericAndX->AndXOffset,
  287. (USHORT)(*CurrentPosition - StufferState->BufferBase));
  288. }
  289. StufferState->CurrentWct = *CurrentPosition;
  290. StufferState->CurrentCommand = Command;
  291. StufferState->CurrentDataOffset = 0;
  292. return STATUS_SUCCESS;
  293. }
  294. BOOLEAN
  295. MrxSMBWillThisFit(
  296. IN PSMBSTUFFER_BUFFER_STATE StufferState,
  297. IN ULONG AlignmentUnit,
  298. IN ULONG DataSize
  299. )
  300. {
  301. return(StufferState->CurrentPosition+AlignmentUnit+DataSize<StufferState->BufferLimit);
  302. }
  303. #if RDBSSTRACE
  304. #define StufferFLoopTrace(Z) { if (StufferState->PrintFLoop) {RxDbgTraceLV__norx(0,StufferState->ControlPoint,900,Z);}}
  305. #define StufferCLoopTrace(Z) { if (StufferState->PrintCLoop) {RxDbgTraceLV__norx(0,StufferState->ControlPoint,800,Z);}}
  306. #else // DBG
  307. #define StufferFLoopTrace(Z)
  308. #define StufferCLoopTrace(Z)
  309. #endif // DBG
  310. NTSTATUS
  311. MRxSmbStuffSMB (
  312. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  313. ...
  314. )
  315. {
  316. va_list AP;
  317. PBYTE BufferBase = (StufferState->BufferBase);
  318. PBYTE *CurrentPosition = &(StufferState->CurrentPosition);
  319. PBYTE *CurrentWct = &(StufferState->CurrentWct);
  320. PBYTE *CurrentBcc = &(StufferState->CurrentBcc);
  321. PBYTE *CurrentDataOffset = &(StufferState->CurrentDataOffset);
  322. PBYTE *CurrentParamOffset = &(StufferState->CurrentParamOffset);
  323. SMB_STUFFER_CONTROLS CurrentStufferControl = STUFFER_CTL_NORMAL;
  324. PSMB_HEADER SmbHeader = (PSMB_HEADER)BufferBase;
  325. PSZ CurrentFormatString = NULL;
  326. ULONG arg;
  327. UCHAR WordCount;
  328. USHORT ByteCount;
  329. #define PADBYTE ((UCHAR)0xee)
  330. PBYTE CopyPtr; ULONG CopyCount,EarlyReturn;
  331. PBYTE *RegionPtr;
  332. PUNICODE_STRING Zstring;
  333. PSZ Astring;
  334. PNET_ROOT NetRoot;
  335. PLARGE_INTEGER LargeInteger;
  336. PBYTE PreviousPosition;
  337. #if DBG
  338. ULONG offset, required_WCT;
  339. ULONG CurrentOffset_tmp;
  340. #endif
  341. PAGED_CODE();
  342. va_start(AP,StufferState);
  343. for (;;) {
  344. switch (CurrentStufferControl) {
  345. case STUFFER_CTL_SKIP:
  346. case STUFFER_CTL_NORMAL:
  347. CurrentFormatString = va_arg(AP,PSZ);
  348. StufferCLoopTrace(("StufferAC = %s\n",CurrentFormatString));
  349. ASSERT (CurrentFormatString);
  350. for (;*CurrentFormatString;CurrentFormatString++) {
  351. char CurrentFormatChar = *CurrentFormatString;
  352. #if DBG
  353. { char msgbuf[80];
  354. switch (CurrentFormatChar) {
  355. case 'W': case 'w':
  356. case 'D': case 'd':
  357. case 'Y': case 'y':
  358. case 'M': case 'm':
  359. case 'L': case 'l':
  360. case 'c': case '4': case '>':
  361. case '!':
  362. //this guys are skipable
  363. break;
  364. default:
  365. if (CurrentStufferControl != STUFFER_CTL_SKIP) break;
  366. DbgPrint("Bad skip char '%c'\n",*CurrentFormatString);
  367. DbgBreakPoint();
  368. }}
  369. //these are the ones that we do the offset check for
  370. { char msgbuf[80];
  371. #ifndef WIN9X
  372. RxSprintf(msgbuf,"control char '%c'\n",*CurrentFormatString);
  373. #endif
  374. switch (CurrentFormatChar) {
  375. case 'W': case 'D': case 'Y': case 'M': case 'B':
  376. case 'Q': case 'A': case 'U': case 'V':
  377. case 'N':
  378. case 'L':
  379. case 'R':
  380. case 'P':
  381. offset = va_arg(AP,ULONG);
  382. required_WCT = offset>>16;
  383. offset = offset & 0xffff;
  384. CurrentOffset_tmp = (ULONG)(*CurrentPosition-*CurrentWct);
  385. if (offset && (offset != CurrentOffset_tmp)){
  386. DbgPrint("Bad offset %d; should be %d\n",offset,CurrentOffset_tmp);
  387. DbgBreakPoint();
  388. }
  389. break;
  390. default:
  391. break;
  392. }}
  393. #endif
  394. switch (CurrentFormatChar) {
  395. case '0':
  396. StufferFLoopTrace((" StufferFloop '0'\n",0));
  397. //just do the wct field...
  398. **CurrentPosition = (UCHAR)MRXSMB_INITIAL_WCT;
  399. *CurrentPosition+=1;
  400. break;
  401. case 'X':
  402. StufferFLoopTrace((" StufferFloop 'X'\n",0));
  403. //do the wct field and the &x
  404. **CurrentPosition = (UCHAR)MRXSMB_INITIAL_WCT;
  405. *CurrentPosition+=1;
  406. SmbPutUlong (*CurrentPosition, (ULONG)MRXSMB_INITIAL_ANDX);
  407. *CurrentPosition+=sizeof(ULONG);
  408. break;
  409. case 'W':
  410. case 'w':
  411. arg = va_arg(AP,ULONG);
  412. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  413. StufferFLoopTrace((" StufferFloop 'w' arg=%lu\n",arg));
  414. SmbPutUshort (*CurrentPosition, (USHORT)arg);
  415. *CurrentPosition+=sizeof(USHORT);
  416. break;
  417. case 'Y':
  418. case 'y':
  419. arg = va_arg(AP,UCHAR);
  420. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  421. StufferFLoopTrace((" StufferFloop 'y' arg=%lu\n",arg));
  422. **CurrentPosition = (UCHAR)arg;
  423. *CurrentPosition+=sizeof(UCHAR);
  424. break;
  425. case 'M':
  426. case 'm':
  427. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  428. StufferFLoopTrace((" StufferFloop 'm'\n",0));
  429. **CurrentPosition = 0;
  430. *CurrentPosition+=sizeof(UCHAR);
  431. break;
  432. case 'D':
  433. case 'd':
  434. arg = va_arg(AP,ULONG);
  435. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  436. StufferFLoopTrace((" StufferFloop 'd' arg=%lu\n",arg));
  437. SmbPutUlong (*CurrentPosition, arg);
  438. *CurrentPosition+=sizeof(ULONG);
  439. break;
  440. case 'L':
  441. case 'l':
  442. LargeInteger = va_arg(AP,PLARGE_INTEGER);
  443. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  444. StufferFLoopTrace((" StufferFloop 'l' arg=%0lx %0lx\n",
  445. LargeInteger->HighPart, LargeInteger->LowPart));
  446. SmbPutUlong (*CurrentPosition, LargeInteger->LowPart);
  447. SmbPutUlong (*CurrentPosition, LargeInteger->HighPart);
  448. *CurrentPosition+=2*sizeof(ULONG);
  449. break;
  450. case 'B':
  451. case 'b':
  452. ASSERT (**CurrentWct == MRXSMB_INITIAL_WCT);
  453. WordCount = (UCHAR)((*CurrentPosition-*CurrentWct)>>1); //the one gets shifted off
  454. StufferFLoopTrace((" StufferFloop 'b' Wct=%lu\n",WordCount));
  455. DbgDoit( ASSERT(!required_WCT || (WordCount == (required_WCT&0x7fff))); )
  456. **CurrentWct = (UCHAR)WordCount;
  457. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_BCC);
  458. *CurrentBcc = *CurrentPosition;
  459. *CurrentPosition+=sizeof(USHORT);
  460. break;
  461. case 'Q':
  462. case 'q':
  463. StufferFLoopTrace((" StufferFloop 'q' \n",0));
  464. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_DATAOFFSET);
  465. *CurrentDataOffset = *CurrentPosition;
  466. *CurrentPosition+=sizeof(USHORT);
  467. break;
  468. case '5':
  469. //fill in the data offset
  470. ASSERT (SmbGetUshort (*CurrentDataOffset) == MRXSMB_INITIAL_DATAOFFSET);
  471. ByteCount = (USHORT)(*CurrentPosition-BufferBase);
  472. StufferFLoopTrace((" StufferFloop '5' offset=%lu\n",ByteCount));
  473. SmbPutUshort (*CurrentDataOffset, (USHORT)ByteCount);
  474. break;
  475. case 'P':
  476. case 'p':
  477. StufferFLoopTrace((" StufferFloop 'p' \n",0));
  478. SmbPutUshort (*CurrentPosition, (USHORT)MRXSMB_INITIAL_PARAMOFFSET);
  479. *CurrentParamOffset = *CurrentPosition;
  480. *CurrentPosition+=sizeof(USHORT);
  481. break;
  482. case '6':
  483. //fill in the data offset
  484. ASSERT (SmbGetUshort (*CurrentParamOffset) == MRXSMB_INITIAL_PARAMOFFSET);
  485. ByteCount = (USHORT)(*CurrentPosition-BufferBase);
  486. StufferFLoopTrace((" StufferFloop '6' offset=%lu\n",ByteCount));
  487. SmbPutUshort (*CurrentParamOffset, (USHORT)ByteCount);
  488. break;
  489. case 'S':
  490. // pad to ULONG; we loop behind instead of adding so we can clear
  491. // out behind ourselves; apparently, some server croak on nonzero padding
  492. StufferFLoopTrace((" StufferFloop 'S' \n",0));
  493. PreviousPosition = *CurrentPosition;
  494. *CurrentPosition = (PBYTE)QuadAlignPtr(*CurrentPosition);
  495. for (;PreviousPosition!=*CurrentPosition;) {
  496. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  497. *PreviousPosition++ = PADBYTE;
  498. }
  499. break;
  500. case 's':
  501. // pad to arg; we loop behind instead of adding so we can clear
  502. // out behind ourselves; apparently, some server croak on nonzero padding
  503. arg = va_arg(AP,ULONG);
  504. StufferFLoopTrace((" StufferFloop 's' arg=\n",arg));
  505. PreviousPosition = *CurrentPosition;
  506. *CurrentPosition += arg-1;
  507. *CurrentPosition = (PBYTE)( ((ULONG_PTR)(*CurrentPosition)) & ~((LONG)(arg-1)) );
  508. for (;PreviousPosition!=*CurrentPosition;) {
  509. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  510. *PreviousPosition++ = PADBYTE;
  511. }
  512. break;
  513. case '1':
  514. // pad to USHORT; we loop behind instead of adding so we can clear
  515. // out behind ourselves; apparently, some server croak on nonzero padding
  516. StufferFLoopTrace((" StufferFloop '1' Curr=%08lx \n",*CurrentPosition));
  517. PreviousPosition = *CurrentPosition;
  518. *CurrentPosition += sizeof(USHORT)-1;
  519. StufferFLoopTrace((" Curr=%08lx \n",*CurrentPosition));
  520. *CurrentPosition = (PBYTE)( ((ULONG_PTR)(*CurrentPosition)) & ~((LONG)(sizeof(USHORT)-1)) );
  521. StufferFLoopTrace((" Curr=%08lx \n",*CurrentPosition));
  522. for (;PreviousPosition!=*CurrentPosition;) {
  523. StufferFLoopTrace((" StufferFloop '1' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  524. *PreviousPosition++ = PADBYTE;
  525. }
  526. break;
  527. case 'c':
  528. // copy in the bytes....used a lot in transact
  529. CopyCount = va_arg(AP,ULONG);
  530. CopyPtr = va_arg(AP,PBYTE);
  531. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  532. StufferFLoopTrace((" StufferFloop 'c' copycount = %lu\n", CopyCount));
  533. PreviousPosition = *CurrentPosition;
  534. *CurrentPosition += CopyCount;
  535. for (;PreviousPosition!=*CurrentPosition;) {
  536. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  537. *PreviousPosition++ = *CopyPtr++;
  538. }
  539. break;
  540. case 'R':
  541. case 'r':
  542. // copy in the bytes....used a lot in transact
  543. RegionPtr = va_arg(AP,PBYTE*);
  544. CopyCount = va_arg(AP,ULONG);
  545. StufferFLoopTrace((" StufferFloop 'r' regionsize = %lu\n", CopyCount));
  546. *RegionPtr = *CurrentPosition;
  547. *CurrentPosition += CopyCount;
  548. IF_DEBUG {
  549. PreviousPosition = *RegionPtr;
  550. for (;PreviousPosition!=*CurrentPosition;) {
  551. //StufferFLoopTrace((" StufferFloop 'S' prev,curr=%08lx %08lx\n",PreviousPosition,*CurrentPosition));
  552. *PreviousPosition++ = '-';
  553. }
  554. }
  555. break;
  556. case 'A':
  557. case 'a':
  558. //copy byte from an asciiz including the trailing NULL
  559. Astring = va_arg(AP,PSZ);
  560. StufferFLoopTrace((" StufferFloop 'a' stringing = %s\n", Astring));
  561. CopyCount = strlen(Astring)+1;
  562. //if (((ULONG)(*CurrentPosition))&1) {
  563. // StufferFLoopTrace((" StufferFloop 'a' aligning\n", 0));
  564. // *CurrentPosition+=1;
  565. //}
  566. PreviousPosition = *CurrentPosition;
  567. *CurrentPosition += CopyCount;
  568. if (*CurrentPosition >= StufferState->BufferLimit) {
  569. StufferFLoopTrace((" StufferFloop 'a' bufferoverrun\n", 0));
  570. ASSERT(!"BufferOverrun");
  571. return(STATUS_BUFFER_OVERFLOW);
  572. }
  573. RtlCopyMemory(PreviousPosition,Astring,CopyCount);
  574. break;
  575. case 'z':
  576. case '4':
  577. case '>':
  578. Zstring = va_arg(AP,PUNICODE_STRING);
  579. StufferFLoopTrace((" StufferFloop '4/z/>' stringing = %wZ, cp=\n", Zstring,*CurrentPosition ));
  580. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  581. if (CurrentFormatChar=='4') {
  582. //first lay down a x'04' and then copy either a asciiz or a unicodez depending on the flags setting
  583. **CurrentPosition = (UCHAR)4; //ascii marker
  584. *CurrentPosition+=1;
  585. } else if (CurrentFormatChar=='>'){
  586. //back up over the previous NULL
  587. *CurrentPosition-=(FlagOn(SmbHeader->Flags2,SMB_FLAGS2_UNICODE)?sizeof(WCHAR):sizeof(char));
  588. StufferFLoopTrace((" StufferFloop '4/z/>' afterroolback, cp=\n", *CurrentPosition ));
  589. }
  590. if (FlagOn(SmbHeader->Flags2,SMB_FLAGS2_UNICODE)){
  591. if (((ULONG_PTR)(*CurrentPosition))&1) {
  592. StufferFLoopTrace((" StufferFloop '4/z/>' aligning\n", 0));
  593. *CurrentPosition+=1;
  594. }
  595. PreviousPosition = *CurrentPosition;
  596. *CurrentPosition += (Zstring->Length + sizeof(WCHAR));
  597. if (*CurrentPosition >= StufferState->BufferLimit) {
  598. StufferFLoopTrace((" StufferFloop '4/z/>' bufferoverrun\n", 0));
  599. ASSERT(!"BufferOverrun");
  600. return(STATUS_BUFFER_OVERFLOW);
  601. }
  602. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  603. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  604. } else {
  605. NTSTATUS Status;
  606. OEM_STRING OemString;
  607. OemString.Length =
  608. OemString.MaximumLength =
  609. (USHORT)( StufferState->BufferLimit - *CurrentPosition - sizeof(CHAR));
  610. OemString.Buffer = *CurrentPosition;
  611. if (FlagOn(SmbHeader->Flags,SMB_FLAGS_CASE_INSENSITIVE) &&
  612. !FlagOn(SmbHeader->Flags2,SMB_FLAGS2_KNOWS_LONG_NAMES)) {
  613. Status = RtlUpcaseUnicodeStringToOemString(
  614. &OemString,
  615. Zstring,
  616. FALSE);
  617. } else {
  618. Status = RtlUnicodeStringToOemString(
  619. &OemString,
  620. Zstring,
  621. FALSE);
  622. }
  623. if (!NT_SUCCESS(Status)) {
  624. StufferFLoopTrace((" StufferFloop '4/z/>' bufferoverrun(ascii)\n", 0));
  625. ASSERT(!"BufferOverrun");
  626. return(STATUS_BUFFER_OVERFLOW);
  627. }
  628. *CurrentPosition += OemString.Length + 1;
  629. *(*CurrentPosition-1) = 0;
  630. }
  631. break;
  632. case 'U':
  633. case 'u':
  634. //copy bytes from an UNICODE string including a trailing NULL
  635. Zstring = va_arg(AP,PUNICODE_STRING);
  636. StufferFLoopTrace((" StufferFloop 'u' stringing = %wZ\n", Zstring));
  637. if (((ULONG_PTR)(*CurrentPosition))&1) {
  638. StufferFLoopTrace((" StufferFloop 'u' aligning\n", 0));
  639. *CurrentPosition+=1;
  640. }
  641. PreviousPosition = *CurrentPosition;
  642. *CurrentPosition += (Zstring->Length + sizeof(WCHAR));
  643. if (*CurrentPosition >= StufferState->BufferLimit) {
  644. StufferFLoopTrace((" StufferFloop 'u' bufferoverrun\n", 0));
  645. return(STATUS_BUFFER_OVERFLOW);
  646. }
  647. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  648. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  649. break;
  650. case 'V':
  651. case 'v':
  652. //copy bytes from an UNICODE string no trailing NUL
  653. Zstring = va_arg(AP,PUNICODE_STRING);
  654. StufferFLoopTrace((" StufferFloop 'v' stringing = %wZ\n", Zstring));
  655. if (((ULONG_PTR)(*CurrentPosition))&1) {
  656. StufferFLoopTrace((" StufferFloop 'v' aligning\n", 0));
  657. *CurrentPosition+=1;
  658. }
  659. PreviousPosition = *CurrentPosition;
  660. *CurrentPosition += Zstring->Length;
  661. if (*CurrentPosition >= StufferState->BufferLimit) {
  662. StufferFLoopTrace((" StufferFloop 'v' bufferoverrun\n", 0));
  663. ASSERT(!"BufferOverrun");
  664. return(STATUS_BUFFER_OVERFLOW);
  665. }
  666. RtlCopyMemory(PreviousPosition,Zstring->Buffer,Zstring->Length);
  667. break;
  668. case 'N':
  669. case 'n':
  670. //copy bytes from a NetRoot name....w null
  671. NetRoot = va_arg(AP,PNET_ROOT);
  672. ASSERT(NodeType(NetRoot)==RDBSS_NTC_NETROOT);
  673. Zstring = &NetRoot->PrefixEntry.Prefix;
  674. StufferFLoopTrace((" StufferFloop 'n' stringing = %wZ\n", Zstring));
  675. if (StufferState->Flags2Copy&SMB_FLAGS2_UNICODE) {
  676. if (((ULONG_PTR)(*CurrentPosition))&1) {
  677. StufferFLoopTrace((" StufferFloop 'n' aligning\n", 0));
  678. *CurrentPosition+=1;
  679. }
  680. PreviousPosition = *CurrentPosition;
  681. *CurrentPosition += (Zstring->Length + 2 * sizeof(WCHAR)); //extra \ plus a nul
  682. if (*CurrentPosition >= StufferState->BufferLimit) {
  683. StufferFLoopTrace((" StufferFloop 'n' bufferoverrun\n", 0));
  684. ASSERT(!"BufferOverrun");
  685. return(STATUS_BUFFER_OVERFLOW);
  686. }
  687. *((PWCHAR)PreviousPosition) = '\\';
  688. RtlCopyMemory(PreviousPosition+sizeof(WCHAR),Zstring->Buffer,Zstring->Length);
  689. *(((PWCHAR)(*CurrentPosition))-1) = 0;
  690. }
  691. break;
  692. case '?':
  693. //early out....used in transact to do the setup
  694. EarlyReturn = va_arg(AP,ULONG);
  695. StufferFLoopTrace((" StufferFloop '?' out if 0==%08lx\n",EarlyReturn));
  696. if (EarlyReturn==0) return STATUS_SUCCESS;
  697. break;
  698. case '.':
  699. //noop...used to reenter without a real formatting string
  700. StufferFLoopTrace((" StufferFloop '.'\n",0));
  701. break;
  702. case '!':
  703. if (CurrentStufferControl == STUFFER_CTL_SKIP) break;
  704. ASSERT (SmbGetUshort (*CurrentBcc) == MRXSMB_INITIAL_BCC);
  705. ByteCount = (USHORT)(*CurrentPosition-*CurrentBcc-sizeof(USHORT));
  706. StufferFLoopTrace((" StufferFloop '!' arg=%lu\n",ByteCount));
  707. SmbPutUshort (*CurrentBcc, (USHORT)ByteCount);
  708. return STATUS_SUCCESS;
  709. default:
  710. StufferFLoopTrace((" StufferFloop '%c' BADBADBAD\n",*CurrentFormatString));
  711. ASSERT(!"Illegal Controlstring character\n");
  712. } //switch
  713. }//for
  714. break;
  715. case 0:
  716. return STATUS_SUCCESS;
  717. default:
  718. StufferCLoopTrace((" StufferCloop %u BADBADBAD\n",CurrentStufferControl));
  719. ASSERT(!"IllegalStufferControl\n");
  720. }//switch
  721. CurrentStufferControl = va_arg(AP,SMB_STUFFER_CONTROLS);
  722. StufferCLoopTrace((" StufferCloop NewStufferControl=%u \n",CurrentStufferControl));
  723. } //for
  724. return STATUS_SUCCESS;
  725. }
  726. VOID
  727. MRxSmbStuffAppendRawData(
  728. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  729. IN PMDL Mdl
  730. )
  731. {
  732. PMDL pMdl;
  733. PAGED_CODE();
  734. ASSERT(!StufferState->DataMdl);
  735. pMdl = StufferState->DataMdl = Mdl;
  736. StufferState->DataSize = 0;
  737. while (pMdl != NULL) {
  738. StufferState->DataSize += pMdl->ByteCount;
  739. pMdl = pMdl->Next;
  740. }
  741. return;
  742. }
  743. VOID
  744. MRxSmbStuffAppendSmbData(
  745. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState,
  746. IN PMDL Mdl
  747. )
  748. {
  749. ULONG Offset;
  750. PAGED_CODE();
  751. ASSERT(!StufferState->DataMdl);
  752. StufferState->DataMdl = Mdl;
  753. StufferState->DataSize = Mdl->ByteCount;
  754. //now reach back into the buffer and set the SMB data offset; if it is already set...just get out
  755. if (SmbGetUshort (StufferState->CurrentDataOffset) == MRXSMB_INITIAL_DATAOFFSET){
  756. Offset = (ULONG)(StufferState->CurrentPosition - StufferState->BufferBase);
  757. RxDbgTrace(0, Dbg,("MRxSmbStuffAppendSmbData offset=%lu\n",Offset));
  758. SmbPutUshort (StufferState->CurrentDataOffset, (USHORT)Offset);
  759. }
  760. return;
  761. }
  762. VOID
  763. MRxSmbStuffSetByteCount(
  764. IN OUT PSMBSTUFFER_BUFFER_STATE StufferState
  765. )
  766. {
  767. ULONG ByteCount;
  768. PAGED_CODE();
  769. ASSERT (SmbGetUshort (StufferState->CurrentBcc) == MRXSMB_INITIAL_BCC);
  770. ByteCount = (ULONG)(StufferState->CurrentPosition
  771. - StufferState->CurrentBcc
  772. - sizeof(USHORT)
  773. + StufferState->DataSize);
  774. RxDbgTrace(0, Dbg,("MRxSmbStuffSetByteCount ByteCount=%lu\n",ByteCount));
  775. SmbPutUshort (StufferState->CurrentBcc, (USHORT)ByteCount);
  776. return;
  777. }
  778.