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.

2398 lines
90 KiB

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