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.

984 lines
36 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. Jim McNelis [JimMcN] 15-November-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, MRxSmbDosPathFunction)
  15. #pragma alloc_text(PAGE, MRxSmbLoadPathFileSearchBuffer)
  16. #pragma alloc_text(PAGE, MRxSmbPathFileSearch)
  17. #pragma alloc_text(PAGE, MrxSmbPathQueryFsVolumeInfo)
  18. #pragma alloc_text(PAGE, MrxSmbPathQueryDiskAttributes)
  19. #pragma alloc_text(PAGE, SmbPseExchangeStart_PathFunction)
  20. #endif
  21. #define Dbg (DEBUG_TRACE_VOLINFO)
  22. extern SMB_EXCHANGE_DISPATCH_VECTOR SmbPseDispatch_PathFunction;
  23. //++
  24. //
  25. // VOID
  26. // NAME_LENGTH(
  27. // OUT ULONG Length,
  28. // IN PUCHAR Ptr
  29. // )
  30. //
  31. // Routine Description:
  32. //
  33. // Determines the length of a Path filename returned by search. This
  34. // is normally a NULL terminated string less than MAXIMUM_COMPONENT_CORE.
  35. // In some cases this is Non-null teminated and space filled.
  36. //
  37. // Arguments:
  38. //
  39. // Length - Returns the string length
  40. // Ptr - The filename to be measured
  41. //
  42. // Return Value:
  43. //
  44. // None.
  45. //
  46. //--
  47. #define NAME_LENGTH( Length, Ptr, Max ) { \
  48. Length = 0; \
  49. while( ((PCHAR)Ptr)[Length] != '\0' ) { \
  50. Length++; \
  51. if ( Length == Max ) { \
  52. break; \
  53. } \
  54. } \
  55. while( ((PCHAR)Ptr)[Length-1] == ' ' && Length ) { \
  56. Length--; \
  57. } \
  58. }
  59. MRxSmbSetDeleteDisposition(
  60. IN PRX_CONTEXT RxContext
  61. );
  62. NTSTATUS
  63. MRxSmbDosPathFunction(
  64. IN OUT PRX_CONTEXT RxContext
  65. )
  66. /*++
  67. Routine Description:
  68. This routine perfoms one of several single path functions to the network
  69. Arguments:
  70. RxContext - the RDBSS context
  71. InformationClass - a class variable that is specific to the call.
  72. sometimes it's a SMB class; sometimes an NT class.
  73. CODE.IMPROVEMENT.ASHAMED we should always use the NT
  74. guy OR we should define some other enumeration that
  75. we like better. consideration of the latter has kept
  76. me from proceeding here..........
  77. pBuffer - pointer to the user's buffer
  78. pBufferLength - a pointer to a ulong containing the bufferlength that is
  79. updated as we go; if it's a setinfo then we deref and
  80. place the actual bufferlength in the OE.
  81. Return Value:
  82. RXSTATUS - The return status for the operation
  83. --*/
  84. {
  85. NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
  86. RxCaptureRequestPacket;
  87. // RxCaptureFcb;
  88. PSMBSTUFFER_BUFFER_STATE StufferState = NULL;
  89. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
  90. PSMB_EXCHANGE Exchange;
  91. PAGED_CODE();
  92. RxDbgTrace(1, Dbg, ("MRxSmbDownLevelQueryInformation\n", 0 ));
  93. switch (RxContext->MajorFunction) {
  94. case DOSBASED_DELETE:
  95. case DOSBASED_DIRFUNCTION:
  96. break;
  97. default:
  98. ASSERT(!"Supposed to be here");
  99. }
  100. StufferState = MRxSmbCreateSmbStufferState(RxContext,
  101. RxContext->DosVolumeFunction.VNetRoot,
  102. RxContext->DosVolumeFunction.NetRoot,
  103. ORDINARY_EXCHANGE,CREATE_SMB_SIZE,
  104. &SmbPseDispatch_PathFunction
  105. );
  106. if (StufferState==NULL) {
  107. RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
  108. return(RX_MAP_STATUS(INSUFFICIENT_RESOURCES));
  109. }
  110. OrdinaryExchange =
  111. (PSMB_PSE_ORDINARY_EXCHANGE)( Exchange = StufferState->Exchange );
  112. OrdinaryExchange->pPathArgument1 = RxContext->DosVolumeFunction.pUniStringParam1;
  113. Status = SmbCeInitiateExchange(Exchange);
  114. //async was turned away at the top level
  115. ASSERT (Status != RX_MAP_STATUS(PENDING));
  116. //NTRAID-455630-2/2/2000-yunlin possible reconnect point
  117. MRxSmbFinalizeSmbStufferState(StufferState);
  118. FINALLY:
  119. RxDbgTrace(-1, Dbg,
  120. ("MRxSmbDownLevelQueryInformation exit with status=%08lx\n",
  121. Status ));
  122. return(Status);
  123. }
  124. extern UNICODE_STRING MRxSmbAll8dot3Files;
  125. #if DBG
  126. #include "stdarg.h"
  127. #include "stdio.h"
  128. #include "string.h"
  129. extern
  130. VOID
  131. MRxSmbDumpResumeKey(
  132. PSZ text,
  133. PSMB_RESUME_KEY ResumeKey
  134. );
  135. #else
  136. #define MRxSmbDumpResumeKey(x,y)
  137. #endif
  138. NTSTATUS
  139. MRxSmbLoadPathFileSearchBuffer(
  140. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  141. )
  142. /*++
  143. Routine Description:
  144. This routine does a CORE_SMB_SEARCH and leaves the result in the SMBbuf.
  145. Arguments:
  146. OrdinaryExchange - an exchange to be used for conducting this open.
  147. Return Value:
  148. RXSTATUS - The return status for the operation
  149. Notes:
  150. --*/
  151. {
  152. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  153. //SMBbuf_STATUS SMBbufStatus;
  154. #ifndef WIN9X
  155. RxCaptureRequestPacket;
  156. RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
  157. // RxCaptureFileObject;
  158. PMRX_SMB_FOBX smbFobx = (PMRX_SMB_FOBX)capFobx;
  159. //PSRV_OPEN SrvOpen = capFobx->SrvOpen;
  160. //PMRX_SMB_SRV_OPEN smbSrvOpen = (PMRX_SMB_SRV_OPEN)SrvOpen;
  161. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  162. PSMBSTUFFER_BUFFER_STATE StufferState;
  163. PSMB_HEADER SmbHeader;
  164. //PUNICODE_STRING DirectoryName;
  165. //PUNICODE_STRING Template;
  166. BOOLEAN FindFirst;
  167. UNICODE_STRING FindFirstPattern;
  168. USHORT ResumeKeyLength;
  169. ULONG ReturnCount;
  170. BOOLEAN EndOfSearchReached;
  171. // SearchAttributes is hardcoded to the magic number 0x16
  172. ULONG SearchAttributes =
  173. (SMB_FILE_ATTRIBUTE_DIRECTORY
  174. | SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN);
  175. PULONG pCountRemainingInSmbbuf = &OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf;
  176. PAGED_CODE();
  177. RxDbgTrace(+1, Dbg, ("MRxSmbLoadPathFileSearchBuffer entering.......OE=%08lx\n",OrdinaryExchange));
  178. RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.PathResumeKey));
  179. if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST)) {
  180. PUNICODE_STRING DirectoryName = &capFcb->AlreadyPrefixedName;
  181. PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
  182. ULONG DirectoryNameLength,TemplateLength,AllocationLength;
  183. PBYTE SmbFileName;
  184. //this is the first time thru....the stuffer cannot handle the intricate logic here so we
  185. //will have to preallocate for the name
  186. if (smbFobx->Enumeration.WildCardsFound = FsRtlDoesNameContainWildCards(Template)){
  187. // we will need to have an upcased template for compares; we do this in place
  188. RtlUpcaseUnicodeString( Template, Template, FALSE );
  189. //CODE.IMPROVEMENT but we should specialcase *.* (altho the fsrtl routine also does it)
  190. Template = &MRxSmbAll8dot3Files; //we will have to filter on this side
  191. }
  192. DirectoryNameLength = DirectoryName->Length;
  193. TemplateLength = Template->Length;
  194. AllocationLength = sizeof(WCHAR) // backslash separator
  195. +DirectoryNameLength
  196. +TemplateLength;
  197. RxDbgTrace(0, Dbg, (" --> d/t/dl/tl/al <%wZ><%wZ>%08lx/%08lx/%08lx!\n",
  198. DirectoryName,Template,
  199. DirectoryNameLength,TemplateLength,AllocationLength));
  200. FindFirstPattern.Buffer = (PWCHAR)RxAllocatePoolWithTag( PagedPool,AllocationLength,'0SxR');
  201. if (FindFirstPattern.Buffer==NULL) {
  202. RxDbgTrace(0, Dbg, (" --> Couldn't get the findfind pattern buffer!\n"));
  203. Status = STATUS_INSUFFICIENT_RESOURCES;
  204. goto FINALLY;
  205. }
  206. SmbFileName = (PBYTE)FindFirstPattern.Buffer;
  207. RtlCopyMemory(SmbFileName,DirectoryName->Buffer,DirectoryNameLength);
  208. SmbFileName += DirectoryNameLength;
  209. if (*((PWCHAR)(SmbFileName-sizeof(WCHAR))) != L'\\') {
  210. *((PWCHAR)SmbFileName) = L'\\'; SmbFileName+= sizeof(WCHAR);
  211. }
  212. RtlCopyMemory(SmbFileName,Template->Buffer,TemplateLength);
  213. SmbFileName += TemplateLength;
  214. if ((TemplateLength == sizeof(WCHAR)) && (Template->Buffer[0]==DOS_STAR)) {
  215. *((PWCHAR)SmbFileName) = L'.'; SmbFileName+= sizeof(WCHAR);
  216. *((PWCHAR)SmbFileName) = L'*'; SmbFileName+= sizeof(WCHAR);
  217. }
  218. //*((PWCHAR)SmbFileName) = 0; SmbFileName+= sizeof(WCHAR); //trailing NULL;
  219. //CODE.IMPROVEMENT we should potentially 8.3ize the string here
  220. FindFirstPattern.Length = (USHORT)(SmbFileName - (PBYTE)FindFirstPattern.Buffer);
  221. RxDbgTrace(0, Dbg, (" --> find1stpattern <%wZ>!\n",&FindFirstPattern));
  222. FindFirst = TRUE;
  223. ResumeKeyLength = 0;
  224. } else {
  225. RxDbgTrace(0, Dbg, ("-->FINDNEXT\n"));
  226. FindFirstPattern.Buffer = NULL;
  227. if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS)) {
  228. Status = smbFobx->Enumeration.ErrorStatus;
  229. RxDbgTrace(0, Dbg, ("-->ERROR EARLY OUT\n"));
  230. goto FINALLY;
  231. }
  232. FindFirst = FALSE;
  233. FindFirstPattern.Length = 0;
  234. ResumeKeyLength = sizeof(SMB_RESUME_KEY);
  235. MRxSmbDumpResumeKey("FindNext:",smbFobx->Enumeration.PathResumeKey);
  236. }
  237. //get the correct return count. there are three factors: countremaining from the OE,
  238. // how many could fit the the user's buffer, and how many could fit in a negotiated buffer.
  239. // we pick the smallest of the three.
  240. ReturnCount = OrdinaryExchange->Info.CoreSearch.CountRemaining;
  241. { ULONG t = (*OrdinaryExchange->Info.pBufferLength) / smbFobx->Enumeration.FileNameOffset;
  242. if (t<ReturnCount) { ReturnCount = t; }
  243. }
  244. { PSMBCE_SERVER pServer = &((PSMB_EXCHANGE)OrdinaryExchange)->SmbCeContext.pServerEntry->Server;
  245. ULONG AvailableBufferSize = pServer->MaximumBufferSize -
  246. (sizeof(SMB_HEADER) +
  247. FIELD_OFFSET(RESP_SEARCH,Buffer[0])
  248. +sizeof(UCHAR)+sizeof(USHORT) //bufferformat,datalength fields
  249. );
  250. ULONG t = AvailableBufferSize / sizeof(SMB_DIRECTORY_INFORMATION);
  251. if (t<ReturnCount) { ReturnCount = t; }
  252. }
  253. RxDbgTrace( 0, Dbg, ("-------->count=%08lx\n",ReturnCount));
  254. if (ReturnCount==0) {
  255. Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED);
  256. RxDbgTrace(0, Dbg, ("-->Count==0 EARLY OUT\n"));
  257. goto FINALLY;
  258. }
  259. StufferState = OrdinaryExchange->StufferState;
  260. ASSERT( StufferState );
  261. *pCountRemainingInSmbbuf = 0;
  262. OrdinaryExchange->Info.CoreSearch.NextDirInfo = NULL;
  263. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,
  264. SMB_COM_SEARCH, SMB_REQUEST_SIZE(SEARCH),
  265. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  266. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  267. );
  268. RxDbgTrace(0, Dbg,("core search command initial status = %lu\n",Status));
  269. MRxSmbDumpStufferState (1100,"SMB w/ core search before stuffing",StufferState);
  270. MRxSmbStuffSMB (StufferState,
  271. "0wwB4ywc!",
  272. // 0 UCHAR WordCount; // Count of parameter words = 2
  273. ReturnCount, // w _USHORT( MaxCount ); // Number of dir. entries to return
  274. SearchAttributes, // w _USHORT( SearchAttributes );
  275. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
  276. // UCHAR Buffer[1]; // Buffer containing:
  277. &FindFirstPattern, // 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
  278. // //UCHAR FileName[]; // File name, may be null
  279. 0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
  280. ResumeKeyLength, // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
  281. // c //UCHAR SearchStatus[]; // Resume key
  282. ResumeKeyLength,smbFobx->Enumeration.PathResumeKey
  283. );
  284. MRxSmbDumpStufferState (700,"SMB w/ core search after stuffing",StufferState);
  285. //ASSERT(!"Now it's stuffed");
  286. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  287. SMBPSE_OETYPE_CORESEARCH
  288. );
  289. if (!NT_SUCCESS(Status)) goto FINALLY;
  290. smbFobx->Enumeration.Flags |= SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST|SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  291. //if (Status==RxStatus(SUCCESS) && FilesReturned==0) {
  292. // RxDbgTrace( 0, Dbg, ("MRxSmbQueryDirectory: no files returned...switch status\n"));
  293. // EndOfSearchReached = TRUE;
  294. // Status = RxStatus(NO_MORE_FILES);
  295. //}
  296. if (Status==RX_MAP_STATUS(SUCCESS) && *pCountRemainingInSmbbuf==0) {
  297. RxDbgTrace( 0, Dbg, ("MRxSmbLoadPathFileSearchBuffer: no files returned...switch status\n"));
  298. EndOfSearchReached = TRUE;
  299. Status = RX_MAP_STATUS(NO_MORE_FILES);
  300. } else {
  301. //CODE.IMPROVEMENT a possible improvement here is to know that the search is closed
  302. // based on a "smaller-than-normal" return; we would key this off of the
  303. // operatingsystem return string i guess. for NT systems, we don't do this
  304. EndOfSearchReached = FALSE;
  305. }
  306. if (EndOfSearchReached) {
  307. RxDbgTrace( 0, Dbg, ("MRxSmbLoadPathFileSearchBuffer: no longer in progress...EOS\n"));
  308. smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  309. smbFobx->Enumeration.ErrorStatus = RX_MAP_STATUS(NO_MORE_FILES);
  310. }
  311. //we dont save a resume key here since each individual copy operation will have to do that
  312. FINALLY:
  313. if (FindFirstPattern.Buffer != NULL) {
  314. RxFreePool(FindFirstPattern.Buffer);
  315. }
  316. if (!NT_SUCCESS(Status)&&(Status!=RX_MAP_STATUS(MORE_PROCESSING_REQUIRED))) {
  317. RxDbgTrace( 0, Dbg, ("MRxSmbPathFileSearch: Failed .. returning %lx\n",Status));
  318. smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
  319. smbFobx->Enumeration.ErrorStatus = Status; //keep returning this
  320. }
  321. RxDbgTrace(-1, Dbg, ("MRxSmbLoadPathFileSearchBuffer exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  322. #endif
  323. return(Status);
  324. }
  325. #define ASSERT_SAME_FIELD(__field,__t1,__t2) { \
  326. ASSERT(FIELD_OFFSET(__t1,__field)==FIELD_OFFSET(__t2,__field)); \
  327. }
  328. #define ASSERT_SAME_DIRINFO_FIELDS(__t1,__t2) {\
  329. ASSERT_SAME_FIELD(LastWriteTime,__t1,__t2); \
  330. ASSERT_SAME_FIELD(EndOfFile,__t1,__t2); \
  331. ASSERT_SAME_FIELD(AllocationSize,__t1,__t2); \
  332. ASSERT_SAME_FIELD(FileAttributes,__t1,__t2); \
  333. }
  334. #if DBG
  335. VOID MRxSmbPathFileSeach_AssertFields(void){
  336. //just move this out of the main execution path so that we don't have to look at it while
  337. //we Uing the code
  338. ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_FULL_DIR_INFORMATION);
  339. ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_BOTH_DIR_INFORMATION);
  340. }
  341. #else
  342. #define MRxSmbPathFileSeach_AssertFields()
  343. #endif
  344. NTSTATUS
  345. MRxSmbPathFileSearch(
  346. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  347. )
  348. /*++
  349. Routine Description:
  350. This routine does a GetFileAttributes and remembers the reponse.
  351. Arguments:
  352. OrdinaryExchange - an exchange to be used for conducting this open.
  353. Return Value:
  354. RXSTATUS - The return status for the operation
  355. Notes:
  356. --*/
  357. {
  358. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  359. //SMBbuf_STATUS SMBbufStatus;
  360. #ifndef WIN9X
  361. RxCaptureRequestPacket;
  362. RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
  363. // RxCaptureFileObject;
  364. PMRX_SMB_FOBX smbFobx = (PMRX_SMB_FOBX)capFobx;
  365. PBYTE pBuffer = OrdinaryExchange->Info.Buffer;
  366. PULONG pLengthRemaining = OrdinaryExchange->Info.pBufferLength;
  367. ULONG InformationClass = OrdinaryExchange->Info.InfoClass;
  368. PFILE_DIRECTORY_INFORMATION pPreviousBuffer = NULL;
  369. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  370. ULONG SuccessCount = 0;
  371. PAGED_CODE();
  372. RxDbgTrace(+1, Dbg, ("MRxSmbPathFileSearch entering.......OE=%08lx\n",OrdinaryExchange));
  373. MRxSmbPathFileSeach_AssertFields();
  374. OrdinaryExchange->Info.CoreSearch.CountRemaining =
  375. RxContext->QueryD.ReturnSingleEntry?1:0x7ffffff;
  376. if ( (smbFobx->Enumeration.PathResumeKey ==NULL )
  377. && ((smbFobx->Enumeration.PathResumeKey = RxAllocatePoolWithTag(PagedPool,sizeof(SMB_RESUME_KEY),'rbms'))==NULL) ){
  378. RxDbgTrace(0, Dbg, ("...couldn't allocate resume key\n"));
  379. Status = RX_MAP_STATUS(INSUFFICIENT_RESOURCES);
  380. goto FINALLY;
  381. }
  382. RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.PathResumeKey));
  383. Status = MRxSmbLoadPathFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
  384. for (;;) {
  385. BOOLEAN BufferOverflow = FALSE;
  386. PSMB_DIRECTORY_INFORMATION NextDirInfo;
  387. UNICODE_STRING FileNameU;
  388. OEM_STRING FileNameA;
  389. WCHAR FileNameU_buffer[14];
  390. ULONG NameLength;
  391. PBYTE NextFileName;
  392. BOOLEAN Match,BufferOverFlow;
  393. if (!NT_SUCCESS(Status)) {
  394. if (Status = RX_MAP_STATUS(NO_MORE_FILES)) {
  395. if (SuccessCount > 0) {
  396. Status = RX_MAP_STATUS(SUCCESS);
  397. }
  398. } else if (Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED)) {
  399. if (SuccessCount > 0) {
  400. Status = RX_MAP_STATUS(SUCCESS);
  401. } else {
  402. Status = RX_MAP_STATUS(BUFFER_OVERFLOW);
  403. }
  404. }
  405. goto FINALLY;
  406. }
  407. ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemaining>0 );
  408. ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf>0 );
  409. RxDbgTrace(0, Dbg, ("MRxSmbPathFileSearch looptopcheck counts=%08lx,%08lx\n",
  410. OrdinaryExchange->Info.CoreSearch.CountRemaining,
  411. OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf
  412. ));
  413. //next issue: does the next dirinfo match the criteria?!?
  414. NextDirInfo = OrdinaryExchange->Info.CoreSearch.NextDirInfo;
  415. NextFileName = &NextDirInfo->FileName[0];
  416. // According to colinw, some core servers do not remember to insert the null at the end of the name...
  417. // but the namelength macro handles this correctly. some servers (Xenix, apparently) pad the
  418. // names with spaces. again, the macro handles it....
  419. //
  420. NAME_LENGTH(NameLength, NextFileName,sizeof(NextDirInfo->FileName));
  421. FileNameA.Length = (USHORT)NameLength;
  422. FileNameA.MaximumLength = (USHORT)NameLength;
  423. FileNameA.Buffer = NextFileName;
  424. FileNameU.Length = sizeof(FileNameU_buffer);
  425. FileNameU.MaximumLength = sizeof(FileNameU_buffer);
  426. FileNameU.Buffer = &FileNameU_buffer[0];
  427. Status = RtlOemStringToUnicodeString(&FileNameU, &FileNameA, TRUE);
  428. RxDbgTrace(0, Dbg, ("MRxSmbPathFileSearch considering.......filename=%wZ, template=%wZ\n",
  429. &FileNameU,&capFobx->UnicodeQueryTemplate));
  430. ASSERT(Status==RX_MAP_STATUS(SUCCESS));
  431. // we deal with a conversion failure by skipping this guy
  432. Match = (Status==RX_MAP_STATUS(SUCCESS));
  433. if (Match && smbFobx->Enumeration.WildCardsFound ) {
  434. //DbgBreakPoint();
  435. try
  436. {
  437. Match = FsRtlIsNameInExpression( &capFobx->UnicodeQueryTemplate,
  438. &FileNameU, TRUE, NULL );
  439. }
  440. except(EXCEPTION_EXECUTE_HANDLER)
  441. {
  442. Match = FALSE;
  443. }
  444. }
  445. //next issue: will the next dirinfo fit in the user's buffer?!?
  446. if (Match) {
  447. ULONG SpaceNeeded;
  448. PBYTE pRememberBuffer = pBuffer;
  449. pBuffer = (PBYTE)LongAlign(pBuffer); //assume that this will fit
  450. SpaceNeeded = smbFobx->Enumeration.FileNameOffset+FileNameU.Length;
  451. if (pBuffer+SpaceNeeded > pRememberBuffer+*pLengthRemaining) {
  452. BufferOverflow = TRUE;
  453. pBuffer = pRememberBuffer; //rollback
  454. } else {
  455. PFILE_DIRECTORY_INFORMATION pThisBuffer = (PFILE_DIRECTORY_INFORMATION)pBuffer;
  456. SMB_TIME Time;
  457. SMB_DATE Date;
  458. BufferOverflow = FALSE;
  459. if (pPreviousBuffer != NULL) {
  460. pPreviousBuffer->NextEntryOffset = ((PBYTE)pThisBuffer)-((PBYTE)pPreviousBuffer);
  461. }
  462. pPreviousBuffer = pThisBuffer;
  463. RtlZeroMemory(pBuffer,smbFobx->Enumeration.FileNameOffset);
  464. RtlCopyMemory(pBuffer+smbFobx->Enumeration.FileNameOffset, FileNameU.Buffer,FileNameU.Length);
  465. *((PULONG)(pBuffer+smbFobx->Enumeration.FileNameLengthOffset)) = FileNameU.Length;
  466. //hallucinate the record based on specific return type
  467. switch (InformationClass) {
  468. case SMB_FIND_FILE_NAMES_INFO:
  469. break;
  470. case SMB_FIND_FILE_DIRECTORY_INFO:
  471. case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
  472. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  473. //just fill what we have...we do not go to a lot of trouble on allocinfo as rdr1 did.
  474. // actually, rdr1 didn't do that here...only on getfielinfo.......
  475. SmbMoveTime (&Time, &NextDirInfo->LastWriteTime);
  476. SmbMoveDate (&Date, &NextDirInfo->LastWriteDate);
  477. pThisBuffer->LastWriteTime = MRxSmbConvertSmbTimeToTime(Exchange, Time, Date);
  478. pThisBuffer->EndOfFile.LowPart = SmbGetUlong(&NextDirInfo->FileSize);
  479. pThisBuffer->FileAttributes = MRxSmbMapSmbAttributes (NextDirInfo->FileAttributes);
  480. break;
  481. default:
  482. RxDbgTrace( 0, Dbg, ("MRxSmbPathFileSearch: Invalid FS information class\n"));
  483. ASSERT(!"this can't happen");
  484. Status = STATUS_INVALID_PARAMETER;
  485. goto FINALLY;
  486. }
  487. pBuffer += SpaceNeeded;
  488. *pLengthRemaining -= pBuffer-pRememberBuffer;
  489. OrdinaryExchange->Info.CoreSearch.CountRemaining--;
  490. SuccessCount++;
  491. }
  492. }
  493. //
  494. // if no match or no overflow, move up in the buffer. this means not only juggling the
  495. // pointers but also saving the resume key
  496. if (!Match || !BufferOverflow) {
  497. MRxSmbDumpResumeKey("BufferKey:",&NextDirInfo->ResumeKey);
  498. *(smbFobx->Enumeration.PathResumeKey) = NextDirInfo->ResumeKey;
  499. MRxSmbDumpResumeKey("SaveKey: ",smbFobx->Enumeration.PathResumeKey);
  500. OrdinaryExchange->Info.CoreSearch.NextDirInfo = NextDirInfo + 1;
  501. OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf--;
  502. }
  503. if (OrdinaryExchange->Info.CoreSearch.CountRemaining==0) {
  504. Status = RX_MAP_STATUS(SUCCESS);
  505. goto FINALLY;
  506. }
  507. //should we jam these together by smashing the countrem to 0 on bufferoverflow??? CODE.IMPROVEMENT
  508. if (BufferOverflow) {
  509. Status = (SuccessCount==0)?RX_MAP_STATUS(BUFFER_OVERFLOW):RX_MAP_STATUS(SUCCESS);
  510. goto FINALLY;
  511. }
  512. if (OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf==0) {
  513. Status = MRxSmbLoadPathFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
  514. }
  515. }
  516. FINALLY:
  517. RxDbgTrace(-1, Dbg, ("MRxSmbPathFileSearch exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  518. //CODE.IMPROVEMENT if we're done with the resume key we could free it!
  519. #endif
  520. return(Status);
  521. }
  522. NTSTATUS
  523. MrxSmbPathQueryFsVolumeInfo(
  524. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  525. )
  526. /*++
  527. Routine Description:
  528. This routine does a GetFileAttributes and remembers the reponse.
  529. Arguments:
  530. OrdinaryExchange - an exchange to be used for conducting this open.
  531. Return Value:
  532. RXSTATUS - The return status for the operation
  533. Notes:
  534. --*/
  535. {
  536. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  537. //SMBbuf_STATUS SMBbufStatus;
  538. #ifndef WIN9X
  539. RxCaptureRequestPacket;
  540. RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
  541. // RxCaptureFileObject;
  542. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  543. PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
  544. PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
  545. PSMBSTUFFER_BUFFER_STATE StufferState;
  546. PAGED_CODE();
  547. RxDbgTrace(+1, Dbg, ("MrxSmbPathQueryFsVolumeInfo entering.......OE=%08lx\n",OrdinaryExchange));
  548. StufferState = OrdinaryExchange->StufferState;
  549. ASSERT( StufferState );
  550. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_SEARCH,
  551. SMB_REQUEST_SIZE(SEARCH),
  552. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  553. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  554. );
  555. MRxSmbDumpStufferState (1100,"SMB w/ searchvolumelabel before stuffing",StufferState);
  556. //CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
  557. // otherwise, we don't need to copy the name here, we can just Mdl like in writes
  558. MRxSmbStuffSMB (StufferState,
  559. "0wwB4yw!",
  560. // 0 UCHAR WordCount; // Count of parameter words = 2
  561. 1, // w _USHORT( MaxCount ); // Number of dir. entries to return
  562. // w _USHORT( SearchAttributes );
  563. SMB_FILE_ATTRIBUTE_VOLUME,
  564. SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
  565. // UCHAR Buffer[1]; // Buffer containing:
  566. &MRxSmbAll8dot3Files,// 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
  567. // //UCHAR FileName[]; // File name, may be null
  568. 0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
  569. 0 // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
  570. // //UCHAR SearchStatus[]; // Resume key
  571. );
  572. MRxSmbDumpStufferState (700,"SMB w/ searchvolumelabel after stuffing",StufferState);
  573. //ASSERT(!"Now it's stuffed");
  574. OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] = 0; //no label
  575. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  576. SMBPSE_OETYPE_COREQUERYLABEL
  577. );
  578. //Status = RxStatus(NOT_IMPLEMENTED);
  579. ASSERT ( *pBufferLength>=sizeof(FILE_FS_VOLUME_INFORMATION));
  580. RxDbgTrace(0, Dbg, ("MrxSmbPathQueryFsVolumeInfo OEstatus=%08lx\n",Status));
  581. //DbgBreakPoint();
  582. pBuffer->SupportsObjects = FALSE;
  583. pBuffer->VolumeCreationTime.LowPart = 0;
  584. pBuffer->VolumeCreationTime.HighPart = 0;
  585. pBuffer->VolumeSerialNumber = 0;
  586. pBuffer->VolumeLabelLength = 0;
  587. if (NT_SUCCESS(Status) &&
  588. (OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] != 0) ) {
  589. UNICODE_STRING VolumeLabelU;
  590. OEM_STRING VolumeLabelA;
  591. SMB_DIRECTORY_INFORMATION Buffer;
  592. ULONG NameLength;
  593. ULONG BytesToCopy;
  594. PBYTE VolumeLabel = &OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0];
  595. //pBuffer->VolumeSerialNumber =
  596. // (((SmbGetUshort(&Buffer.LastWriteTime.Ushort)) << 16) |
  597. // (SmbGetUshort(&Buffer.LastWriteDate.Ushort)));
  598. NAME_LENGTH(NameLength, VolumeLabel,
  599. sizeof(OrdinaryExchange->Info.QFSVolInfo.CoreLabel));
  600. VolumeLabelA.Length = (USHORT)NameLength;
  601. VolumeLabelA.MaximumLength = (USHORT)NameLength;
  602. VolumeLabelA.Buffer = VolumeLabel;
  603. //some core servers put a '.' in the labelname.....if it's there then remove it
  604. if ((NameLength>8)&& (VolumeLabel[8]=='.') ) {
  605. ULONG i;
  606. for (i=8;i<NameLength;i++) {
  607. VolumeLabel[i] = VolumeLabel[i+1];
  608. }
  609. }
  610. Status = RtlOemStringToUnicodeString(&VolumeLabelU, &VolumeLabelA, TRUE);
  611. if (NT_SUCCESS(Status)) {
  612. ULONG BytesToCopy = min((ULONG)VolumeLabelU.Length, (*pBufferLength-sizeof(FILE_FS_VOLUME_INFORMATION)));
  613. RtlCopyMemory(&pBuffer->VolumeLabel[0],
  614. VolumeLabelU.Buffer,
  615. BytesToCopy);
  616. *pBufferLength -= BytesToCopy;
  617. pBuffer->VolumeLabelLength = VolumeLabelU.Length;
  618. IF_DEBUG {
  619. UNICODE_STRING FinalLabel;
  620. FinalLabel.Buffer = &pBuffer->VolumeLabel[0];
  621. FinalLabel.Length = (USHORT)BytesToCopy;
  622. RxDbgTrace(0, Dbg, ("MrxSmbPathQueryFsVolumeInfo vollabel=%wZ\n",&FinalLabel));
  623. }
  624. RtlFreeUnicodeString(&VolumeLabelU);
  625. }
  626. } else if (Status == RX_MAP_STATUS(NO_SUCH_FILE)) {
  627. //
  628. // If we got no such file, this means that there's no volume label
  629. // the remote volume. Return success with no data.
  630. //
  631. Status = RX_MAP_STATUS(SUCCESS);
  632. }
  633. if (NT_SUCCESS(Status)) {
  634. *pBufferLength -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,VolumeLabel);
  635. }
  636. FINALLY:
  637. RxDbgTrace(-1, Dbg, ("MrxSmbPathQueryFsVolumeInfo exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  638. #endif
  639. return(Status);
  640. }
  641. NTSTATUS
  642. MrxSmbPathQueryDiskAttributes(
  643. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  644. )
  645. /*++
  646. Routine Description:
  647. This routine does a GetDiskAttributes and remembers the reponse.
  648. Arguments:
  649. OrdinaryExchange - an exchange to be used for conducting this open.
  650. Return Value:
  651. RXSTATUS - The return status for the operation
  652. Notes:
  653. --*/
  654. {
  655. NTSTATUS Status;
  656. //SMBbuf_STATUS SMBbufStatus;
  657. RxCaptureRequestPacket;
  658. RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
  659. // RxCaptureFileObject;
  660. PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
  661. PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
  662. PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
  663. PSMBSTUFFER_BUFFER_STATE StufferState;
  664. PAGED_CODE();
  665. RxDbgTrace(+1, Dbg, ("MrxSmbPathQueryDiskAttributes entering.......OE=%08lx\n",OrdinaryExchange));
  666. StufferState = OrdinaryExchange->StufferState;
  667. ASSERT( StufferState );
  668. COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_QUERY_INFORMATION_DISK,
  669. SMB_REQUEST_SIZE(QUERY_INFORMATION_DISK),
  670. NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
  671. 0,0,0,0 STUFFERTRACE(Dbg,'FC'))
  672. );
  673. RxDbgTrace(0, Dbg,("querydiskattribs command initial status = %lu\n",Status));
  674. MRxSmbDumpStufferState (1100,"SMB w/ querydiskattribs before stuffing",StufferState);
  675. MRxSmbStuffSMB (StufferState,
  676. "0B!",
  677. // 0 UCHAR WordCount; // Count of parameter words = 0
  678. SMB_WCT_CHECK(0) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
  679. // UCHAR Buffer[1]; // empty
  680. );
  681. MRxSmbDumpStufferState (700,"SMB w/ querydiskattribs after stuffing",StufferState);
  682. //ASSERT(!"Now it's stuffed");
  683. Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
  684. SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES
  685. );
  686. FINALLY:
  687. RxDbgTrace(-1, Dbg, ("MrxSmbPathQueryDiskAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
  688. return(Status);
  689. }
  690. NTSTATUS
  691. MRxSmbGetFileAttributes(
  692. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
  693. );
  694. NTSTATUS
  695. MRxSmbCoreDeleteForSupercedeOrClose(
  696. SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
  697. BOOLEAN DeleteDirectory
  698. );
  699. NTSTATUS
  700. SmbPseExchangeStart_PathFunction(
  701. PSMB_EXCHANGE pExchange)
  702. /*++
  703. Routine Description:
  704. This is the start routine for VOLINFO.
  705. Arguments:
  706. pExchange - the exchange instance
  707. Return Value:
  708. RXSTATUS - The return status for the operation
  709. --*/
  710. {
  711. NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
  712. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
  713. (PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
  714. PSMBSTUFFER_BUFFER_STATE StufferState = OrdinaryExchange->StufferState;
  715. PRX_CONTEXT RxContext = StufferState->RxContext;
  716. PAGED_CODE();
  717. RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_PathFunction\n", 0 ));
  718. ASSERT(pExchange->Type == ORDINARY_EXCHANGE);
  719. MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
  720. //ASSERT (StufferState->CurrentCommand == SMB_COM_NO_ANDX_COMMAND);
  721. switch (RxContext->MajorFunction) {
  722. case DOSBASED_DELETE:
  723. Status = MRxSmbCoreDeleteForSupercedeOrClose(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, FALSE);
  724. goto FINALLY;
  725. case DOSBASED_DIRFUNCTION:
  726. switch (RxContext->MinorFunction) {
  727. case DOSBASED_CREATEDIR:
  728. break;
  729. case DOSBASED_DELETEDIR:
  730. Status = MRxSmbCoreDeleteForSupercedeOrClose(
  731. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, TRUE);
  732. goto FINALLY;
  733. case DOSBASED_CHECKDIR:
  734. Status = MRxSmbCoreCheckDirFunction(
  735. SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
  736. goto FINALLY;
  737. case DOSBASED_QUERY83DIR:
  738. break;
  739. default:
  740. ASSERT(!"DIR MINOR FUNCTION SUPPOSED TO BE HERE!");
  741. }
  742. default:
  743. ASSERT(!"Supposed to be here");
  744. }
  745. FINALLY:
  746. RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_PathFunction exit w %08lx\n", Status ));
  747. return Status;
  748. }
  749. extern
  750. NTSTATUS
  751. MRxSmbFinishSearch (
  752. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  753. PRESP_SEARCH Response
  754. );
  755. extern
  756. NTSTATUS
  757. MRxSmbFinishQueryDiskInfo (
  758. PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
  759. PRESP_QUERY_INFORMATION_DISK Response
  760. );
  761. SMB_EXCHANGE_DISPATCH_VECTOR
  762. SmbPseDispatch_PathFunction = {
  763. SmbPseExchangeStart_PathFunction,
  764. SmbPseExchangeReceive_default,
  765. SmbPseExchangeCopyDataHandler_default,
  766. SmbPseExchangeSendCallbackHandler_default,
  767. SmbPseExchangeFinalize_default,
  768. NULL
  769. };
  770.