Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

985 lines
36 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
DownLvlI.c
Abstract:
This module implements downlevel fileinfo, volinfo, and dirctrl.
Author:
Jim McNelis [JimMcN] 15-November-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxSmbDosPathFunction)
#pragma alloc_text(PAGE, MRxSmbLoadPathFileSearchBuffer)
#pragma alloc_text(PAGE, MRxSmbPathFileSearch)
#pragma alloc_text(PAGE, MrxSmbPathQueryFsVolumeInfo)
#pragma alloc_text(PAGE, MrxSmbPathQueryDiskAttributes)
#pragma alloc_text(PAGE, SmbPseExchangeStart_PathFunction)
#endif
#define Dbg (DEBUG_TRACE_VOLINFO)
extern SMB_EXCHANGE_DISPATCH_VECTOR SmbPseDispatch_PathFunction;
//++
//
// VOID
// NAME_LENGTH(
// OUT ULONG Length,
// IN PUCHAR Ptr
// )
//
// Routine Description:
//
// Determines the length of a Path filename returned by search. This
// is normally a NULL terminated string less than MAXIMUM_COMPONENT_CORE.
// In some cases this is Non-null teminated and space filled.
//
// Arguments:
//
// Length - Returns the string length
// Ptr - The filename to be measured
//
// Return Value:
//
// None.
//
//--
#define NAME_LENGTH( Length, Ptr, Max ) { \
Length = 0; \
while( ((PCHAR)Ptr)[Length] != '\0' ) { \
Length++; \
if ( Length == Max ) { \
break; \
} \
} \
while( ((PCHAR)Ptr)[Length-1] == ' ' && Length ) { \
Length--; \
} \
}
MRxSmbSetDeleteDisposition(
IN PRX_CONTEXT RxContext
);
NTSTATUS
MRxSmbDosPathFunction(
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine perfoms one of several single path functions to the network
Arguments:
RxContext - the RDBSS context
InformationClass - a class variable that is specific to the call.
sometimes it's a SMB class; sometimes an NT class.
CODE.IMPROVEMENT.ASHAMED we should always use the NT
guy OR we should define some other enumeration that
we like better. consideration of the latter has kept
me from proceeding here..........
pBuffer - pointer to the user's buffer
pBufferLength - a pointer to a ulong containing the bufferlength that is
updated as we go; if it's a setinfo then we deref and
place the actual bufferlength in the OE.
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = RX_MAP_STATUS(SUCCESS);
RxCaptureRequestPacket;
// RxCaptureFcb;
PSMBSTUFFER_BUFFER_STATE StufferState = NULL;
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange = NULL;
PSMB_EXCHANGE Exchange;
PAGED_CODE();
RxDbgTrace(1, Dbg, ("MRxSmbDownLevelQueryInformation\n", 0 ));
switch (RxContext->MajorFunction) {
case DOSBASED_DELETE:
case DOSBASED_DIRFUNCTION:
break;
default:
ASSERT(!"Supposed to be here");
}
StufferState = MRxSmbCreateSmbStufferState(RxContext,
RxContext->DosVolumeFunction.VNetRoot,
RxContext->DosVolumeFunction.NetRoot,
ORDINARY_EXCHANGE,CREATE_SMB_SIZE,
&SmbPseDispatch_PathFunction
);
if (StufferState==NULL) {
RxDbgTrace(-1, Dbg, ("Couldn't get the smb buf!\n"));
return(RX_MAP_STATUS(INSUFFICIENT_RESOURCES));
}
OrdinaryExchange =
(PSMB_PSE_ORDINARY_EXCHANGE)( Exchange = StufferState->Exchange );
OrdinaryExchange->pPathArgument1 = RxContext->DosVolumeFunction.pUniStringParam1;
Status = SmbCeInitiateExchange(Exchange);
//async was turned away at the top level
ASSERT (Status != RX_MAP_STATUS(PENDING));
//NTRAID-455630-2/2/2000-yunlin possible reconnect point
MRxSmbFinalizeSmbStufferState(StufferState);
FINALLY:
RxDbgTrace(-1, Dbg,
("MRxSmbDownLevelQueryInformation exit with status=%08lx\n",
Status ));
return(Status);
}
extern UNICODE_STRING MRxSmbAll8dot3Files;
#if DBG
#include "stdarg.h"
#include "stdio.h"
#include "string.h"
extern
VOID
MRxSmbDumpResumeKey(
PSZ text,
PSMB_RESUME_KEY ResumeKey
);
#else
#define MRxSmbDumpResumeKey(x,y)
#endif
NTSTATUS
MRxSmbLoadPathFileSearchBuffer(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This routine does a CORE_SMB_SEARCH and leaves the result in the SMBbuf.
Arguments:
OrdinaryExchange - an exchange to be used for conducting this open.
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
//SMBbuf_STATUS SMBbufStatus;
#ifndef WIN9X
RxCaptureRequestPacket;
RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
// RxCaptureFileObject;
PMRX_SMB_FOBX smbFobx = (PMRX_SMB_FOBX)capFobx;
//PSRV_OPEN SrvOpen = capFobx->SrvOpen;
//PMRX_SMB_SRV_OPEN smbSrvOpen = (PMRX_SMB_SRV_OPEN)SrvOpen;
PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
PSMBSTUFFER_BUFFER_STATE StufferState;
PSMB_HEADER SmbHeader;
//PUNICODE_STRING DirectoryName;
//PUNICODE_STRING Template;
BOOLEAN FindFirst;
UNICODE_STRING FindFirstPattern;
USHORT ResumeKeyLength;
ULONG ReturnCount;
BOOLEAN EndOfSearchReached;
// SearchAttributes is hardcoded to the magic number 0x16
ULONG SearchAttributes =
(SMB_FILE_ATTRIBUTE_DIRECTORY
| SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN);
PULONG pCountRemainingInSmbbuf = &OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbLoadPathFileSearchBuffer entering.......OE=%08lx\n",OrdinaryExchange));
RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.PathResumeKey));
if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST)) {
PUNICODE_STRING DirectoryName = &capFcb->AlreadyPrefixedName;
PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
ULONG DirectoryNameLength,TemplateLength,AllocationLength;
PBYTE SmbFileName;
//this is the first time thru....the stuffer cannot handle the intricate logic here so we
//will have to preallocate for the name
if (smbFobx->Enumeration.WildCardsFound = FsRtlDoesNameContainWildCards(Template)){
// we will need to have an upcased template for compares; we do this in place
RtlUpcaseUnicodeString( Template, Template, FALSE );
//CODE.IMPROVEMENT but we should specialcase *.* (altho the fsrtl routine also does it)
Template = &MRxSmbAll8dot3Files; //we will have to filter on this side
}
DirectoryNameLength = DirectoryName->Length;
TemplateLength = Template->Length;
AllocationLength = sizeof(WCHAR) // backslash separator
+DirectoryNameLength
+TemplateLength;
RxDbgTrace(0, Dbg, (" --> d/t/dl/tl/al <%wZ><%wZ>%08lx/%08lx/%08lx!\n",
DirectoryName,Template,
DirectoryNameLength,TemplateLength,AllocationLength));
FindFirstPattern.Buffer = (PWCHAR)RxAllocatePoolWithTag( PagedPool,AllocationLength,'0SxR');
if (FindFirstPattern.Buffer==NULL) {
RxDbgTrace(0, Dbg, (" --> Couldn't get the findfind pattern buffer!\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto FINALLY;
}
SmbFileName = (PBYTE)FindFirstPattern.Buffer;
RtlCopyMemory(SmbFileName,DirectoryName->Buffer,DirectoryNameLength);
SmbFileName += DirectoryNameLength;
if (*((PWCHAR)(SmbFileName-sizeof(WCHAR))) != L'\\') {
*((PWCHAR)SmbFileName) = L'\\'; SmbFileName+= sizeof(WCHAR);
}
RtlCopyMemory(SmbFileName,Template->Buffer,TemplateLength);
SmbFileName += TemplateLength;
if ((TemplateLength == sizeof(WCHAR)) && (Template->Buffer[0]==DOS_STAR)) {
*((PWCHAR)SmbFileName) = L'.'; SmbFileName+= sizeof(WCHAR);
*((PWCHAR)SmbFileName) = L'*'; SmbFileName+= sizeof(WCHAR);
}
//*((PWCHAR)SmbFileName) = 0; SmbFileName+= sizeof(WCHAR); //trailing NULL;
//CODE.IMPROVEMENT we should potentially 8.3ize the string here
FindFirstPattern.Length = (USHORT)(SmbFileName - (PBYTE)FindFirstPattern.Buffer);
RxDbgTrace(0, Dbg, (" --> find1stpattern <%wZ>!\n",&FindFirstPattern));
FindFirst = TRUE;
ResumeKeyLength = 0;
} else {
RxDbgTrace(0, Dbg, ("-->FINDNEXT\n"));
FindFirstPattern.Buffer = NULL;
if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS)) {
Status = smbFobx->Enumeration.ErrorStatus;
RxDbgTrace(0, Dbg, ("-->ERROR EARLY OUT\n"));
goto FINALLY;
}
FindFirst = FALSE;
FindFirstPattern.Length = 0;
ResumeKeyLength = sizeof(SMB_RESUME_KEY);
MRxSmbDumpResumeKey("FindNext:",smbFobx->Enumeration.PathResumeKey);
}
//get the correct return count. there are three factors: countremaining from the OE,
// how many could fit the the user's buffer, and how many could fit in a negotiated buffer.
// we pick the smallest of the three.
ReturnCount = OrdinaryExchange->Info.CoreSearch.CountRemaining;
{ ULONG t = (*OrdinaryExchange->Info.pBufferLength) / smbFobx->Enumeration.FileNameOffset;
if (t<ReturnCount) { ReturnCount = t; }
}
{ PSMBCE_SERVER pServer = &((PSMB_EXCHANGE)OrdinaryExchange)->SmbCeContext.pServerEntry->Server;
ULONG AvailableBufferSize = pServer->MaximumBufferSize -
(sizeof(SMB_HEADER) +
FIELD_OFFSET(RESP_SEARCH,Buffer[0])
+sizeof(UCHAR)+sizeof(USHORT) //bufferformat,datalength fields
);
ULONG t = AvailableBufferSize / sizeof(SMB_DIRECTORY_INFORMATION);
if (t<ReturnCount) { ReturnCount = t; }
}
RxDbgTrace( 0, Dbg, ("-------->count=%08lx\n",ReturnCount));
if (ReturnCount==0) {
Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED);
RxDbgTrace(0, Dbg, ("-->Count==0 EARLY OUT\n"));
goto FINALLY;
}
StufferState = OrdinaryExchange->StufferState;
ASSERT( StufferState );
*pCountRemainingInSmbbuf = 0;
OrdinaryExchange->Info.CoreSearch.NextDirInfo = NULL;
COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,
SMB_COM_SEARCH, SMB_REQUEST_SIZE(SEARCH),
NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
0,0,0,0 STUFFERTRACE(Dbg,'FC'))
);
RxDbgTrace(0, Dbg,("core search command initial status = %lu\n",Status));
MRxSmbDumpStufferState (1100,"SMB w/ core search before stuffing",StufferState);
MRxSmbStuffSMB (StufferState,
"0wwB4ywc!",
// 0 UCHAR WordCount; // Count of parameter words = 2
ReturnCount, // w _USHORT( MaxCount ); // Number of dir. entries to return
SearchAttributes, // w _USHORT( SearchAttributes );
SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
// UCHAR Buffer[1]; // Buffer containing:
&FindFirstPattern, // 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
// //UCHAR FileName[]; // File name, may be null
0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
ResumeKeyLength, // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
// c //UCHAR SearchStatus[]; // Resume key
ResumeKeyLength,smbFobx->Enumeration.PathResumeKey
);
MRxSmbDumpStufferState (700,"SMB w/ core search after stuffing",StufferState);
//ASSERT(!"Now it's stuffed");
Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_CORESEARCH
);
if (!NT_SUCCESS(Status)) goto FINALLY;
smbFobx->Enumeration.Flags |= SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST|SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
//if (Status==RxStatus(SUCCESS) && FilesReturned==0) {
// RxDbgTrace( 0, Dbg, ("MRxSmbQueryDirectory: no files returned...switch status\n"));
// EndOfSearchReached = TRUE;
// Status = RxStatus(NO_MORE_FILES);
//}
if (Status==RX_MAP_STATUS(SUCCESS) && *pCountRemainingInSmbbuf==0) {
RxDbgTrace( 0, Dbg, ("MRxSmbLoadPathFileSearchBuffer: no files returned...switch status\n"));
EndOfSearchReached = TRUE;
Status = RX_MAP_STATUS(NO_MORE_FILES);
} else {
//CODE.IMPROVEMENT a possible improvement here is to know that the search is closed
// based on a "smaller-than-normal" return; we would key this off of the
// operatingsystem return string i guess. for NT systems, we don't do this
EndOfSearchReached = FALSE;
}
if (EndOfSearchReached) {
RxDbgTrace( 0, Dbg, ("MRxSmbLoadPathFileSearchBuffer: no longer in progress...EOS\n"));
smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
smbFobx->Enumeration.ErrorStatus = RX_MAP_STATUS(NO_MORE_FILES);
}
//we dont save a resume key here since each individual copy operation will have to do that
FINALLY:
if (FindFirstPattern.Buffer != NULL) {
RxFreePool(FindFirstPattern.Buffer);
}
if (!NT_SUCCESS(Status)&&(Status!=RX_MAP_STATUS(MORE_PROCESSING_REQUIRED))) {
RxDbgTrace( 0, Dbg, ("MRxSmbPathFileSearch: Failed .. returning %lx\n",Status));
smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_CORE_SEARCH_IN_PROGRESS;
smbFobx->Enumeration.ErrorStatus = Status; //keep returning this
}
RxDbgTrace(-1, Dbg, ("MRxSmbLoadPathFileSearchBuffer exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
#endif
return(Status);
}
#define ASSERT_SAME_FIELD(__field,__t1,__t2) { \
ASSERT(FIELD_OFFSET(__t1,__field)==FIELD_OFFSET(__t2,__field)); \
}
#define ASSERT_SAME_DIRINFO_FIELDS(__t1,__t2) {\
ASSERT_SAME_FIELD(LastWriteTime,__t1,__t2); \
ASSERT_SAME_FIELD(EndOfFile,__t1,__t2); \
ASSERT_SAME_FIELD(AllocationSize,__t1,__t2); \
ASSERT_SAME_FIELD(FileAttributes,__t1,__t2); \
}
#if DBG
VOID MRxSmbPathFileSeach_AssertFields(void){
//just move this out of the main execution path so that we don't have to look at it while
//we Uing the code
ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_FULL_DIR_INFORMATION);
ASSERT_SAME_DIRINFO_FIELDS(FILE_DIRECTORY_INFORMATION,FILE_BOTH_DIR_INFORMATION);
}
#else
#define MRxSmbPathFileSeach_AssertFields()
#endif
NTSTATUS
MRxSmbPathFileSearch(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This routine does a GetFileAttributes and remembers the reponse.
Arguments:
OrdinaryExchange - an exchange to be used for conducting this open.
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
//SMBbuf_STATUS SMBbufStatus;
#ifndef WIN9X
RxCaptureRequestPacket;
RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
// RxCaptureFileObject;
PMRX_SMB_FOBX smbFobx = (PMRX_SMB_FOBX)capFobx;
PBYTE pBuffer = OrdinaryExchange->Info.Buffer;
PULONG pLengthRemaining = OrdinaryExchange->Info.pBufferLength;
ULONG InformationClass = OrdinaryExchange->Info.InfoClass;
PFILE_DIRECTORY_INFORMATION pPreviousBuffer = NULL;
PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
ULONG SuccessCount = 0;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxSmbPathFileSearch entering.......OE=%08lx\n",OrdinaryExchange));
MRxSmbPathFileSeach_AssertFields();
OrdinaryExchange->Info.CoreSearch.CountRemaining =
RxContext->QueryD.ReturnSingleEntry?1:0x7ffffff;
if ( (smbFobx->Enumeration.PathResumeKey ==NULL )
&& ((smbFobx->Enumeration.PathResumeKey = RxAllocatePoolWithTag(PagedPool,sizeof(SMB_RESUME_KEY),'rbms'))==NULL) ){
RxDbgTrace(0, Dbg, ("...couldn't allocate resume key\n"));
Status = RX_MAP_STATUS(INSUFFICIENT_RESOURCES);
goto FINALLY;
}
RxDbgTrace( 0, Dbg, (".......smbFobx/resumekey=%08lx/%08lx\n",smbFobx,smbFobx->Enumeration.PathResumeKey));
Status = MRxSmbLoadPathFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
for (;;) {
BOOLEAN BufferOverflow = FALSE;
PSMB_DIRECTORY_INFORMATION NextDirInfo;
UNICODE_STRING FileNameU;
OEM_STRING FileNameA;
WCHAR FileNameU_buffer[14];
ULONG NameLength;
PBYTE NextFileName;
BOOLEAN Match,BufferOverFlow;
if (!NT_SUCCESS(Status)) {
if (Status = RX_MAP_STATUS(NO_MORE_FILES)) {
if (SuccessCount > 0) {
Status = RX_MAP_STATUS(SUCCESS);
}
} else if (Status = RX_MAP_STATUS(MORE_PROCESSING_REQUIRED)) {
if (SuccessCount > 0) {
Status = RX_MAP_STATUS(SUCCESS);
} else {
Status = RX_MAP_STATUS(BUFFER_OVERFLOW);
}
}
goto FINALLY;
}
ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemaining>0 );
ASSERT ( OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf>0 );
RxDbgTrace(0, Dbg, ("MRxSmbPathFileSearch looptopcheck counts=%08lx,%08lx\n",
OrdinaryExchange->Info.CoreSearch.CountRemaining,
OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf
));
//next issue: does the next dirinfo match the criteria?!?
NextDirInfo = OrdinaryExchange->Info.CoreSearch.NextDirInfo;
NextFileName = &NextDirInfo->FileName[0];
// According to colinw, some core servers do not remember to insert the null at the end of the name...
// but the namelength macro handles this correctly. some servers (Xenix, apparently) pad the
// names with spaces. again, the macro handles it....
//
NAME_LENGTH(NameLength, NextFileName,sizeof(NextDirInfo->FileName));
FileNameA.Length = (USHORT)NameLength;
FileNameA.MaximumLength = (USHORT)NameLength;
FileNameA.Buffer = NextFileName;
FileNameU.Length = sizeof(FileNameU_buffer);
FileNameU.MaximumLength = sizeof(FileNameU_buffer);
FileNameU.Buffer = &FileNameU_buffer[0];
Status = RtlOemStringToUnicodeString(&FileNameU, &FileNameA, TRUE);
RxDbgTrace(0, Dbg, ("MRxSmbPathFileSearch considering.......filename=%wZ, template=%wZ\n",
&FileNameU,&capFobx->UnicodeQueryTemplate));
ASSERT(Status==RX_MAP_STATUS(SUCCESS));
// we deal with a conversion failure by skipping this guy
Match = (Status==RX_MAP_STATUS(SUCCESS));
if (Match && smbFobx->Enumeration.WildCardsFound ) {
//DbgBreakPoint();
try
{
Match = FsRtlIsNameInExpression( &capFobx->UnicodeQueryTemplate,
&FileNameU, TRUE, NULL );
}
except(EXCEPTION_EXECUTE_HANDLER)
{
Match = FALSE;
}
}
//next issue: will the next dirinfo fit in the user's buffer?!?
if (Match) {
ULONG SpaceNeeded;
PBYTE pRememberBuffer = pBuffer;
pBuffer = (PBYTE)LongAlign(pBuffer); //assume that this will fit
SpaceNeeded = smbFobx->Enumeration.FileNameOffset+FileNameU.Length;
if (pBuffer+SpaceNeeded > pRememberBuffer+*pLengthRemaining) {
BufferOverflow = TRUE;
pBuffer = pRememberBuffer; //rollback
} else {
PFILE_DIRECTORY_INFORMATION pThisBuffer = (PFILE_DIRECTORY_INFORMATION)pBuffer;
SMB_TIME Time;
SMB_DATE Date;
BufferOverflow = FALSE;
if (pPreviousBuffer != NULL) {
pPreviousBuffer->NextEntryOffset = ((PBYTE)pThisBuffer)-((PBYTE)pPreviousBuffer);
}
pPreviousBuffer = pThisBuffer;
RtlZeroMemory(pBuffer,smbFobx->Enumeration.FileNameOffset);
RtlCopyMemory(pBuffer+smbFobx->Enumeration.FileNameOffset, FileNameU.Buffer,FileNameU.Length);
*((PULONG)(pBuffer+smbFobx->Enumeration.FileNameLengthOffset)) = FileNameU.Length;
//hallucinate the record based on specific return type
switch (InformationClass) {
case SMB_FIND_FILE_NAMES_INFO:
break;
case SMB_FIND_FILE_DIRECTORY_INFO:
case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
//just fill what we have...we do not go to a lot of trouble on allocinfo as rdr1 did.
// actually, rdr1 didn't do that here...only on getfielinfo.......
SmbMoveTime (&Time, &NextDirInfo->LastWriteTime);
SmbMoveDate (&Date, &NextDirInfo->LastWriteDate);
pThisBuffer->LastWriteTime = MRxSmbConvertSmbTimeToTime(Exchange, Time, Date);
pThisBuffer->EndOfFile.LowPart = SmbGetUlong(&NextDirInfo->FileSize);
pThisBuffer->FileAttributes = MRxSmbMapSmbAttributes (NextDirInfo->FileAttributes);
break;
default:
RxDbgTrace( 0, Dbg, ("MRxSmbPathFileSearch: Invalid FS information class\n"));
ASSERT(!"this can't happen");
Status = STATUS_INVALID_PARAMETER;
goto FINALLY;
}
pBuffer += SpaceNeeded;
*pLengthRemaining -= pBuffer-pRememberBuffer;
OrdinaryExchange->Info.CoreSearch.CountRemaining--;
SuccessCount++;
}
}
//
// if no match or no overflow, move up in the buffer. this means not only juggling the
// pointers but also saving the resume key
if (!Match || !BufferOverflow) {
MRxSmbDumpResumeKey("BufferKey:",&NextDirInfo->ResumeKey);
*(smbFobx->Enumeration.PathResumeKey) = NextDirInfo->ResumeKey;
MRxSmbDumpResumeKey("SaveKey: ",smbFobx->Enumeration.PathResumeKey);
OrdinaryExchange->Info.CoreSearch.NextDirInfo = NextDirInfo + 1;
OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf--;
}
if (OrdinaryExchange->Info.CoreSearch.CountRemaining==0) {
Status = RX_MAP_STATUS(SUCCESS);
goto FINALLY;
}
//should we jam these together by smashing the countrem to 0 on bufferoverflow??? CODE.IMPROVEMENT
if (BufferOverflow) {
Status = (SuccessCount==0)?RX_MAP_STATUS(BUFFER_OVERFLOW):RX_MAP_STATUS(SUCCESS);
goto FINALLY;
}
if (OrdinaryExchange->Info.CoreSearch.CountRemainingInSmbbuf==0) {
Status = MRxSmbLoadPathFileSearchBuffer( SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS );
}
}
FINALLY:
RxDbgTrace(-1, Dbg, ("MRxSmbPathFileSearch exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
//CODE.IMPROVEMENT if we're done with the resume key we could free it!
#endif
return(Status);
}
NTSTATUS
MrxSmbPathQueryFsVolumeInfo(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This routine does a GetFileAttributes and remembers the reponse.
Arguments:
OrdinaryExchange - an exchange to be used for conducting this open.
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
//SMBbuf_STATUS SMBbufStatus;
#ifndef WIN9X
RxCaptureRequestPacket;
RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
// RxCaptureFileObject;
PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
PSMBSTUFFER_BUFFER_STATE StufferState;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MrxSmbPathQueryFsVolumeInfo entering.......OE=%08lx\n",OrdinaryExchange));
StufferState = OrdinaryExchange->StufferState;
ASSERT( StufferState );
COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_SEARCH,
SMB_REQUEST_SIZE(SEARCH),
NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
0,0,0,0 STUFFERTRACE(Dbg,'FC'))
);
MRxSmbDumpStufferState (1100,"SMB w/ searchvolumelabel before stuffing",StufferState);
//CODE.IMPROVEMENT if this is truly core, we have to copy the name since its in UNICODE
// otherwise, we don't need to copy the name here, we can just Mdl like in writes
MRxSmbStuffSMB (StufferState,
"0wwB4yw!",
// 0 UCHAR WordCount; // Count of parameter words = 2
1, // w _USHORT( MaxCount ); // Number of dir. entries to return
// w _USHORT( SearchAttributes );
SMB_FILE_ATTRIBUTE_VOLUME,
SMB_WCT_CHECK(2) // B _USHORT( ByteCount ); // Count of data bytes; min = 5
// UCHAR Buffer[1]; // Buffer containing:
&MRxSmbAll8dot3Files,// 4 //UCHAR BufferFormat1; // 0x04 -- ASCII
// //UCHAR FileName[]; // File name, may be null
0x05, // y //UCHAR BufferFormat2; // 0x05 -- Variable block
0 // w //USHORT ResumeKeyLength; // Length of resume key, may be 0
// //UCHAR SearchStatus[]; // Resume key
);
MRxSmbDumpStufferState (700,"SMB w/ searchvolumelabel after stuffing",StufferState);
//ASSERT(!"Now it's stuffed");
OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] = 0; //no label
Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_COREQUERYLABEL
);
//Status = RxStatus(NOT_IMPLEMENTED);
ASSERT ( *pBufferLength>=sizeof(FILE_FS_VOLUME_INFORMATION));
RxDbgTrace(0, Dbg, ("MrxSmbPathQueryFsVolumeInfo OEstatus=%08lx\n",Status));
//DbgBreakPoint();
pBuffer->SupportsObjects = FALSE;
pBuffer->VolumeCreationTime.LowPart = 0;
pBuffer->VolumeCreationTime.HighPart = 0;
pBuffer->VolumeSerialNumber = 0;
pBuffer->VolumeLabelLength = 0;
if (NT_SUCCESS(Status) &&
(OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0] != 0) ) {
UNICODE_STRING VolumeLabelU;
OEM_STRING VolumeLabelA;
SMB_DIRECTORY_INFORMATION Buffer;
ULONG NameLength;
ULONG BytesToCopy;
PBYTE VolumeLabel = &OrdinaryExchange->Info.QFSVolInfo.CoreLabel[0];
//pBuffer->VolumeSerialNumber =
// (((SmbGetUshort(&Buffer.LastWriteTime.Ushort)) << 16) |
// (SmbGetUshort(&Buffer.LastWriteDate.Ushort)));
NAME_LENGTH(NameLength, VolumeLabel,
sizeof(OrdinaryExchange->Info.QFSVolInfo.CoreLabel));
VolumeLabelA.Length = (USHORT)NameLength;
VolumeLabelA.MaximumLength = (USHORT)NameLength;
VolumeLabelA.Buffer = VolumeLabel;
//some core servers put a '.' in the labelname.....if it's there then remove it
if ((NameLength>8)&& (VolumeLabel[8]=='.') ) {
ULONG i;
for (i=8;i<NameLength;i++) {
VolumeLabel[i] = VolumeLabel[i+1];
}
}
Status = RtlOemStringToUnicodeString(&VolumeLabelU, &VolumeLabelA, TRUE);
if (NT_SUCCESS(Status)) {
ULONG BytesToCopy = min((ULONG)VolumeLabelU.Length, (*pBufferLength-sizeof(FILE_FS_VOLUME_INFORMATION)));
RtlCopyMemory(&pBuffer->VolumeLabel[0],
VolumeLabelU.Buffer,
BytesToCopy);
*pBufferLength -= BytesToCopy;
pBuffer->VolumeLabelLength = VolumeLabelU.Length;
IF_DEBUG {
UNICODE_STRING FinalLabel;
FinalLabel.Buffer = &pBuffer->VolumeLabel[0];
FinalLabel.Length = (USHORT)BytesToCopy;
RxDbgTrace(0, Dbg, ("MrxSmbPathQueryFsVolumeInfo vollabel=%wZ\n",&FinalLabel));
}
RtlFreeUnicodeString(&VolumeLabelU);
}
} else if (Status == RX_MAP_STATUS(NO_SUCH_FILE)) {
//
// If we got no such file, this means that there's no volume label
// the remote volume. Return success with no data.
//
Status = RX_MAP_STATUS(SUCCESS);
}
if (NT_SUCCESS(Status)) {
*pBufferLength -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION,VolumeLabel);
}
FINALLY:
RxDbgTrace(-1, Dbg, ("MrxSmbPathQueryFsVolumeInfo exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
#endif
return(Status);
}
NTSTATUS
MrxSmbPathQueryDiskAttributes(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
)
/*++
Routine Description:
This routine does a GetDiskAttributes and remembers the reponse.
Arguments:
OrdinaryExchange - an exchange to be used for conducting this open.
Return Value:
RXSTATUS - The return status for the operation
Notes:
--*/
{
NTSTATUS Status;
//SMBbuf_STATUS SMBbufStatus;
RxCaptureRequestPacket;
RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
// RxCaptureFileObject;
PSMB_EXCHANGE Exchange = (PSMB_EXCHANGE) OrdinaryExchange;
PFILE_FS_VOLUME_INFORMATION pBuffer = OrdinaryExchange->Info.Buffer;
PULONG pBufferLength = OrdinaryExchange->Info.pBufferLength;
PSMBSTUFFER_BUFFER_STATE StufferState;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MrxSmbPathQueryDiskAttributes entering.......OE=%08lx\n",OrdinaryExchange));
StufferState = OrdinaryExchange->StufferState;
ASSERT( StufferState );
COVERED_CALL(MRxSmbStartSMBCommand (StufferState,SetInitialSMB_ForReuse,SMB_COM_QUERY_INFORMATION_DISK,
SMB_REQUEST_SIZE(QUERY_INFORMATION_DISK),
NO_EXTRA_DATA,SMB_BEST_ALIGNMENT(1,0),RESPONSE_HEADER_SIZE_NOT_SPECIFIED,
0,0,0,0 STUFFERTRACE(Dbg,'FC'))
);
RxDbgTrace(0, Dbg,("querydiskattribs command initial status = %lu\n",Status));
MRxSmbDumpStufferState (1100,"SMB w/ querydiskattribs before stuffing",StufferState);
MRxSmbStuffSMB (StufferState,
"0B!",
// 0 UCHAR WordCount; // Count of parameter words = 0
SMB_WCT_CHECK(0) 0 // B _USHORT( ByteCount ); // Count of data bytes = 0
// UCHAR Buffer[1]; // empty
);
MRxSmbDumpStufferState (700,"SMB w/ querydiskattribs after stuffing",StufferState);
//ASSERT(!"Now it's stuffed");
Status = SmbPseOrdinaryExchange(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS,
SMBPSE_OETYPE_COREQUERYDISKATTRIBUTES
);
FINALLY:
RxDbgTrace(-1, Dbg, ("MrxSmbPathQueryDiskAttributes exiting.......OE=%08lx, st=%08lx\n",OrdinaryExchange,Status));
return(Status);
}
NTSTATUS
MRxSmbGetFileAttributes(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
);
NTSTATUS
MRxSmbCoreDeleteForSupercedeOrClose(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE,
BOOLEAN DeleteDirectory
);
NTSTATUS
SmbPseExchangeStart_PathFunction(
PSMB_EXCHANGE pExchange)
/*++
Routine Description:
This is the start routine for VOLINFO.
Arguments:
pExchange - the exchange instance
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = RX_MAP_STATUS(NOT_IMPLEMENTED);
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange =
(PSMB_PSE_ORDINARY_EXCHANGE)pExchange;
PSMBSTUFFER_BUFFER_STATE StufferState = OrdinaryExchange->StufferState;
PRX_CONTEXT RxContext = StufferState->RxContext;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("SmbPseExchangeStart_PathFunction\n", 0 ));
ASSERT(pExchange->Type == ORDINARY_EXCHANGE);
MRxSmbSetInitialSMB(StufferState STUFFERTRACE(Dbg,'FC'));
//ASSERT (StufferState->CurrentCommand == SMB_COM_NO_ANDX_COMMAND);
switch (RxContext->MajorFunction) {
case DOSBASED_DELETE:
Status = MRxSmbCoreDeleteForSupercedeOrClose(SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, FALSE);
goto FINALLY;
case DOSBASED_DIRFUNCTION:
switch (RxContext->MinorFunction) {
case DOSBASED_CREATEDIR:
break;
case DOSBASED_DELETEDIR:
Status = MRxSmbCoreDeleteForSupercedeOrClose(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS, TRUE);
goto FINALLY;
case DOSBASED_CHECKDIR:
Status = MRxSmbCoreCheckDirFunction(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENTS);
goto FINALLY;
case DOSBASED_QUERY83DIR:
break;
default:
ASSERT(!"DIR MINOR FUNCTION SUPPOSED TO BE HERE!");
}
default:
ASSERT(!"Supposed to be here");
}
FINALLY:
RxDbgTrace(-1, Dbg, ("SmbPseExchangeStart_PathFunction exit w %08lx\n", Status ));
return Status;
}
extern
NTSTATUS
MRxSmbFinishSearch (
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
PRESP_SEARCH Response
);
extern
NTSTATUS
MRxSmbFinishQueryDiskInfo (
PSMB_PSE_ORDINARY_EXCHANGE OrdinaryExchange,
PRESP_QUERY_INFORMATION_DISK Response
);
SMB_EXCHANGE_DISPATCH_VECTOR
SmbPseDispatch_PathFunction = {
SmbPseExchangeStart_PathFunction,
SmbPseExchangeReceive_default,
SmbPseExchangeCopyDataHandler_default,
SmbPseExchangeSendCallbackHandler_default,
SmbPseExchangeFinalize_default,
NULL
};