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.

2173 lines
80 KiB

  1. /*++
  2. Copyright (c) 1989 - 1999 Microsoft Corporation
  3. Module Name:
  4. DownLvlI.c
  5. Abstract:
  6. This module implements downlevel fileinfo, volinfo, and dirctrl.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #ifdef ALLOC_PRAGMA
  11. #pragma alloc_text(PAGE, MRxSmbFabricateAttributesOnNetRoot)
  12. #pragma alloc_text(PAGE, MRxSmbCoreInformation)
  13. #pragma alloc_text(PAGE, MRxSmbLoadCoreFileSearchBuffer)
  14. #pragma alloc_text(PAGE, MRxSmbCoreFileSearch)
  15. #pragma alloc_text(PAGE, MrxSmbOemVolumeInfoToUnicode)
  16. #pragma alloc_text(PAGE, MrxSmbCoreQueryFsVolumeInfo)
  17. #pragma alloc_text(PAGE, MrxSmbQueryFsVolumeInfo)
  18. #pragma alloc_text(PAGE, MrxSmbCoreQueryDiskAttributes)
  19. #pragma alloc_text(PAGE, MrxSmbCoreQueryDiskAttributes)
  20. #pragma alloc_text(PAGE, SmbPseExchangeStart_CoreInfo)
  21. #pragma alloc_text(PAGE, MRxSmbFinishSearch)
  22. #pragma alloc_text(PAGE, MRxSmbFinishQueryDiskInfo)
  23. #pragma alloc_text(PAGE, MRxSmbExtendForCache)
  24. #pragma alloc_text(PAGE, MRxSmbExtendForNonCache)
  25. #pragma alloc_text(PAGE, MRxSmbGetNtAllocationInfo)
  26. #pragma alloc_text(PAGE, __MRxSmbSimpleSyncTransact2)
  27. #pragma alloc_text(PAGE, MRxSmbFinishTransaction2)
  28. #endif
  29. #define Dbg (DEBUG_TRACE_VOLINFO)
  30. //#define FORCE_CORE_GETATTRIBUTES
  31. #ifndef FORCE_CORE_GETATTRIBUTES
  32. #define MRxSmbForceCoreGetAttributes FALSE
  33. #else
  34. BOOLEAN MRxSmbForceCoreGetAttributes = TRUE;
  35. #endif
  36. NTSTATUS
  37. SmbPseExchangeStart_CoreInfo(
  38. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  39. );
  40. //these structures are used for t2_query_fs_info
  41. typedef
  42. struct _QFS_INFO {
  43. ULONG ulVSN;
  44. UCHAR cch;
  45. CHAR szVolLabel[12]; //not unicode
  46. } QFS_INFO, *PQFS_INFO;
  47. #define ACTUAL_QFS_INFO_LENGTH (FIELD_OFFSET(QFS_INFO,szVolLabel[12]))
  48. typedef
  49. struct _QFS_ALLOCATE {
  50. ULONG ulReserved;
  51. ULONG cSectorUnit;
  52. ULONG cUnit;
  53. ULONG cUnitAvail;
  54. USHORT cbSector;
  55. } QFS_ALLOCATE, *PQFS_ALLOCATE;
  56. #define ACTUAL_QFS_ALLOCATE_LENGTH (FIELD_OFFSET(QFS_ALLOCATE,cbSector)+sizeof(((PQFS_ALLOCATE)0)->cbSector))
  57. //++
  58. //
  59. // VOID
  60. // NAME_LENGTH(
  61. // OUT ULONG Length,
  62. // IN PUCHAR Ptr
  63. // )
  64. //
  65. // Routine Description:
  66. //
  67. // Determines the length of a Core filename returned by search. This
  68. // is normally a NULL terminated string less than MAXIMUM_COMPONENT_CORE.
  69. // In some cases this is Non-null teminated and space filled.
  70. //
  71. // Arguments:
  72. //
  73. // Length - Returns the string length
  74. // Ptr - The filename to be measured
  75. //
  76. // Return Value:
  77. //
  78. // None.
  79. //
  80. //--
  81. #define NAME_LENGTH( Length, Ptr, Max ) { \
  82. Length = 0; \
  83. while( ((PCHAR)Ptr)[Length] != '\0' ) { \
  84. Length++; \
  85. if ( Length == Max ) { \
  86. break; \
  87. } \
  88. } \
  89. while( ((PCHAR)Ptr)[Length-1] == ' ' && Length ) { \
  90. Length--; \
  91. } \
  92. }
  93. MRxSmbSetDeleteDisposition(
  94. IN PRX_CONTEXT RxContext
  95. );
  96. typedef struct __NativeFs_Name_Entry {
  97. UCHAR Last;
  98. UCHAR MaximumComponentNameLength;
  99. UCHAR FileSystemAttributes; //this may overflow someday.....
  100. UCHAR NameLength;
  101. PWCHAR Name;
  102. };
  103. struct __NativeFs_Name_Entry NativeFsNameTable[] = {
  104. {0,12,0,sizeof(L"FAT")-sizeof(WCHAR),L"FAT"},
  105. {0,254,FILE_CASE_PRESERVED_NAMES,sizeof(L"HPFS")-sizeof(WCHAR),L"HPFS"},
  106. {1,254,FILE_CASE_PRESERVED_NAMES,sizeof(L"HPFS386")-sizeof(WCHAR),L"HPFS386"}
  107. };
  108. NTSTATUS
  109. MRxSmbFabricateAttributesOnNetRoot(
  110. IN OUT PSMBCE_NET_ROOT psmbNetRoot,
  111. IN PSMBCE_SERVER pServer
  112. )
  113. /*++
  114. Routine Description:
  115. This routine uses information stored in the netroot structure to hallucinate the attributes
  116. of the netroot. it may be that the ascii representation of the filesystem name has already been
  117. stored in the netroot. If so, expeand it out.....otherwise, it must be FAT.
  118. Arguments:
  119. Return Value:
  120. RXSTATUS - STATUS_SUCCESS
  121. --*/
  122. {
  123. NTSTATUS StringStatus;
  124. WCHAR FileSystemNameBuffer[SMB_MAXIMUM_SUPPORTED_VOLUME_LABEL+1]; //must leave room for the null
  125. UNICODE_STRING FileSystemNameU;
  126. OEM_STRING FileSystemNameA;
  127. UCHAR FileSystemNameALength;
  128. PAGED_CODE();
  129. // ASSERT (psmbNetRoot->MaximumComponentNameLength==0);
  130. FileSystemNameALength = psmbNetRoot->FileSystemNameALength;
  131. if (FileSystemNameALength == 0) {
  132. if (pServer->Dialect <= WFW10_DIALECT)
  133. {
  134. //must be Fat!
  135. FileSystemNameALength = 3;
  136. psmbNetRoot->FileSystemNameA[0] = 'F';
  137. psmbNetRoot->FileSystemNameA[1] = 'A';
  138. psmbNetRoot->FileSystemNameA[2] = 'T';
  139. }
  140. else
  141. {
  142. FileSystemNameALength = 7;
  143. psmbNetRoot->FileSystemNameA[0] = 'U';
  144. psmbNetRoot->FileSystemNameA[1] = 'N';
  145. psmbNetRoot->FileSystemNameA[2] = 'K';
  146. psmbNetRoot->FileSystemNameA[3] = 'N';
  147. psmbNetRoot->FileSystemNameA[4] = 'O';
  148. psmbNetRoot->FileSystemNameA[5] = 'W';
  149. psmbNetRoot->FileSystemNameA[6] = 'N';
  150. }
  151. }
  152. //now, translate the name to Unicode.......
  153. FileSystemNameA.Length = FileSystemNameALength;
  154. FileSystemNameA.MaximumLength = FileSystemNameALength;
  155. FileSystemNameA.Buffer = &psmbNetRoot->FileSystemNameA[0];
  156. FileSystemNameU.Length = 0;
  157. FileSystemNameU.MaximumLength = (USHORT)sizeof(FileSystemNameBuffer);
  158. FileSystemNameU.Buffer = &FileSystemNameBuffer[0];
  159. StringStatus = RtlOemStringToUnicodeString(&FileSystemNameU, &FileSystemNameA, FALSE);
  160. ASSERT(StringStatus==STATUS_SUCCESS);
  161. //copy back the name
  162. RtlCopyMemory(&psmbNetRoot->FileSystemName[0],FileSystemNameU.Buffer,FileSystemNameU.Length);
  163. psmbNetRoot->FileSystemNameLength = FileSystemNameU.Length;
  164. if (FALSE) DbgPrint("NativeFs in unicode %wZ (%d/%d) on netroot %08lx\n",
  165. &FileSystemNameU,FileSystemNameU.Length,FileSystemNameU.MaximumLength,psmbNetRoot);
  166. { struct __NativeFs_Name_Entry *i;
  167. for (i=NativeFsNameTable;;i++) {
  168. UCHAR NameLength = i->NameLength;
  169. if (RtlCompareMemory(&FileSystemNameBuffer[0],
  170. i->Name,
  171. NameLength) == NameLength) {
  172. psmbNetRoot->MaximumComponentNameLength = i->MaximumComponentNameLength;
  173. psmbNetRoot->FileSystemAttributes = i->FileSystemAttributes;
  174. if (FALSE) {
  175. UNICODE_STRING u;
  176. u.Buffer = i->Name;
  177. u.Length = i->NameLength;
  178. DbgPrint("FoundNativeFsStrng %wZ len %d for %d %d\n",&u,i->NameLength,
  179. i->MaximumComponentNameLength,i->FileSystemAttributes);
  180. }
  181. break;
  182. }
  183. if (i->Last) {
  184. //ASSERT(!"Valid Share Type returned in TREE COnnect And X response");
  185. psmbNetRoot->MaximumComponentNameLength = 255;
  186. psmbNetRoot->FileSystemAttributes = 0;
  187. break;
  188. }
  189. }
  190. }
  191. return(STATUS_SUCCESS); //could be a VOID routine.....
  192. }
  193. NTSTATUS
  194. MRxSmbGetFsAttributesFromNetRoot(
  195. IN OUT PRX_CONTEXT RxContext
  196. )
  197. /*++
  198. Routine Description:
  199. This routine uses information stored in the netroot structure to fill in a FILE
  200. FileFsAttributeInformation structure.
  201. Arguments:
  202. Return Value:
  203. RXSTATUS - STATUS_SUCCESS
  204. --*/
  205. {
  206. RxCaptureFcb;
  207. ULONG FileSystemNameLength,LengthNeeded;
  208. PSMBCEDB_NET_ROOT_ENTRY pNetRootEntry;
  209. PSMBCE_NET_ROOT psmbNetRoot;
  210. //FILE_INFORMATION_CLASS FileInformationClass;
  211. PBYTE pBuffer;
  212. PULONG pBufferLength;
  213. //DbgPrint("yeppp!!\n");
  214. pNetRootEntry = SmbCeGetAssociatedNetRootEntry(capFcb->pNetRoot);
  215. if (pNetRootEntry == NULL) {
  216. return (STATUS_INVALID_PARAMETER);
  217. }
  218. ASSERT(RxContext->MajorFunction==IRP_MJ_QUERY_VOLUME_INFORMATION);
  219. //FileInformationClass = RxContext->Info.FileInformationClass;
  220. ASSERT(RxContext->Info.FileInformationClass==FileFsAttributeInformation);
  221. pBuffer = RxContext->Info.Buffer;
  222. pBufferLength = &RxContext->Info.LengthRemaining;
  223. psmbNetRoot = &pNetRootEntry->NetRoot;
  224. if (psmbNetRoot->MaximumComponentNameLength==0) {
  225. MRxSmbFabricateAttributesOnNetRoot(psmbNetRoot, &pNetRootEntry->pServerEntry->Server);
  226. }
  227. FileSystemNameLength = psmbNetRoot->FileSystemNameLength;
  228. LengthNeeded = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName)+FileSystemNameLength;
  229. if (*pBufferLength < LengthNeeded) {
  230. return (STATUS_BUFFER_OVERFLOW);
  231. }
  232. {
  233. PFILE_FS_ATTRIBUTE_INFORMATION pTypedBuffer = (PFILE_FS_ATTRIBUTE_INFORMATION)pBuffer;
  234. pTypedBuffer->MaximumComponentNameLength = psmbNetRoot->MaximumComponentNameLength;
  235. pTypedBuffer->FileSystemAttributes = psmbNetRoot->FileSystemAttributes;
  236. pTypedBuffer->FileSystemNameLength = FileSystemNameLength;
  237. RtlCopyMemory(pTypedBuffer->FileSystemName, psmbNetRoot->FileSystemName, FileSystemNameLength);
  238. *pBufferLength -= LengthNeeded;
  239. }
  240. return(STATUS_SUCCESS);
  241. }
  242. NTSTATUS
  243. MRxSmbCoreInformation(
  244. IN OUT PRX_CONTEXT RxContext,
  245. IN ULONG InformationClass,
  246. IN OUT PVOID pBuffer,
  247. IN OUT PULONG pBufferLength,
  248. IN SMB_PSE_ORDINARY_EXCHANGE_ENTRYPOINTS EntryPoint
  249. )
  250. /*++
  251. Routine Description:
  252. This routine does a core level getinfo (vol or fileinfo) a file across the network
  253. Arguments:
  254. RxContext - the RDBSS context
  255. InformationClass - a class variable that is specific to the call. sometimes it's a SMB class; sometimes
  256. an NT class.
  257. pBuffer - pointer to the user's buffer
  258. pBufferLength - a pointer to a ulong containing the bufferlength that is updated as we go;
  259. if it's a setinfo then we deref and place the actual bufferlength in the OE.
  260. Return Value:
  261. RXSTATUS - The return status for the operation
  262. --*/
  263. {
  264. NTSTATUS Status = (STATUS_SUCCESS);
  265. PUNICODE_STRING RemainingName;
  266. RxCaptureFcb; RxCaptureFobx;
  267. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  268. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  269. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange;
  270. PAGED_CODE();
  271. RxDbgTrace(0, Dbg, ("MRxSmbDownLevelQueryInformation\n", 0 )); //0 instead of +1.....the general entrypoint already inc'd
  272. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  273. //some stuff is early out............catch them here even before we initialize the stufferstate
  274. switch (EntryPoint) {
  275. case SMBPSE_OE_FROM_QUERYVOLUMEINFO:
  276. switch (InformationClass) {
  277. case FileFsVolumeInformation:
  278. case FileFsSizeInformation:
  279. break; //these are actually implemented on the wire
  280. case FileFsAttributeInformation: {
  281. Status = MRxSmbGetFsAttributesFromNetRoot(RxContext);
  282. goto FINALLY;
  283. }
  284. //no break needed because of gotofinally
  285. case FileFsDeviceInformation:
  286. ASSERT(!"this should have been turned away");
  287. //no break;
  288. default:
  289. Status = STATUS_NOT_IMPLEMENTED;
  290. goto FINALLY;
  291. }
  292. break;
  293. case SMBPSE_OE_FROM_QUERYFILEINFO:
  294. //notice that the designators are smb_query_info types
  295. switch (InformationClass) {
  296. case SMB_QUERY_FILE_BASIC_INFO:
  297. case SMB_QUERY_FILE_STANDARD_INFO:
  298. // go thru to the wire or get it from file information cache
  299. break;
  300. case SMB_QUERY_FILE_EA_INFO:
  301. //downlevel guys have no EAs....turn this backright here
  302. ((PFILE_EA_INFORMATION)pBuffer)->EaSize = 0;
  303. *pBufferLength -= sizeof(FILE_EA_INFORMATION);
  304. goto FINALLY;
  305. //case SMB_QUERY_FILE_ALLOCATION_INFO:
  306. //case SMB_QUERY_FILE_END_OF_FILEINFO:
  307. //case SMB_QUERY_FILE_ALT_NAME_INFO:
  308. //case SMB_QUERY_FILE_STREAM_INFO:
  309. default:
  310. Status = STATUS_NOT_IMPLEMENTED;
  311. goto FINALLY;
  312. }
  313. break;
  314. case SMBPSE_OE_FROM_SETFILEINFO:
  315. switch (InformationClass) {
  316. case FileBasicInformation:
  317. case FileEndOfFileInformation:
  318. //these go thru to the wire
  319. break;
  320. case FileDispositionInformation:
  321. if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_FILE_DELETED) ||
  322. !FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_NOT_REALLY_OPEN)) {
  323. // if it is a pseudo open, we send the delete file request to get the result;
  324. // otherwise, we delay the delete until close.
  325. goto FINALLY;
  326. }
  327. break;
  328. case FileRenameInformation:
  329. Status = MRxSmbRename(RxContext);
  330. goto FINALLY;
  331. case FileAllocationInformation:
  332. Status = STATUS_SUCCESS;
  333. goto FINALLY;
  334. default:
  335. Status = STATUS_NOT_IMPLEMENTED;
  336. goto FINALLY;
  337. }
  338. break;
  339. case SMBPSE_OE_FROM_EXTENDFILEFORCACHEING:
  340. case SMBPSE_OE_FROM_QUERYDIRECTORY:
  341. break;
  342. }
  343. Status = SmbPseCreateOrdinaryExchange(RxContext,
  344. SrvOpen->pVNetRoot,
  345. EntryPoint,
  346. SmbPseExchangeStart_CoreInfo,
  347. &OrdinaryExchange
  348. );
  349. if (Status != STATUS_SUCCESS) {
  350. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  351. goto FINALLY;
  352. }
  353. OrdinaryExchange->Info.Buffer = pBuffer;
  354. OrdinaryExchange->Info.pBufferLength = pBufferLength;
  355. OrdinaryExchange->Info.InfoClass = InformationClass;
  356. Status = SmbPseInitiateOrdinaryExchange(OrdinaryExchange);
  357. ASSERT (Status != (STATUS_PENDING)); //async was turned away at the top level
  358. SmbPseFinalizeOrdinaryExchange(OrdinaryExchange);
  359. FINALLY:
  360. RxDbgTrace(-1, Dbg, ("MRxSmbDownLevelQueryInformation exit with status=%08lx\n", Status ));
  361. return(Status);
  362. }
  363. UNICODE_STRING MRxSmbAll8dot3Files = {sizeof(L"????????.???")-sizeof(WCHAR),sizeof(L"????????.???"),L"????????.???"};
  364. #if 0
  365. #include "stdarg.h"
  366. #include "stdio.h"
  367. #include "string.h"
  368. VOID
  369. MRxSmbDumpResumeKey(
  370. PSZ text,
  371. PSMB_RESUME_KEY ResumeKey
  372. )
  373. {
  374. PBYTE rk = (PBYTE)ResumeKey;
  375. CHAR Buffer[80];
  376. PCHAR b;
  377. ULONG i;
  378. PAGED_CODE();
  379. for (i=0,b=Buffer;i<sizeof(SMB_RESUME_KEY);i++,b+=2) {
  380. RxSprintf(b,"%02lx ",rk[i]);
  381. if (i==0) b+=2;
  382. if (i==11) b+=2;
  383. if (i==16) b+=2;
  384. }
  385. RxDbgTrace(0, Dbg, ("%s rk(%08lx)=%s\n", text, ResumeKey, Buffer));
  386. }
  387. #else
  388. #define MRxSmbDumpResumeKey(x,y)
  389. #endif
  390. NTSTATUS
  391. MRxSmbLoadCoreFileSearchBuffer(
  392. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  393. )
  394. /*++
  395. Routine Description:
  396. This routine does a CORE_SMB_SEARCH and leaves the result in the SMBbuf.
  397. Arguments:
  398. OrdinaryExchange - an exchange to be used for conducting this open.
  399. Return Value:
  400. RXSTATUS - The return status for the operation
  401. Notes:
  402. --*/
  403. {
  404. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  405. RxCaptureFcb; RxCaptureFobx;
  406. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  407. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  408. PSMBSTUFFER_BUFFER_STATE StufferState;
  409. PSMB_HEADER SmbHeader;
  410. //PUNICODE_STRING DirectoryName;
  411. //PUNICODE_STRING Template;
  412. BOOLEAN FindFirst;
  413. UNICODE_STRING FindFirstPattern;
  414. USHORT ResumeKeyLength;
  415. ULONG ReturnCount;
  416. BOOLEAN EndOfSearchReached;
  417. // SearchAttributes is hardcoded to the magic number 0x16
  418. ULONG SearchAttributes =
  419. (SMB_FILE_ATTRIBUTE_DIRECTORY
  420. | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN);
  421. PULONG pCountRemainingInSmbbuf = &OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf;
  422. PAGED_CODE();
  423. RxDbgTrace(+1, Dbg, ("MRxSmbLoadCoreFileSearchBuffer entering.......OE=%08lx\n",OrdinaryExchange));
  424. RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.CoreResumeKey));
  425. if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST)) {
  426. PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME(capFobx->pSrvOpen,capFcb);
  427. PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
  428. ULONG DirectoryNameLength,TemplateLength,AllocationLength;
  429. PBYTE SmbFileName;
  430. //this is the first time thru....the stuffer cannot handle the intricate logic here so we
  431. //will have to preallocate for the name
  432. if (smbFobx->Enumeration.WildCardsFound = FsRtlDoesNameContainWildCards(Template)){
  433. // we will need to have an upcased template for compares; we do this in place
  434. RtlUpcaseUnicodeString( Template, Template, FALSE );
  435. Template = &MRxSmbAll8dot3Files; //we will have to filter on this side
  436. }
  437. DirectoryNameLength = DirectoryName->Length;
  438. TemplateLength = Template->Length;
  439. AllocationLength = sizeof(WCHAR) // backslash separator
  440. +DirectoryNameLength
  441. +TemplateLength;
  442. RxDbgTrace(0, Dbg, (" --> d/t/dl/tl/al <%wZ><%wZ>%08lx/%08lx/%08lx!\n",
  443. DirectoryName,Template,
  444. DirectoryNameLength,TemplateLength,AllocationLength));
  445. FindFirstPattern.Buffer = (PWCHAR)RxAllocatePoolWithTag( PagedPool,AllocationLength,'0SxR');
  446. if (FindFirstPattern.Buffer==NULL) {
  447. RxDbgTrace(0, Dbg, (" --> Couldn't get the findfind pattern buffer!\n"));
  448. Status = STATUS_INSUFFICIENT_RESOURCES;
  449. goto FINALLY;
  450. }
  451. SmbFileName = (PBYTE)FindFirstPattern.Buffer;
  452. RtlCopyMemory(SmbFileName,DirectoryName->Buffer,DirectoryNameLength);
  453. SmbFileName += DirectoryNameLength;
  454. if (*((PWCHAR)(SmbFileName-sizeof(WCHAR))) != L'\\') {
  455. *((PWCHAR)SmbFileName) = L'\\'; SmbFileName+= sizeof(WCHAR);
  456. }
  457. RtlCopyMemory(SmbFileName,Template->Buffer,TemplateLength);
  458. SmbFileName += TemplateLength;
  459. if ((TemplateLength == sizeof(WCHAR)) && (Template->Buffer[0]==DOS_STAR)) {
  460. ASSERT(FALSE); //this should never happen
  461. *((PWCHAR)SmbFileName) = L'.'; SmbFileName+= sizeof(WCHAR);
  462. *((PWCHAR)SmbFileName) = L'*'; SmbFileName+= sizeof(WCHAR);
  463. }
  464. FindFirstPattern.Length = (USHORT)(SmbFileName - (PBYTE)FindFirstPattern.Buffer);
  465. RxDbgTrace(0, Dbg, (" --> find1stpattern <%wZ>!\n",&FindFirstPattern));
  466. FindFirst = TRUE;
  467. ResumeKeyLength = 0;
  468. } else {
  469. RxDbgTrace(0, Dbg, ("-->FINDNEXT\n"));
  470. FindFirstPattern.Buffer = NULL;
  471. if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS)) {
  472. Status = smbFobx->Enumeration.ErrorStatus;
  473. RxDbgTrace(0, Dbg, ("-->ERROR EARLY OUT\n"));
  474. goto FINALLY;
  475. }
  476. FindFirst = FALSE;
  477. FindFirstPattern.Length = 0;
  478. ResumeKeyLength = sizeof(SMB_RESUME_KEY);
  479. MRxSmbDumpResumeKey("FindNext:",smbFobx->Enumeration.CoreResumeKey);
  480. }
  481. //get the correct return count. there are three factors: countremaining from the OE,
  482. // how many could fit the the user's buffer, and how many could fit in a negotiated buffer.
  483. // we pick the smallest of the three except that we never go for less than 10 unless 10 won't
  484. // fit in the smbbuf.
  485. ReturnCount = OrdinaryExchange->Info.CoreSearch.CountRemaining;
  486. { ULONG t = (*OrdinaryExchange->Info.pBufferLength) / smbFobx->Enumeration.FileNameOffset;
  487. if (t<ReturnCount) { ReturnCount = t; }
  488. }
  489. if (ReturnCount<10) { ReturnCount = 10; }
  490. {
  491. PSMBCE_SERVER pServer;
  492. ULONG AvailableBufferSize,t;
  493. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  494. AvailableBufferSize = pServer->MaximumBufferSize -
  495. (sizeof(SMB_HEADER) +
  496. FIELD_OFFSET(RESP_SEARCH,Buffer[0])
  497. +sizeof(UCHAR)+sizeof(USHORT) //bufferformat,datalength fields
  498. );
  499. t = AvailableBufferSize / sizeof(SMB_DIRECTORY_INFORMATION);
  500. if (t<ReturnCount) { ReturnCount = t; }
  501. }
  502. RxDbgTrace( 0, Dbg, ("-------->count=%08lx\n",ReturnCount));
  503. if (ReturnCount==0) {
  504. Status = (STATUS_MORE_PROCESSING_REQUIRED);
  505. RxDbgTrace(0, Dbg, ("-->Count==0 EARLY OUT\n"));
  506. goto FINALLY;
  507. }
  508. StufferState = &OrdinaryExchange->AssociatedStufferState;
  509. ASSERT( StufferState );
  510. *pCountRemainingInSmbbuf = 0;
  511. OrdinaryExchange->Info.CoreSearch.NextDirInfo = NULL;
  512. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,
  513. SMB_COM_SEARCH, SMB_REQUEST_SIZE(SEARCH),
  514. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  515. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  516. );
  517. RxDbgTrace(0, Dbg,("core search command initial status = %lu\n",Status));
  518. MRxSmbDumpStufferState (1100,"SMB w/ core search before stuffing",StufferState);
  519. MRxSmbStuffSMB (StufferState,
  520. "0wwB4ywc!",
  521. // 0 UCHAR WordCount; // Count of parameter words = 2
  522. ReturnCount, // w _USHORT( MaxCount ); // Number of dir. entries to return
  523. SearchAttributes, // w _USHORT( SearchAttributes );
  524. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
  525. // UCHAR Buffer[1]; // Buffer containing:
  526. &FindFirstPattern, // 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
  527. // //UCHAR FileName[]; // File name, may be null
  528. 0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
  529. ResumeKeyLength, // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
  530. // c //UCHAR SearchStatus[]; // Resume key
  531. ResumeKeyLength,smbFobx->Enumeration.CoreResumeKey
  532. );
  533. MRxSmbDumpStufferState (700,"SMB w/ core search after stuffing",StufferState);
  534. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  535. SMBPSE_OETYPE_CORESEARCH
  536. );
  537. if (!NT_SUCCESS(Status)) goto FINALLY;
  538. smbFobx->Enumeration.Flags |= SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST|SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  539. if (Status==(STATUS_SUCCESS) && *pCountRemainingInSmbbuf==0) {
  540. RxDbgTrace( 0, Dbg, ("MRxSmbLoadCoreFileSearchBuffer: no files returned...switch status\n"));
  541. EndOfSearchReached = TRUE;
  542. Status = (STATUS_NO_MORE_FILES);
  543. } else {
  544. EndOfSearchReached = FALSE;
  545. }
  546. if (EndOfSearchReached) {
  547. RxDbgTrace( 0, Dbg, ("MRxSmbLoadCoreFileSearchBuffer: no longer in progress...EOS\n"));
  548. smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  549. smbFobx->Enumeration.ErrorStatus = (STATUS_NO_MORE_FILES);
  550. }
  551. //we dont save a resume key here since each individual copy operation will have to do that
  552. FINALLY:
  553. if (FindFirstPattern.Buffer != NULL) {
  554. RxFreePool(FindFirstPattern.Buffer);
  555. }
  556. if (!NT_SUCCESS(Status)&&(Status!=(STATUS_MORE_PROCESSING_REQUIRED))) {
  557. RxDbgTrace( 0, Dbg, ("MRxSmbCoreFileSearch: Failed .. returning %lx\n",Status));
  558. smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  559. smbFobx->Enumeration.ErrorStatus = Status; //keep returning this
  560. }
  561. RxDbgTrace(-1, Dbg, ("MRxSmbLoadCoreFileSearchBuffer exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  562. return(Status);
  563. }
  564. #define ASSERT_SAME_FIELD(__field,__t1,__t2) { \
  565. ASSERT(FIELD_OFFSET(__t1,__field)==FIELD_OFFSET(__t2,__field)); \
  566. }
  567. #define ASSERT_SAME_DIRINFO_FIELDS(__t1,__t2) {\
  568. ASSERT_SAME_FIELD(LastWriteTime,__t1,__t2); \
  569. ASSERT_SAME_FIELD(EndOfFile,__t1,__t2); \
  570. ASSERT_SAME_FIELD(AllocationSize,__t1,__t2); \
  571. ASSERT_SAME_FIELD(FileAttributes,__t1,__t2); \
  572. }
  573. #if DBG
  574. VOID MRxSmbCoreFileSeach_AssertFields(void){
  575. //just move this out of the main execution path so that we don't have to look at it while
  576. //we Uing the code
  577. ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_FULL_DIR_INFORMATION);
  578. ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_BOTH_DIR_INFORMATION);
  579. }
  580. #else
  581. #define MRxSmbCoreFileSeach_AssertFields()
  582. #endif
  583. NTSTATUS
  584. MRxSmbCoreFileSearch(
  585. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  586. )
  587. /*++
  588. Routine Description:
  589. This routine does a GetFileAttributes and remembers the reponse.
  590. Arguments:
  591. OrdinaryExchange - an exchange to be used for conducting this open.
  592. Return Value:
  593. RXSTATUS - The return status for the operation
  594. Notes:
  595. --*/
  596. {
  597. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  598. RxCaptureFcb; RxCaptureFobx;
  599. PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
  600. PBYTE pBuffer = OrdinaryExchange->Info.Buffer;
  601. PULONG pLengthRemaining = OrdinaryExchange->Info.pBufferLength;
  602. ULONG InformationClass = OrdinaryExchange->Info.InfoClass;
  603. PFILE_DIRECTORY_INFORMATION pPreviousBuffer = NULL;
  604. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  605. ULONG SuccessCount = 0;
  606. PAGED_CODE();
  607. RxDbgTrace(+1, Dbg, ("MRxSmbCoreFileSearch entering.......OE=%08lx\n",OrdinaryExchange));
  608. MRxSmbCoreFileSeach_AssertFields();
  609. OrdinaryExchange->Info.CoreSearch.CountRemaining =
  610. RxContext->QueryDirectory.ReturnSingleEntry?1:0x7ffffff;
  611. if ( (smbFobx->Enumeration.CoreResumeKey ==NULL )
  612. && ((smbFobx->Enumeration.CoreResumeKey = RxAllocatePoolWithTag(PagedPool,sizeof(SMB_RESUME_KEY),'rbms'))==NULL) ){
  613. RxDbgTrace(0, Dbg, ("...couldn't allocate resume key\n"));
  614. Status = (STATUS_INSUFFICIENT_RESOURCES);
  615. goto FINALLY;
  616. }
  617. RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.CoreResumeKey));
  618. Status = MRxSmbLoadCoreFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
  619. for (;;) {
  620. BOOLEAN BufferOverflow = FALSE;
  621. PSMB_DIRECTORY_INFORMATION NextDirInfo;
  622. UNICODE_STRING FileNameU;
  623. OEM_STRING FileNameA;
  624. WCHAR FileNameU_buffer[14];
  625. ULONG NameLength;
  626. PBYTE NextFileName;
  627. BOOLEAN Match,BufferOverFlow;
  628. if (!NT_SUCCESS(Status)) {
  629. if (Status == (STATUS_NO_MORE_FILES)) {
  630. if (SuccessCount > 0) {
  631. Status = (STATUS_SUCCESS);
  632. }
  633. } else if (Status == (STATUS_MORE_PROCESSING_REQUIRED)) {
  634. if (SuccessCount > 0) {
  635. Status = (STATUS_SUCCESS);
  636. } else {
  637. Status = (STATUS_BUFFER_OVERFLOW);
  638. }
  639. }
  640. goto FINALLY;
  641. }
  642. ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemaining>0 );
  643. ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf>0 );
  644. RxDbgTrace(0, Dbg, ("MRxSmbCoreFileSearch looptopcheck counts=%08lx,%08lx\n",
  645. OrdinaryExchange->Info.CoreSearch.CountRemaining,
  646. OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf
  647. ));
  648. //next issue: does the next dirinfo match the criteria?!?
  649. NextDirInfo = OrdinaryExchange->Info.CoreSearch.NextDirInfo;
  650. NextFileName = &NextDirInfo->FileName[0];
  651. // According to colinw, some core servers do not remember to insert the null at the end of the name...
  652. // but the namelength macro handles this correctly. some servers (Xenix, apparently) pad the
  653. // names with spaces. again, the macro handles it....
  654. //
  655. NAME_LENGTH(NameLength, NextFileName,sizeof(NextDirInfo->FileName));
  656. FileNameA.Length = (USHORT)NameLength;
  657. FileNameA.MaximumLength = (USHORT)NameLength;
  658. FileNameA.Buffer = NextFileName;
  659. FileNameU.Length = sizeof(FileNameU_buffer);
  660. FileNameU.MaximumLength = sizeof(FileNameU_buffer);
  661. FileNameU.Buffer = &FileNameU_buffer[0];
  662. Status = RtlOemStringToUnicodeString(&FileNameU, &FileNameA, TRUE);
  663. RxDbgTrace(0, Dbg, ("MRxSmbCoreFileSearch considering.......filename=%wZ, template=%wZ\n",
  664. &FileNameU,&capFobx->UnicodeQueryTemplate));
  665. ASSERT(Status==(STATUS_SUCCESS));
  666. // we deal with a conversion failure by skipping this guy
  667. Match = (Status==(STATUS_SUCCESS));
  668. if (Match && smbFobx->Enumeration.WildCardsFound ) {
  669. //DbgBreakPoint();
  670. Match = FsRtlIsNameInExpression( &capFobx->UnicodeQueryTemplate,
  671. &FileNameU, TRUE, NULL );
  672. }
  673. //next issue: will the next dirinfo fit in the user's buffer?!?
  674. if (Match) {
  675. ULONG SpaceNeeded;
  676. PBYTE pRememberBuffer = pBuffer;
  677. //QuadAlign!! pBuffer = (PBYTE)LongAlign(pBuffer); //assume that this will fit
  678. if (SuccessCount != 0) {
  679. pBuffer = (PBYTE)QuadAlignPtr(pBuffer); //assume that this will fit
  680. }
  681. SpaceNeeded = smbFobx->Enumeration.FileNameOffset+FileNameU.Length;
  682. if (pBuffer+SpaceNeeded > pRememberBuffer+*pLengthRemaining) {
  683. BufferOverflow = TRUE;
  684. pBuffer = pRememberBuffer; //rollback
  685. } else {
  686. PSMBCEDB_SERVER_ENTRY pServerEntry;
  687. PFILE_DIRECTORY_INFORMATION pThisBuffer = (PFILE_DIRECTORY_INFORMATION)pBuffer;
  688. SMB_TIME Time;
  689. SMB_DATE Date;
  690. PSMBCE_SERVER Server;
  691. Server = SmbCeGetExchangeServer(Exchange);
  692. BufferOverflow = FALSE;
  693. if (pPreviousBuffer != NULL) {
  694. pPreviousBuffer->NextEntryOffset =
  695. (ULONG)(((PBYTE)pThisBuffer)-((PBYTE)pPreviousBuffer));
  696. }
  697. pPreviousBuffer = pThisBuffer;
  698. RtlZeroMemory(pBuffer,smbFobx->Enumeration.FileNameOffset);
  699. RtlCopyMemory(pBuffer+smbFobx->Enumeration.FileNameOffset, FileNameU.Buffer,FileNameU.Length);
  700. *((PULONG)(pBuffer+smbFobx->Enumeration.FileNameLengthOffset)) = FileNameU.Length;
  701. //hallucinate the record based on specific return type
  702. switch (InformationClass) {
  703. case SMB_FIND_FILE_NAMES_INFO:
  704. break;
  705. case SMB_FIND_FILE_DIRECTORY_INFO:
  706. case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
  707. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  708. //just fill what we have...we do not go to a lot of trouble on allocinfo as rdr1 did.
  709. // actually, rdr1 didn't do that here...only on getfielinfo.......
  710. SmbMoveTime (&Time, &NextDirInfo->LastWriteTime);
  711. SmbMoveDate (&Date, &NextDirInfo->LastWriteDate);
  712. pThisBuffer->LastWriteTime = MRxSmbConvertSmbTimeToTime(Server, Time, Date);
  713. pThisBuffer->EndOfFile.LowPart = SmbGetUlong(&NextDirInfo->FileSize);
  714. pThisBuffer->FileAttributes = MRxSmbMapSmbAttributes (NextDirInfo->FileAttributes);
  715. break;
  716. default:
  717. RxDbgTrace( 0, Dbg, ("MRxSmbCoreFileSearch: Invalid FS information class\n"));
  718. ASSERT(!"this can't happen");
  719. Status = STATUS_INVALID_PARAMETER;
  720. goto FINALLY;
  721. }
  722. pBuffer += SpaceNeeded;
  723. *pLengthRemaining -= (ULONG)(pBuffer-pRememberBuffer);
  724. OrdinaryExchange->Info.CoreSearch.CountRemaining--;
  725. SuccessCount++;
  726. }
  727. }
  728. //
  729. // if no match or no overflow, move up in the buffer. this means not only juggling the
  730. // pointers but also saving the resume key
  731. if (!Match || !BufferOverflow) {
  732. MRxSmbDumpResumeKey("BufferKey:",&NextDirInfo->ResumeKey);
  733. *(smbFobx->Enumeration.CoreResumeKey) = NextDirInfo->ResumeKey;
  734. MRxSmbDumpResumeKey("SaveKey: ",smbFobx->Enumeration.CoreResumeKey);
  735. OrdinaryExchange->Info.CoreSearch.NextDirInfo = NextDirInfo + 1;
  736. OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf--;
  737. }
  738. if (OrdinaryExchange->Info.CoreSearch.CountRemaining==0) {
  739. Status = (STATUS_SUCCESS);
  740. goto FINALLY;
  741. }
  742. if (BufferOverflow) {
  743. Status = (SuccessCount==0)?(STATUS_BUFFER_OVERFLOW):(STATUS_SUCCESS);
  744. goto FINALLY;
  745. }
  746. if (OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf==0) {
  747. Status = MRxSmbLoadCoreFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
  748. }
  749. }
  750. FINALLY:
  751. RxDbgTrace(-1, Dbg, ("MRxSmbCoreFileSearch exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  752. return(Status);
  753. }
  754. NTSTATUS
  755. MrxSmbOemVolumeInfoToUnicode(
  756. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  757. ULONG *VolumeLabelLengthReturned
  758. )
  759. /*++
  760. Routine Description:
  761. This routine does a GetFileAttributes and remembers the reponse.
  762. Arguments:
  763. Return Value:
  764. RXSTATUS - The return status for the operation
  765. also VolumeLabelLengthReturned is the number of bytes of the label that were stored, if any.
  766. Notes:
  767. --*/
  768. {
  769. NTSTATUS Status = STATUS_SUCCESS;
  770. UNICODE_STRING VolumeLabelU;
  771. OEM_STRING VolumeLabelA;
  772. SMB_DIRECTORY_INFORMATION Buffer;
  773. ULONG NameLength;
  774. ULONG BytesToCopy;
  775. PBYTE VolumeLabel = &OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0];
  776. PAGED_CODE();
  777. NAME_LENGTH(NameLength, VolumeLabel,
  778. sizeof(OrdinaryExchange->Info.QFSVolInfo.CoreLabel));
  779. VolumeLabelA.Length = (USHORT)NameLength;
  780. VolumeLabelA.MaximumLength = (USHORT)NameLength;
  781. VolumeLabelA.Buffer = VolumeLabel;
  782. //some core servers put a '.' in the labelname.....if it's there then remove it
  783. if ((NameLength>8)&& (VolumeLabel[8]=='.') ) {
  784. ULONG i;
  785. for (i=8;i<NameLength;i++) {
  786. VolumeLabel[i] = VolumeLabel[i+1];
  787. }
  788. }
  789. Status = RtlOemStringToUnicodeString(&VolumeLabelU, &VolumeLabelA, TRUE);
  790. if (NT_SUCCESS(Status)) {
  791. PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
  792. PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
  793. BytesToCopy = min((ULONG)VolumeLabelU.Length, (*pBufferLength-sizeof(FILE_FS_VOLUME_INFORMATION)));
  794. RtlCopyMemory(&pBuffer->VolumeLabel[0],
  795. VolumeLabelU.Buffer,
  796. BytesToCopy);
  797. *VolumeLabelLengthReturned = BytesToCopy;
  798. pBuffer->VolumeLabelLength = VolumeLabelU.Length;
  799. IF_DEBUG {
  800. UNICODE_STRING FinalLabel;
  801. FinalLabel.Buffer = &pBuffer->VolumeLabel[0];
  802. FinalLabel.Length = (USHORT)BytesToCopy;
  803. RxDbgTrace(0, Dbg, ("MrxSmbOemVolumeInfoToUnicode vollabel=%wZ\n",&FinalLabel));
  804. }
  805. RtlFreeUnicodeString(&VolumeLabelU);
  806. }
  807. return(Status);
  808. }
  809. MrxSmbCoreQueryFsVolumeInfo(
  810. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  811. )
  812. /*++
  813. Routine Description:
  814. This routine does a GetFileAttributes and remembers the reponse.
  815. Arguments:
  816. OrdinaryExchange - an exchange to be used for conducting this open.
  817. Return Value:
  818. RXSTATUS - The return status for the operation
  819. Notes:
  820. --*/
  821. {
  822. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  823. PSMBSTUFFER_BUFFER_STATE StufferState;
  824. PAGED_CODE();
  825. RxDbgTrace(+1, Dbg, ("MrxSmbCoreQueryFsVolumeInfo entering.......OE=%08lx\n",OrdinaryExchange));
  826. StufferState = &OrdinaryExchange->AssociatedStufferState;
  827. ASSERT( StufferState );
  828. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_SEARCH,
  829. SMB_REQUEST_SIZE(SEARCH),
  830. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  831. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  832. );
  833. MRxSmbDumpStufferState (1100,"SMB w/ searchvolumelabel before stuffing",StufferState);
  834. MRxSmbStuffSMB (StufferState,
  835. "0wwB4yw!",
  836. // 0 UCHAR WordCount; // Count of parameter words = 2
  837. 1, // w _USHORT( MaxCount ); // Number of dir. entries to return
  838. // w _USHORT( SearchAttributes );
  839. SMB_FILE_ATTRIBUTE_VOLUME,
  840. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
  841. // UCHAR Buffer[1]; // Buffer containing:
  842. &MRxSmbAll8dot3Files,// 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
  843. // //UCHAR FileName[]; // File name, may be null
  844. 0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
  845. 0 // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
  846. // //UCHAR SearchStatus[]; // Resume key
  847. );
  848. MRxSmbDumpStufferState (700,"SMB w/ searchvolumelabel after stuffing",StufferState);
  849. //ASSERT(!"Now it's stuffed");
  850. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  851. SMBPSE_OETYPE_COREQUERYLABEL
  852. );
  853. //Status = RxStatus(NOT_IMPLEMENTED);
  854. FINALLY:
  855. RxDbgTrace(-1, Dbg, ("MrxSmbCoreQueryFsVolumeInfo exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  856. return(Status);
  857. }
  858. NTSTATUS
  859. MrxSmbQueryFsVolumeInfo(
  860. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  861. )
  862. /*++
  863. Routine Description:
  864. This routine does a downlevel getvolumeinfo/FS_VOLUME_INFORMATION.
  865. Arguments:
  866. OrdinaryExchange - duh!
  867. Return Value:
  868. RXSTATUS - The return status for the operation
  869. Notes:
  870. --*/
  871. {
  872. NTSTATUS Status;
  873. RxCaptureFcb;
  874. RxCaptureFobx;
  875. PSMBCE_SERVER pServer;
  876. BOOLEAN UseTransactVersion;
  877. REQ_QUERY_FS_INFORMATION VolInfo;
  878. PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
  879. PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
  880. ULONG VolumeLabelLengthReturned = 0;
  881. PAGED_CODE();
  882. ASSERT(pBuffer!=NULL);
  883. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  884. UseTransactVersion = BooleanFlagOn(pServer->DialectFlags,DF_LANMAN20);
  885. RxDbgTrace(+1, Dbg, ("MrxSmbQueryFsVolumeInfo entering.......OE=%08lx\n",OrdinaryExchange));
  886. pBuffer->SupportsObjects = FALSE;
  887. pBuffer->VolumeCreationTime.LowPart = 0;
  888. pBuffer->VolumeCreationTime.HighPart = 0;
  889. pBuffer->VolumeSerialNumber = 0;
  890. pBuffer->VolumeLabelLength = 0;
  891. OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] = 0; //no label
  892. if (!UseTransactVersion) {
  893. Status = MrxSmbCoreQueryFsVolumeInfo(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  894. } else {
  895. VolInfo.InformationLevel = SMB_INFO_VOLUME;
  896. Status = MRxSmbSimpleSyncTransact2(
  897. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  898. SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO,
  899. TRANS2_QUERY_FS_INFORMATION,
  900. &VolInfo,sizeof(VolInfo),
  901. NULL,0
  902. );
  903. }
  904. ASSERT ( *pBufferLength>=sizeof(FILE_FS_VOLUME_INFORMATION));
  905. RxDbgTrace(0, Dbg, ("MrxSmbQueryFsVolumeInfo OEstatus=%08lx\n",Status));
  906. //DbgBreakPoint();
  907. if ( (Status==STATUS_SUCCESS) &&
  908. (OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] != 0) ) {
  909. Status = MrxSmbOemVolumeInfoToUnicode(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,&VolumeLabelLengthReturned);
  910. } else if ( (Status == STATUS_NO_SUCH_FILE)
  911. || (Status == STATUS_NO_MORE_FILES) ) {
  912. //
  913. // these statuses indicate that there's no volume label
  914. // the remote volume. Return success with no data.
  915. //
  916. Status = (STATUS_SUCCESS);
  917. }
  918. if (NT_SUCCESS(Status)) {
  919. *pBufferLength -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,VolumeLabel);
  920. *pBufferLength -= VolumeLabelLengthReturned;
  921. }
  922. RxDbgTrace(-1, Dbg, ("MrxSmbQueryFsVolumeInfo exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  923. return(Status);
  924. }
  925. NTSTATUS
  926. MrxSmbCoreQueryDiskAttributes(
  927. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  928. )
  929. /*++
  930. Routine Description:
  931. This routine does a GetDiskAttributes and remembers the reponse in a buffer pointed to
  932. by the exchange. this is called from the downlevel queryvolumeinfo AND ALSO from
  933. extend-for-cached-write.
  934. Arguments:
  935. OrdinaryExchange - duh!
  936. Return Value:
  937. RXSTATUS - The return status for the operation
  938. Notes:
  939. --*/
  940. {
  941. NTSTATUS Status;
  942. RxCaptureFcb; RxCaptureFobx;
  943. PSMBSTUFFER_BUFFER_STATE StufferState;
  944. PAGED_CODE();
  945. ASSERT(OrdinaryExchange->Info.Buffer!=NULL);
  946. RxDbgTrace(+1, Dbg, ("MrxSmbCoreQueryDiskAttributes entering.......OE=%08lx\n",OrdinaryExchange));
  947. StufferState = &OrdinaryExchange->AssociatedStufferState;
  948. ASSERT( StufferState );
  949. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_QUERY_INFORMATION_DISK,
  950. SMB_REQUEST_SIZE(QUERY_INFORMATION_DISK),
  951. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  952. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  953. );
  954. RxDbgTrace(0, Dbg,("querydiskattribs command initial status = %lu\n",Status));
  955. MRxSmbDumpStufferState (1100,"SMB w/ querydiskattribs before stuffing",StufferState);
  956. MRxSmbStuffSMB (StufferState,
  957. "0B!",
  958. // 0 UCHAR WordCount; // Count of parameter words = 0
  959. SMB_WCT_CHECK(0) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  960. // UCHAR Buffer[1]; // empty
  961. );
  962. MRxSmbDumpStufferState (700,"SMB w/ querydiskattribs after stuffing",StufferState);
  963. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  964. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES
  965. );
  966. FINALLY:
  967. RxDbgTrace(-1, Dbg, ("MrxSmbCoreQueryDiskAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  968. return(Status);
  969. }
  970. NTSTATUS
  971. MrxSmbQueryDiskAttributes(
  972. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  973. )
  974. /*++
  975. Routine Description:
  976. This routine does a GetDiskAttributes and remembers the reponse in a buffer pointed to
  977. by the exchange. this is called from the downlevel queryvolumeinfo AND ALSO from
  978. extend-for-cached-write.
  979. Arguments:
  980. OrdinaryExchange - duh!
  981. Return Value:
  982. RXSTATUS - The return status for the operation
  983. Notes:
  984. --*/
  985. {
  986. NTSTATUS Status;
  987. RxCaptureFcb;
  988. RxCaptureFobx;
  989. PSMBCE_SERVER pServer;
  990. BOOLEAN UseTransactVersion;
  991. REQ_QUERY_FS_INFORMATION VolInfo;
  992. PAGED_CODE();
  993. ASSERT(OrdinaryExchange->Info.Buffer!=NULL);
  994. pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  995. UseTransactVersion = BooleanFlagOn(pServer->DialectFlags,DF_LANMAN20) &&
  996. !MRxSmbForceCoreGetAttributes;
  997. if (!UseTransactVersion) {
  998. return MrxSmbCoreQueryDiskAttributes(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  999. }
  1000. RxDbgTrace(+1, Dbg, ("MrxSmbQueryDiskAttributes entering.......OE=%08lx\n",OrdinaryExchange));
  1001. VolInfo.InformationLevel = SMB_INFO_ALLOCATION;
  1002. Status = MRxSmbSimpleSyncTransact2(
  1003. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1004. SMBPSE_OETYPE_T2_FOR_LANMAN_DISKATTRIBUTES_INFO,
  1005. TRANS2_QUERY_FS_INFORMATION,
  1006. &VolInfo,sizeof(VolInfo),
  1007. NULL,0
  1008. );
  1009. RxDbgTrace(-1, Dbg, ("MrxSmbQueryDiskAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  1010. return(Status);
  1011. }
  1012. NTSTATUS
  1013. MRxSmbGetNtAllocationInfo (
  1014. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  1015. );
  1016. NTSTATUS
  1017. SmbPseExchangeStart_CoreInfo(
  1018. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  1019. )
  1020. /*++
  1021. Routine Description:
  1022. This is the start routine for VOLINFO.
  1023. Arguments:
  1024. pExchange - the exchange instance
  1025. Return Value:
  1026. RXSTATUS - The return status for the operation
  1027. --*/
  1028. {
  1029. NTSTATUS Status = (STATUS_NOT_IMPLEMENTED);
  1030. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1031. ULONG InformationClass = OrdinaryExchange->Info.InfoClass;
  1032. PBYTE pBuffer = (PBYTE)OrdinaryExchange->Info.Buffer;
  1033. PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
  1034. RxCaptureFcb; RxCaptureFobx;
  1035. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  1036. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1037. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1038. PAGED_CODE();
  1039. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_CoreInfo\n", 0 ));
  1040. ASSERT_ORDINARY_EXCHANGE(OrdinaryExchange);
  1041. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  1042. //ASSERT (StufferState->CurrentCommand == SMB_COM_NO_ANDX_COMMAND);
  1043. switch (OrdinaryExchange->EntryPoint) {
  1044. case SMBPSE_OE_FROM_QUERYVOLUMEINFO:
  1045. switch (InformationClass) {
  1046. case FileFsVolumeInformation:
  1047. Status = MrxSmbQueryFsVolumeInfo(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1048. goto FINALLY;
  1049. case FileFsSizeInformation:
  1050. Status = MrxSmbQueryDiskAttributes(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1051. goto FINALLY;
  1052. default:
  1053. ASSERT(!"this should have been turned away");
  1054. goto FINALLY;
  1055. }
  1056. ASSERT(!"shouldn't get here1");
  1057. goto FINALLY;
  1058. case SMBPSE_OE_FROM_QUERYFILEINFO:
  1059. Status = MRxSmbGetFileAttributes(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1060. if (!NT_SUCCESS(Status)) goto FINALLY;
  1061. switch (InformationClass) {
  1062. case SMB_QUERY_FILE_BASIC_INFO:
  1063. *((PFILE_BASIC_INFORMATION)pBuffer) = OrdinaryExchange->Create.FileInfo.Basic;
  1064. *pBufferLength -= sizeof(FILE_BASIC_INFORMATION);
  1065. goto FINALLY;
  1066. case SMB_QUERY_FILE_STANDARD_INFO:
  1067. *((PFILE_STANDARD_INFORMATION)pBuffer) = OrdinaryExchange->Create.FileInfo.Standard;
  1068. *pBufferLength -= sizeof(FILE_STANDARD_INFORMATION);
  1069. goto FINALLY;
  1070. default:
  1071. ASSERT(!"this should have been turned away");
  1072. goto FINALLY;
  1073. }
  1074. ASSERT(!"shouldn't get here2");
  1075. goto FINALLY;
  1076. case SMBPSE_OE_FROM_SETFILEINFO:
  1077. switch (InformationClass) {
  1078. case FileBasicInformation:
  1079. {
  1080. ULONG SmbAttributes = MRxSmbMapFileAttributes(((PFILE_BASIC_INFORMATION)pBuffer)->FileAttributes);
  1081. PFILE_BASIC_INFORMATION BasicInfo = (PFILE_BASIC_INFORMATION)pBuffer;
  1082. if (SmbAttributes != 0 ||
  1083. (BasicInfo->CreationTime.QuadPart == 0 &&
  1084. BasicInfo->LastWriteTime.QuadPart == 0 &&
  1085. BasicInfo->LastAccessTime.QuadPart == 0)) {
  1086. Status = MRxSmbSetFileAttributes(
  1087. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1088. SmbAttributes);
  1089. }
  1090. if (BasicInfo->LastWriteTime.QuadPart == 0 &&
  1091. FlagOn(pServerEntry->Server.DialectFlags,DF_W95)) {
  1092. // Win9x server only takes last write time.
  1093. Status = STATUS_SUCCESS;
  1094. goto FINALLY;
  1095. }
  1096. if (BasicInfo->CreationTime.QuadPart != 0 ||
  1097. BasicInfo->LastWriteTime.QuadPart != 0 ||
  1098. BasicInfo->LastAccessTime.QuadPart != 0) {
  1099. Status = MRxSmbDeferredCreate(RxContext);
  1100. if (Status == STATUS_SUCCESS) {
  1101. Status = MRxSmbSetFileAttributes(
  1102. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1103. SmbAttributes);
  1104. }
  1105. }
  1106. }
  1107. goto FINALLY;
  1108. case FileEndOfFileInformation:
  1109. if (((PFILE_END_OF_FILE_INFORMATION)pBuffer)->EndOfFile.HighPart) {
  1110. Status = (STATUS_INVALID_PARAMETER);
  1111. } else {
  1112. Status = MRxSmbCoreTruncate(
  1113. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1114. smbSrvOpen->Fid,
  1115. ((PFILE_END_OF_FILE_INFORMATION)pBuffer)->EndOfFile.LowPart);
  1116. }
  1117. goto FINALLY;
  1118. case FileDispositionInformation:
  1119. OrdinaryExchange->pPathArgument1 = GET_ALREADY_PREFIXED_NAME(SrvOpen,capFcb);
  1120. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  1121. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1122. ((BOOLEAN)( NodeType(capFcb)==RDBSS_NTC_STORAGE_TYPE_DIRECTORY )));
  1123. goto FINALLY;
  1124. default:
  1125. ASSERT(!"this should have been turned away");
  1126. goto FINALLY;
  1127. }
  1128. ASSERT(!"shouldn't get here3");
  1129. goto FINALLY;
  1130. case SMBPSE_OE_FROM_QUERYDIRECTORY:
  1131. Status = MRxSmbCoreFileSearch(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1132. goto FINALLY;
  1133. case SMBPSE_OE_FROM_EXTENDFILEFORCACHEING:
  1134. {
  1135. PSMBCE_NET_ROOT psmbNetRoot = SmbCeGetExchangeNetRoot(OrdinaryExchange);
  1136. PMRX_V_NET_ROOT pVNetRoot = SmbCeGetExchangeVNetRoot(OrdinaryExchange);
  1137. PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
  1138. PSMBCE_SERVER psmbServer = SmbCeGetExchangeServer(OrdinaryExchange);
  1139. ULONG ClusterSize;
  1140. PLARGE_INTEGER pFileSize = (PLARGE_INTEGER)(OrdinaryExchange->Info.Buffer);
  1141. PLARGE_INTEGER pAllocationSize = (PLARGE_INTEGER)(OrdinaryExchange->Info.pBufferLength);
  1142. //we will need the cluster size
  1143. if (OrdinaryExchange->ServerVersion==pNetRoot->ParameterValidationStamp) {
  1144. ClusterSize=pNetRoot->DiskParameters.ClusterSize;
  1145. } else {
  1146. RxSynchronizeBlockingOperations( RxContext, (PFCB)RxContext->pFcb, &psmbNetRoot->ClusterSizeSerializationQueue );
  1147. if (OrdinaryExchange->ServerVersion!=pNetRoot->ParameterValidationStamp) {
  1148. //
  1149. //here we have to go find out the clustersize
  1150. NTSTATUS LocalStatus;
  1151. FILE_FS_SIZE_INFORMATION UsersBuffer;
  1152. ULONG BufferLength = sizeof(FILE_FS_SIZE_INFORMATION);
  1153. //fill in the exchange params so that we can get the params we need
  1154. OrdinaryExchange->Info.Buffer = &UsersBuffer;
  1155. OrdinaryExchange->Info.pBufferLength = &BufferLength;
  1156. LocalStatus = MrxSmbQueryDiskAttributes(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1157. if (LocalStatus == STATUS_SUCCESS) {
  1158. ClusterSize = UsersBuffer.BytesPerSector * UsersBuffer.SectorsPerAllocationUnit;
  1159. pNetRoot->ParameterValidationStamp =OrdinaryExchange->ServerVersion;
  1160. } else {
  1161. ClusterSize = 0;
  1162. }
  1163. if (ClusterSize==0) {
  1164. ClusterSize = 1;
  1165. }
  1166. pNetRoot->DiskParameters.ClusterSize = ClusterSize;
  1167. RxDbgTrace(0, Dbg, ("clustersize set to %08lx\n", ClusterSize ));
  1168. RxLog(("clustersize rx/n/cs %lx %lx %lx\n",
  1169. OrdinaryExchange->RxContext,pNetRoot,ClusterSize ));
  1170. } else {
  1171. // someone else went and got the value while i was asleep...just use it
  1172. ClusterSize=pNetRoot->DiskParameters.ClusterSize;
  1173. }
  1174. RxResumeBlockedOperations_Serially(RxContext,&psmbNetRoot->ClusterSizeSerializationQueue);
  1175. }
  1176. ASSERT (ClusterSize != 0);
  1177. if (FlagOn(psmbServer->DialectFlags,DF_NT_SMBS)) {
  1178. //i'm using this to identify a server that supports 64bit offsets
  1179. //for these guys, we write a zero at the eof....since the filesystems
  1180. //extend on writes this will be much better than a set-end-of-file
  1181. LARGE_INTEGER ByteOffset,AllocationSize,ClusterSizeAsLI;
  1182. ULONG Buffer = 0;
  1183. UCHAR WriteCommand;
  1184. PSMBCE_SERVER pServer = SmbCeGetExchangeServer(OrdinaryExchange);
  1185. if (FlagOn(pServer->DialectFlags,DF_LARGE_FILES)) {
  1186. WriteCommand = SMB_COM_WRITE_ANDX;
  1187. } else {
  1188. WriteCommand = SMB_COM_WRITE;
  1189. }
  1190. ByteOffset.QuadPart = pFileSize->QuadPart - 1;
  1191. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,0));
  1192. COVERED_CALL(MRxSmbBuildWriteRequest(
  1193. OrdinaryExchange,
  1194. TRUE, // IsPagingIo
  1195. WriteCommand,
  1196. 1,
  1197. &ByteOffset,
  1198. (PBYTE)&Buffer,
  1199. NULL //BufferAsMdl,
  1200. ));
  1201. COVERED_CALL(SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1202. SMBPSE_OETYPE_EXTEND_WRITE
  1203. ));
  1204. //this is what you do if you can't do better
  1205. ClusterSizeAsLI.QuadPart = ClusterSize;
  1206. AllocationSize.QuadPart =
  1207. (pFileSize->QuadPart+ ClusterSizeAsLI.QuadPart) &
  1208. ~(ClusterSizeAsLI.QuadPart - 1);
  1209. *pAllocationSize = AllocationSize; //64bit!
  1210. Status = MRxSmbGetNtAllocationInfo(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  1211. if ( (NT_SUCCESS(Status)) &&
  1212. (OrdinaryExchange->Transact2.AllocationSize.QuadPart > AllocationSize.QuadPart)) {
  1213. *pAllocationSize = OrdinaryExchange->Transact2.AllocationSize; //64bit!
  1214. RxDbgTrace(0, Dbg, ("alocatedsiz222e set to %08lx\n", pAllocationSize->LowPart ));
  1215. }
  1216. }
  1217. if ( (!FlagOn(psmbServer->DialectFlags,DF_NT_SMBS)) || (!NT_SUCCESS(Status)) ) {
  1218. ULONG FileSize,AllocationSize;
  1219. FileSize = pFileSize->LowPart;
  1220. COVERED_CALL(MRxSmbCoreTruncate(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1221. smbSrvOpen->Fid, FileSize
  1222. ));
  1223. //this is what you do if you can't do better
  1224. AllocationSize = (FileSize+ClusterSize)&~(ClusterSize-1);
  1225. pAllocationSize->QuadPart = AllocationSize; //64bit!
  1226. RxDbgTrace(0, Dbg, ("alocatedsize set to %08lx\n", pAllocationSize->LowPart ));
  1227. //if we care a lot about downlevel performance, we could do the same as ntgetallocation
  1228. //except that we would use a 32bit smb.........like query_information2
  1229. }
  1230. }
  1231. goto FINALLY;
  1232. }
  1233. FINALLY:
  1234. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_CoreInfo exit w %08lx\n", Status ));
  1235. return Status;
  1236. }
  1237. NTSTATUS
  1238. MRxSmbFinishSearch (
  1239. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1240. PRESP_SEARCH Response
  1241. )
  1242. /*++
  1243. Routine Description:
  1244. This routine actually gets the stuff out of the VolInfo response and finishes the close.
  1245. Arguments:
  1246. OrdinaryExchange - the exchange instance
  1247. Response - the response
  1248. Return Value:
  1249. RXSTATUS - The return status for the operation
  1250. --*/
  1251. {
  1252. NTSTATUS Status = (STATUS_SUCCESS);
  1253. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1254. RxCaptureFobx;
  1255. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  1256. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1257. PAGED_CODE();
  1258. RxDbgTrace(+1, Dbg, ("MRxSmbFinishSearch\n" ));
  1259. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishSearch:");
  1260. if (Response->WordCount != 1) {
  1261. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1262. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1263. goto FINALLY;
  1264. }
  1265. if (OrdinaryExchange->OEType == SMBPSE_OETYPE_COREQUERYLABEL) {
  1266. //here, all we do is to copy the label to wherever is pointed to by
  1267. if (SmbGetUshort(&Response->Count)>0) {
  1268. PBYTE smbDirInfotmp = &Response->Buffer[0]
  1269. +sizeof(UCHAR) //bufferformat
  1270. +sizeof(USHORT); //datalength
  1271. PSMB_DIRECTORY_INFORMATION smbDirInfo = (PSMB_DIRECTORY_INFORMATION)smbDirInfotmp;
  1272. RxDbgTrace(+1, Dbg, ("MRxSmbFinishSearch corelabl=%s,size=%d\n",
  1273. smbDirInfo->FileName, sizeof(smbDirInfo->FileName) ));
  1274. if (sizeof(smbDirInfo->FileName) != 13) { //straightfrom the spec
  1275. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1276. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1277. goto FINALLY;
  1278. }
  1279. RtlCopyMemory(OrdinaryExchange->Info.QFSVolInfo.CoreLabel,
  1280. smbDirInfo->FileName, sizeof(smbDirInfo->FileName)
  1281. );
  1282. } else {
  1283. OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] = 0; //no label
  1284. }
  1285. } else if (OrdinaryExchange->OEType == SMBPSE_OETYPE_CORESEARCHFORCHECKEMPTY) {
  1286. //here, we 're doing a search SMB to see if the directory is empty. we have to read thru the
  1287. // entries returned (if successful). if we encounter ones that are neither '.' or '..', set
  1288. // resumekey to null since that will tell the guy above that the directory is nonempty
  1289. ULONG Count = SmbGetUshort(&Response->Count);
  1290. PSMB_DIRECTORY_INFORMATION NextDirInfo =
  1291. (PSMB_DIRECTORY_INFORMATION)(&Response->Buffer[0]+sizeof(UCHAR)+sizeof(USHORT));
  1292. for (;Count>0;Count--,NextDirInfo++) {
  1293. RxDbgTrace(0, Dbg, ("--->emptydirchk: file=%s\n",&NextDirInfo->FileName[0]));
  1294. /*
  1295. // Since the DOS Server returns the file name ". " instead of ".", and so does the
  1296. // ".. ", the following if {...} statements are always past through with no action.
  1297. // But those statements make the RMDIR not working on OS2 Server since it returns the "."
  1298. // and ".." without following blanks. After the if {...} statements were removed, the RMDIR
  1299. // workes on OS2 Server and no impact has been found to access the DOS Server.
  1300. if (NextDirInfo->FileName[0]=='.') {
  1301. CHAR c1;
  1302. if ((c1=NextDirInfo->FileName[1])==0) {
  1303. continue; //skip past "."
  1304. } else if ((c1=='.')&&(NextDirInfo->FileName[2]==0)) {
  1305. continue; //skip past ".."
  1306. } else {
  1307. NOTHING;
  1308. }
  1309. }
  1310. */
  1311. // here we have found a bad one...make sure there's no resume key and change the status
  1312. Status = (STATUS_NO_MORE_FILES);
  1313. OrdinaryExchange->Info.CoreSearch.EmptyCheckResumeKey = NULL;
  1314. }
  1315. //if we get here with success, set up the resume key and buffer
  1316. if (Status == (STATUS_SUCCESS)) {
  1317. NextDirInfo--;
  1318. OrdinaryExchange->Info.CoreSearch.EmptyCheckResumeKeyBuffer =
  1319. NextDirInfo->ResumeKey;
  1320. OrdinaryExchange->Info.CoreSearch.EmptyCheckResumeKey =
  1321. &OrdinaryExchange->Info.CoreSearch.EmptyCheckResumeKeyBuffer;
  1322. }
  1323. } else {
  1324. //all that we do here is to setup the nextdirptr and the count in the OE
  1325. ASSERT(OrdinaryExchange->OEType == SMBPSE_OETYPE_CORESEARCH);
  1326. OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf = SmbGetUshort(&Response->Count);
  1327. OrdinaryExchange->Info.CoreSearch.NextDirInfo =
  1328. (PSMB_DIRECTORY_INFORMATION)(&Response->Buffer[0]+sizeof(UCHAR)+sizeof(USHORT));
  1329. IF_DEBUG {
  1330. ULONG tcount = OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf;
  1331. PSMB_DIRECTORY_INFORMATION ndi = OrdinaryExchange->Info.CoreSearch.NextDirInfo;
  1332. RxDbgTrace(0, Dbg, ("--->coresearch: count/ndi=%08lx/%08lx\n",tcount,ndi));
  1333. if (tcount) {
  1334. //DbgBreakPoint();
  1335. RxDbgTrace(0, Dbg, ("--->coresearch: firstfile=%s\n",&ndi->FileName[0]));
  1336. }
  1337. }
  1338. }
  1339. FINALLY:
  1340. RxDbgTrace(-1, Dbg, ("MRxSmbFinishSearch returning %08lx\n", Status ));
  1341. return Status;
  1342. }
  1343. NTSTATUS
  1344. MRxSmbFinishQueryDiskInfo (
  1345. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1346. PRESP_QUERY_INFORMATION_DISK Response
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. This routine actually gets the stuff out of the VolInfo response and finishes the close.
  1351. Arguments:
  1352. OrdinaryExchange - the exchange instance
  1353. Response - the response
  1354. Return Value:
  1355. RXSTATUS - The return status for the operation
  1356. --*/
  1357. {
  1358. NTSTATUS Status = (STATUS_SUCCESS);
  1359. PFILE_FS_SIZE_INFORMATION UsersBuffer = OrdinaryExchange->Info.Buffer;
  1360. PULONG BufferLength = OrdinaryExchange->Info.pBufferLength;
  1361. PAGED_CODE();
  1362. RxDbgTrace(+1, Dbg, ("MRxSmbFinishQueryDiskInfo\n" ));
  1363. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishQueryDiskInfo:");
  1364. IF_DEBUG{
  1365. PRX_CONTEXT RxContext = OrdinaryExchange->RxContext;
  1366. RxCaptureFobx;
  1367. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  1368. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1369. ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
  1370. }
  1371. if (Response->WordCount != 5 ||
  1372. SmbGetUshort(&Response->ByteCount) != 0) {
  1373. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1374. OrdinaryExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  1375. goto FINALLY;
  1376. }
  1377. UsersBuffer->TotalAllocationUnits.QuadPart = SmbGetUshort(&Response->TotalUnits);
  1378. UsersBuffer->AvailableAllocationUnits.QuadPart = SmbGetUshort(&Response->FreeUnits);
  1379. UsersBuffer->SectorsPerAllocationUnit = SmbGetUshort(&Response->BlocksPerUnit);
  1380. UsersBuffer->BytesPerSector = SmbGetUshort(&Response->BlockSize);
  1381. *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
  1382. FINALLY:
  1383. RxDbgTrace(-1, Dbg, ("MRxSmbFinishQueryDiskInfo returning %08lx\n", Status ));
  1384. return Status;
  1385. }
  1386. NTSTATUS
  1387. MRxSmbExtendForCache (
  1388. IN OUT struct _RX_CONTEXT * RxContext,
  1389. IN PLARGE_INTEGER pNewFileSize,
  1390. OUT PLARGE_INTEGER pNewAllocationSize
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This routine handles network requests to extend the file for cached IO. we just share the
  1395. core_info skeleton.
  1396. Arguments:
  1397. RxContext - the RDBSS context
  1398. Return Value:
  1399. RXSTATUS - The return status for the operation
  1400. --*/
  1401. {
  1402. NTSTATUS Status;
  1403. RxCaptureFcb; RxCaptureFobx;
  1404. PMRX_SRV_OPEN SrvOpen;
  1405. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1406. PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  1407. PSMB_EXCHANGE Exchange;
  1408. PAGED_CODE();
  1409. if (capFcb->Attributes & FILE_ATTRIBUTE_COMPRESSED) {
  1410. //here, we just get out since disk reservations don't do us any good....
  1411. pNewAllocationSize->QuadPart = (pNewFileSize->QuadPart)<<2;
  1412. return(STATUS_SUCCESS);
  1413. }
  1414. RxDbgTrace(+1, Dbg, ("MRxSmbExtendForCache %08lx %08lx %08lx %08lx\n",
  1415. capFcb->Header.FileSize.LowPart,
  1416. capFcb->Header.AllocationSize.LowPart,
  1417. pNewFileSize->LowPart,
  1418. pNewAllocationSize->LowPart
  1419. ));
  1420. ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
  1421. SrvOpen = capFobx->pSrvOpen;
  1422. smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1423. if (FALSE) {
  1424. DbgPrint("Extend top %08lx %08lx %08lx %08lx\n",
  1425. capFcb->Header.FileSize.LowPart,
  1426. capFcb->Header.AllocationSize.LowPart,
  1427. pNewFileSize->LowPart,
  1428. pNewAllocationSize->LowPart);
  1429. }
  1430. //we just pass in our info into MRxSmbCoreInformation thru the existing pointers....
  1431. //we have two pointers.....the first two params are ptrs......
  1432. Status = MRxSmbCoreInformation(RxContext,0,
  1433. (PVOID)pNewFileSize,
  1434. (PULONG)pNewAllocationSize,
  1435. SMBPSE_OE_FROM_EXTENDFILEFORCACHEING
  1436. );
  1437. if (FALSE) {
  1438. DbgPrint("Extend exit Status %lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
  1439. Status,
  1440. capFcb->Header.FileSize.HighPart,
  1441. capFcb->Header.FileSize.LowPart,
  1442. capFcb->Header.AllocationSize.HighPart,
  1443. capFcb->Header.AllocationSize.LowPart,
  1444. pNewFileSize->HighPart,
  1445. pNewFileSize->LowPart,
  1446. pNewAllocationSize->HighPart,
  1447. pNewAllocationSize->LowPart);
  1448. }
  1449. RxLog(("Extend exit %lx %lx %lx %lx %lx\n",
  1450. RxContext,
  1451. capFcb->Header.FileSize.LowPart,
  1452. capFcb->Header.AllocationSize.LowPart,
  1453. pNewFileSize->LowPart,
  1454. pNewAllocationSize->LowPart));
  1455. RxDbgTrace(-1, Dbg, ("MRxSmbExtendForCache exit with status=%08lx %08lx %08lx\n",
  1456. Status, pNewFileSize->LowPart, pNewAllocationSize->LowPart));
  1457. return(Status);
  1458. }
  1459. NTSTATUS
  1460. MRxSmbExtendForNonCache(
  1461. IN OUT struct _RX_CONTEXT * RxContext,
  1462. IN PLARGE_INTEGER pNewFileSize,
  1463. OUT PLARGE_INTEGER pNewAllocationSize
  1464. )
  1465. /*++
  1466. Routine Description:
  1467. This routine handles network requests to extend the file for noncached IO. since the write
  1468. itself will extend the file, we can pretty much just get out quickly.
  1469. Arguments:
  1470. RxContext - the RDBSS context
  1471. Return Value:
  1472. RXSTATUS - The return status for the operation
  1473. --*/
  1474. {
  1475. NTSTATUS Status = STATUS_SUCCESS;
  1476. //RxCaptureFcb; RxCaptureFobx;
  1477. //PMRXSMB_RX_CONTEXT pMRxSmbContext = MRxSmbGetMinirdrContext(RxContext);
  1478. //PSMB_EXCHANGE Exchange;
  1479. PAGED_CODE();
  1480. pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
  1481. return(Status);
  1482. }
  1483. NTSTATUS
  1484. MRxSmbGetNtAllocationInfo (
  1485. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  1486. )
  1487. /*++
  1488. Routine Description:
  1489. gets the nt allocation information by doing a simple transact........
  1490. Arguments:
  1491. OrdinaryExchange - an exchange to be used for conducting this open.
  1492. Return Value:
  1493. RXSTATUS - The return status for the operation
  1494. Notes:
  1495. --*/
  1496. {
  1497. NTSTATUS Status;
  1498. RxCaptureFcb; RxCaptureFobx;
  1499. PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
  1500. PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
  1501. REQ_QUERY_FILE_INFORMATION FileInfo;
  1502. PAGED_CODE();
  1503. FileInfo.Fid = smbSrvOpen->Fid;
  1504. FileInfo.InformationLevel = SMB_QUERY_FILE_STANDARD_INFO;
  1505. Status = MRxSmbSimpleSyncTransact2(
  1506. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1507. SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO,
  1508. TRANS2_QUERY_FILE_INFORMATION,
  1509. &FileInfo,sizeof(FileInfo),
  1510. NULL,0
  1511. );
  1512. return(Status);
  1513. }
  1514. NTSTATUS
  1515. __MRxSmbSimpleSyncTransact2(
  1516. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  1517. IN SMB_PSE_ORDINARY_EXCHANGE_TYPE OEType,
  1518. IN ULONG TransactSetupCode,
  1519. IN PVOID Params,
  1520. IN ULONG ParamsLength,
  1521. IN PVOID Data,
  1522. IN ULONG DataLength,
  1523. IN PSMB_PSE_OE_T2_FIXUP_ROUTINE FixupRoutine
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. This routine does a simple 1-in-1out transact2
  1528. Arguments:
  1529. OrdinaryExchange - an exchange to be used for conducting this open.
  1530. Return Value:
  1531. RXSTATUS - The return status for the operation
  1532. Notes:
  1533. --*/
  1534. {
  1535. NTSTATUS Status;
  1536. RxCaptureFcb; RxCaptureFobx;
  1537. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  1538. PSMBSTUFFER_BUFFER_STATE StufferState;
  1539. PAGED_CODE();
  1540. RxDbgTrace(+1, Dbg, ("MRxSmbSimpleSyncTransact2 entering.......OE=%08lx\n",OrdinaryExchange));
  1541. StufferState = &OrdinaryExchange->AssociatedStufferState;
  1542. ASSERT( StufferState );
  1543. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_TRANSACTION2,
  1544. SMB_REQUEST_SIZE(TRANSACTION),
  1545. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  1546. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  1547. );
  1548. MRxSmbDumpStufferState (1100,"SMB w/ pseT2 before stuffing",StufferState);
  1549. //the return sizes of 100 and 800 are chosen arbitrarily.
  1550. MRxSmbStuffSMB (StufferState,
  1551. "0wwwwdD",
  1552. // 0 UCHAR WordCount; // Count of parameter words; value = (14 + SetupCount)
  1553. ParamsLength, // w _USHORT( TotalParameterCount ); // Total parameter bytes being sent
  1554. DataLength, // w _USHORT( TotalDataCount ); // Total data bytes being sent
  1555. 100, // w _USHORT( MaxParameterCount ); // Max parameter bytes to return
  1556. 800, // w _USHORT( MaxDataCount ); // Max data bytes to return
  1557. 0, // d . UCHAR MaxSetupCount; // Max setup words to return
  1558. // . UCHAR Reserved;
  1559. // . _USHORT( Flags ); // Additional information:
  1560. // // bit 0 - also disconnect TID in Tid
  1561. // // bit 1 - one-way transacion (no resp)
  1562. // D _ULONG( Timeout );
  1563. SMB_OFFSET_CHECK(TRANSACTION,Timeout) 0,
  1564. STUFFER_CTL_NORMAL, "wwpwQyyw",
  1565. 0, // w _USHORT( Reserved2 );
  1566. ParamsLength, // w _USHORT( ParameterCount ); // Parameter bytes sent this buffer
  1567. // p _USHORT( ParameterOffset ); // Offset (from header start) to params
  1568. DataLength, // w _USHORT( DataCount ); // Data bytes sent this buffer
  1569. // Q _USHORT( DataOffset ); // Offset (from header start) to data
  1570. SMB_OFFSET_CHECK(TRANSACTION,DataOffset)
  1571. 1, // y UCHAR SetupCount; // Count of setup words
  1572. 0, // y UCHAR Reserved3; // Reserved (pad above to word)
  1573. // UCHAR Buffer[1]; // Buffer containing:
  1574. TransactSetupCode, // w //USHORT Setup[]; // Setup words (# = SetupWordCount)
  1575. STUFFER_CTL_NORMAL, "ByS6cS5c!",
  1576. SMB_WCT_CHECK(15) // B //USHORT ByteCount; // Count of data bytes
  1577. 0, // y //UCHAR Name[]; // Name of transaction (NULL if Transact2)
  1578. // S //UCHAR Pad[]; // Pad to SHORT or LONG
  1579. // 6c //UCHAR Parameters[]; // Parameter bytes (# = ParameterCount)
  1580. ParamsLength,Params,
  1581. // S //UCHAR Pad1[]; // Pad to SHORT or LONG
  1582. // 5c //UCHAR Data[]; // Data bytes (# = DataCount)
  1583. DataLength,Data
  1584. );
  1585. MRxSmbDumpStufferState (700,"SMB w/ pseT2 after stuffing",StufferState);
  1586. //ASSERT(!"Now it's stuffed");
  1587. if (FixupRoutine) {
  1588. Status = FixupRoutine(OrdinaryExchange);
  1589. if (Status!=STATUS_SUCCESS) {
  1590. goto FINALLY;
  1591. }
  1592. }
  1593. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  1594. OEType
  1595. );
  1596. FINALLY:
  1597. RxDbgTrace(-1, Dbg, ("MRxSmbSimpleSyncTransact2 exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  1598. return(Status);
  1599. }
  1600. NTSTATUS
  1601. MRxSmbFinishTransaction2 (
  1602. IN OUT PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  1603. IN PRESP_TRANSACTION Response
  1604. )
  1605. /*++
  1606. Routine Description:
  1607. This routine finishes a transact2. what it does depends on the OE_TYPE.
  1608. Arguments:
  1609. OrdinaryExchange - the exchange instance
  1610. Response - the response
  1611. Return Value:
  1612. RXSTATUS - The return status for the operation
  1613. --*/
  1614. {
  1615. NTSTATUS Status = (STATUS_SUCCESS);
  1616. PSMBSTUFFER_BUFFER_STATE StufferState = &OrdinaryExchange->AssociatedStufferState;
  1617. PAGED_CODE(); //could actually be nonpaged
  1618. RxDbgTrace(+1, Dbg, ("MRxSmbFinishTransaction2\n", 0 ));
  1619. SmbPseOEAssertConsistentLinkageFromOE("MRxSmbFinishTransaction2:");
  1620. switch (OrdinaryExchange->OEType) {
  1621. case SMBPSE_OETYPE_T2_FOR_NT_FILE_ALLOCATION_INFO:{
  1622. PFILE_STANDARD_INFORMATION StandardInfo;
  1623. if ( (Response->WordCount!=10)
  1624. || (SmbGetUshort(&Response->TotalParameterCount)!=2)
  1625. || (SmbGetUshort(&Response->ParameterCount)!=2)
  1626. || (SmbGetUshort(&Response->ParameterDisplacement)!=0)
  1627. || (SmbGetUshort(&Response->TotalDataCount)!=24)
  1628. || (SmbGetUshort(&Response->DataCount)!=24)
  1629. || (SmbGetUshort(&Response->DataDisplacement)!=0)) {
  1630. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1631. RxDbgTrace(+1, Dbg, ("Invalid parameter(s) received.\n", 0 ));
  1632. break;
  1633. }
  1634. StandardInfo = (PFILE_STANDARD_INFORMATION)
  1635. (StufferState->BufferBase+SmbGetUshort(&Response->DataOffset));
  1636. OrdinaryExchange->Transact2.AllocationSize.LowPart
  1637. = SmbGetUlong(&StandardInfo->AllocationSize.LowPart);
  1638. OrdinaryExchange->Transact2.AllocationSize.HighPart
  1639. = SmbGetUlong(&StandardInfo->AllocationSize.HighPart);
  1640. RxDbgTrace(0, Dbg, ("MRxSmbFinishTransaction2 nt allocation %08lx\n",
  1641. OrdinaryExchange->Transact2.AllocationSize.LowPart ));
  1642. }break;
  1643. case SMBPSE_OETYPE_T2_FOR_LANMAN_DISKATTRIBUTES_INFO:{
  1644. PFILE_FS_SIZE_INFORMATION UsersBuffer = OrdinaryExchange->Info.Buffer;
  1645. PULONG BufferLength = OrdinaryExchange->Info.pBufferLength;
  1646. PQFS_ALLOCATE QfsInfo;
  1647. if (Response->WordCount != 10 ||
  1648. SmbGetUshort(&Response->DataDisplacement) != 0 ||
  1649. SmbGetUshort(&Response->DataCount) != ACTUAL_QFS_ALLOCATE_LENGTH ||
  1650. SmbGetUshort(&Response->TotalDataCount) != ACTUAL_QFS_ALLOCATE_LENGTH ||
  1651. SmbGetUshort(&Response->TotalParameterCount) != SmbGetUshort(&Response->ParameterCount)) {
  1652. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1653. RxDbgTrace(+1, Dbg, ("Invalid parameter(s) received.\n", 0 ));
  1654. break;
  1655. }
  1656. QfsInfo = (PQFS_ALLOCATE)(StufferState->BufferBase+SmbGetUshort(&Response->DataOffset));
  1657. UsersBuffer->TotalAllocationUnits.QuadPart = SmbGetUlong(&QfsInfo->cUnit);
  1658. UsersBuffer->AvailableAllocationUnits.QuadPart = SmbGetUlong(&QfsInfo->cUnitAvail);
  1659. UsersBuffer->SectorsPerAllocationUnit = SmbGetUlong(&QfsInfo->cSectorUnit);
  1660. UsersBuffer->BytesPerSector = SmbGetUshort(&QfsInfo->cbSector);
  1661. *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
  1662. RxDbgTrace(0, Dbg, ("MRxSmbFinishTransaction2 allocation %08lx\n",
  1663. OrdinaryExchange->Transact2.AllocationSize.LowPart ));
  1664. }break;
  1665. case SMBPSE_OETYPE_T2_FOR_LANMAN_VOLUMELABEL_INFO:{
  1666. PFILE_FS_VOLUME_INFORMATION UsersBuffer = OrdinaryExchange->Info.Buffer;
  1667. PULONG BufferLength = OrdinaryExchange->Info.pBufferLength;
  1668. PQFS_INFO QfsInfo;
  1669. ULONG LabelLength;
  1670. PBYTE VolumeLabel = &OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0];
  1671. if (Response->WordCount != 10 ||
  1672. SmbGetUshort(&Response->DataDisplacement) != 0 ||
  1673. SmbGetUshort(&Response->TotalParameterCount) != SmbGetUshort(&Response->ParameterCount)) {
  1674. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1675. RxDbgTrace(+1, Dbg, ("Invalid parameter(s) received.\n", 0 ));
  1676. break;
  1677. }
  1678. QfsInfo = (PQFS_INFO)(StufferState->BufferBase+SmbGetUshort(&Response->DataOffset));
  1679. UsersBuffer->VolumeSerialNumber = SmbGetUlong(&QfsInfo->ulVSN);
  1680. //copy the volumelabel to the right place in the OE where it can UNICODE-ized by the routine above
  1681. LabelLength = min(QfsInfo->cch,12);
  1682. RtlCopyMemory(VolumeLabel,&QfsInfo->szVolLabel[0],LabelLength);
  1683. VolumeLabel[LabelLength] = 0;
  1684. RxDbgTrace(0, Dbg, ("MRxSmbFinishTransaction2 volinfo serialnum= %08lx\n",
  1685. UsersBuffer->VolumeSerialNumber ));
  1686. }break;
  1687. case SMBPSE_OETYPE_T2_FOR_ONE_FILE_DIRCTRL:{
  1688. //do nothing here....everything is done back in the caller with the
  1689. //whole buffer having been copied.....
  1690. RxDbgTrace(0, Dbg, ("MRxSmbFinishTransaction2 one file \n"));
  1691. }break;
  1692. default:
  1693. Status = STATUS_INVALID_NETWORK_RESPONSE;
  1694. }
  1695. RxDbgTrace(-1, Dbg, ("MRxSmbFinishTransaction2 returning %08lx\n", Status ));
  1696. return Status;
  1697. }
  1698.