📄 fileinfo.c
字号:
)
/*++
Routine Description:
This routine does a directory query. Only the NT-->NT path is implemented.
Arguments:
RxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
RxCaptureFcb;
RxCaptureFobx;
PMRX_SMB_FCB smbFcb = MRxSmbGetFcbExtension(capFcb);
PMRX_SMB_FOBX smbFobx = MRxSmbGetFileObjectExtension(capFobx);
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_SMB_SRV_OPEN smbSrvOpen = MRxSmbGetSrvOpenExtension(SrvOpen);
PSMBCE_V_NET_ROOT_CONTEXT pVNetRootContext = SmbCeGetAssociatedVNetRootContext(SrvOpen->pVNetRoot);
PSMBCE_SESSION pSession = &pVNetRootContext->pSessionEntry->Session;
FILE_INFORMATION_CLASS FileInformationClass;
PVOID Buffer;
PULONG pLengthRemaining;
USHORT SmbFileInfoLevel;
ULONG FilesReturned;
ULONG RetryCount = 0;
USHORT Setup;
PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
//REQ_FIND_NEXT2 FindNext2Request;
PREQ_FIND_FIRST2 pFindFirst2Request = NULL;
PBYTE SendParamsBuffer,ReceiveParamsBuffer;
PBYTE UnalignedDirEntrySideBuffer;
BOOLEAN DirEntriesAreUaligned = FALSE;
BOOLEAN IsUnicode = TRUE;
BOOLEAN IsNonNtT2Find;
USHORT SearchFlags = SMB_FIND_CLOSE_AT_EOS|SMB_FIND_RETURN_RESUME_KEYS;
USHORT NumEntries;
ULONG SendParamsBufferLength,ReceiveParamsBufferLength;
RESP_FIND_FIRST2 FindFirst2Response;
UNICODE_STRING FileName = {0,0,NULL};
struct {
RESP_FIND_NEXT2 FindNext2Response;
ULONG Pad; //nonnt needs this
} XX;
#if DBG
UNICODE_STRING smbtemplate = {0,0,NULL};
#endif
PAGED_CODE();
TURN_BACK_ASYNCHRONOUS_OPERATIONS();
FileInformationClass = RxContext->Info.FileInformationClass;
Buffer = RxContext->Info.Buffer;
pLengthRemaining = &RxContext->Info.LengthRemaining;
RxDbgTrace(+1, Dbg, ("MRxSmbQueryDirectory: directory=<%wZ>\n",
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)
));
#define __GET_NAME_PARAMS_FOR_TYPE(___type___) { \
smbFobx->Enumeration.FileNameOffset = (USHORT)FIELD_OFFSET(___type___,FileName[0]); \
smbFobx->Enumeration.FileNameLengthOffset = (USHORT)FIELD_OFFSET(___type___,FileNameLength); \
}
switch (FileInformationClass) {
case FileDirectoryInformation:
SmbFileInfoLevel = SMB_FIND_FILE_DIRECTORY_INFO;
__GET_NAME_PARAMS_FOR_TYPE(FILE_DIRECTORY_INFORMATION);
break;
case FileFullDirectoryInformation:
SmbFileInfoLevel = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
__GET_NAME_PARAMS_FOR_TYPE(FILE_FULL_DIR_INFORMATION);
break;
case FileBothDirectoryInformation:
SmbFileInfoLevel = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
__GET_NAME_PARAMS_FOR_TYPE(FILE_BOTH_DIR_INFORMATION);
break;
case FileNamesInformation:
SmbFileInfoLevel = SMB_FIND_FILE_NAMES_INFO;
__GET_NAME_PARAMS_FOR_TYPE(FILE_NAMES_INFORMATION);
break;
default:
RxDbgTrace( 0, Dbg, ("MRxSmbQueryDirectory: Invalid FS information class\n"));
Status = STATUS_INVALID_PARAMETER;
goto FINALLY;
}
#if DBG
if (MRxSmbLoudSideBuffers) {
SetFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_LOUD_FINALIZE);
}
#endif
if (FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_NO_WILDCARD) ||
FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_READ_FROM_CACHE)) {
// if the FindFirst has been satisfied basied on local file information cache,
// we should fail the FindNext since the file has been found with the exact name.
Status = STATUS_NO_MORE_FILES;
smbFobx->Enumeration.EndOfSearchReached = TRUE;
smbFobx->Enumeration.ErrorStatus = STATUS_NO_MORE_FILES;
ClearFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_READ_FROM_CACHE);
goto FINALLY;
}
if (capFobx->UnicodeQueryTemplate.Length != 0 &&
!FsRtlDoesNameContainWildCards(&capFobx->UnicodeQueryTemplate) &&
!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST)) {
// if it is the FindFirst, we try to find the file on local file information cache.
PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
UNICODE_STRING TargetName = {0,0,NULL};
TargetName.Length = DirectoryName->Length + Template->Length + sizeof(WCHAR);
TargetName.MaximumLength = TargetName.Length;
TargetName.Buffer = (PWCHAR)RxAllocatePoolWithTag(PagedPool,
TargetName.Length,
MRXSMB_DIRCTL_POOLTAG);
if (TargetName.Buffer == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto FINALLY;
}
RtlCopyMemory(TargetName.Buffer,
DirectoryName->Buffer,
DirectoryName->Length);
TargetName.Buffer[DirectoryName->Length/sizeof(WCHAR)] = L'\\';
RtlCopyMemory(&TargetName.Buffer[DirectoryName->Length/sizeof(WCHAR)+1],
Template->Buffer,
Template->Length);
RxFreePool(TargetName.Buffer);
SearchFlags |= SMB_FIND_CLOSE_AFTER_REQUEST;
SetFlag(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_NO_WILDCARD);
}
if (FlagOn(smbSrvOpen->Flags,SMB_SRVOPEN_FLAG_DEFERRED_OPEN)) {
BOOLEAN AcquireExclusive = RxIsFcbAcquiredExclusive(capFcb);
BOOLEAN AcquireShare = RxIsFcbAcquiredShared(capFcb) > 0;
if (AcquireExclusive || AcquireShare) {
RxReleaseFcbResourceInMRx( capFcb );
}
// connection could have been timed out, try to reconnect.
Status = SmbCeReconnect(SrvOpen->pVNetRoot);
if (AcquireExclusive) {
RxAcquireExclusiveFcbResourceInMRx( capFcb );
} else if (AcquireShare) {
RxAcquireExclusiveFcbResourceInMRx( capFcb );
}
if (Status != STATUS_SUCCESS) {
// connection cannot be recovered.
goto FINALLY;
}
}
if (MRxSmbForceCoreInfo ||
!(pServerEntry->Server.DialectFlags&(DF_NT_SMBS|DF_W95|DF_LANMAN20))) {
return MRxSmbCoreInformation(RxContext,
(ULONG)SmbFileInfoLevel,
Buffer,
pLengthRemaining,
SMBPSE_OE_FROM_QUERYDIRECTORY
);
}
if (smbFobx->Enumeration.UnalignedDirEntrySideBuffer != NULL){
RxDbgTrace( 0, Dbg, ("MRxSmbQueryDirectory: win95 internal resume\n"));
Status = MrxSmbUnalignedDirEntryCopyTail(
/*IN OUT PRX_CONTEXT */ RxContext,
/*IN FILE_INFORMATION_CLASS */ FileInformationClass,
/*IN OUT PVOID */ Buffer,
/*IN OUT PULONG */ pLengthRemaining,
/*IN OUT PMRX_SMB_FOBX */ smbFobx
);
if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
return(Status);
} else {
Status = STATUS_SUCCESS;
}
}
NumEntries = RxContext->QueryDirectory.ReturnSingleEntry?1:2000;
IsUnicode = BooleanFlagOn(pServerEntry->Server.DialectFlags,DF_UNICODE);
IsNonNtT2Find = !(pServerEntry->Server.Dialect==NTLANMAN_DIALECT);
if (TRUE || FlagOn(pServerEntry->Server.DialectFlags,DF_W95)){
DirEntriesAreUaligned = TRUE;
//SearchFlags = SMB_FIND_RETURN_RESUME_KEYS;
//SearchFlags = SMB_FIND_CLOSE_AT_EOS;
NumEntries = (USHORT)(1+ UnalignedDirEntrySideBufferSize
/(IsNonNtT2Find?FIELD_OFFSET(SMB_FIND_BUFFER2_WITH_RESUME, FileName)
:FIELD_OFFSET(FILE_NAMES_INFORMATION, FileName)));
}
if (FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)
&& FlagOn(capFobx->Flags,FOBX_FLAG_BACKUP_INTENT)){
SearchFlags |= SMB_FIND_WITH_BACKUP_INTENT;
}
if (IsNonNtT2Find) {
SearchFlags &= ~(SMB_FIND_CLOSE_AT_EOS | SMB_FIND_CLOSE_AFTER_REQUEST);
}
RETRY_____:
if (!FlagOn(smbFobx->Enumeration.Flags,SMBFOBX_ENUMFLAG_SEARCH_NOT_THE_FIRST)) {
//this is the first time thru
PUNICODE_STRING DirectoryName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
ULONG DirectoryNameLength,TemplateLength,AllocationLength;
PBYTE SmbFileName;
RxDbgTrace(0, Dbg, ("-->FINFDIRST\n"));
smbFobx->Enumeration.ErrorStatus = STATUS_SUCCESS;
if (smbFobx->Enumeration.WildCardsFound = FsRtlDoesNameContainWildCards(Template)){
//we need an upcased template for
RtlUpcaseUnicodeString( Template, Template, FALSE );
}
Setup = TRANS2_FIND_FIRST2;
DirectoryNameLength = DirectoryName->Length;
TemplateLength = Template->Length;
AllocationLength = sizeof(REQ_FIND_FIRST2) //NOTE: this buffer is bigger than w95 needs
+2*sizeof(WCHAR)
+DirectoryNameLength
+TemplateLength;
pFindFirst2Request = (PREQ_FIND_FIRST2)RxAllocatePoolWithTag(
PagedPool,
AllocationLength,
MRXSMB_DIRCTL_POOLTAG);
if (pFindFirst2Request==NULL) {
RxDbgTrace(0, Dbg, (" --> Couldn't get the pFindFirst2Request!\n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto FINALLY;
}
SmbFileName = &pFindFirst2Request->Buffer[0];
if (IsUnicode) {
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;
*((PWCHAR)SmbFileName) = 0; SmbFileName+= sizeof(WCHAR); //trailing NULL;
IF_DEBUG {
DbgDoit(smbtemplate.Buffer = (PWCHAR)&pFindFirst2Request->Buffer[0];);
DbgDoit(smbtemplate.Length = (USHORT)(SmbFileName - (PBYTE)smbtemplate.Buffer););
RxDbgTrace(0, Dbg, (" --> smbtemplate <%wZ>!\n",&smbtemplate));
}
} else {
ULONG BufSize = AllocationLength;
PUNICODE_STRING FinalTemplate = Template;
UNICODE_STRING AllFiles;
SmbPutUnicodeStringAsOemString(&SmbFileName,DirectoryName,&AllocationLength);
// append a backslash if it doesn't exist in the unicode version
// NB !!! Don't compare with OEM string
// it busts DBCS characters with 0x5c at the end
if (!DirectoryName->Length || (DirectoryName->Buffer[(DirectoryName->Length/sizeof(USHORT))-1] != (USHORT)'\\'))
{
*(SmbFileName-1) = '\\';
}
else
{
// there is already a backslash, backup one character
SmbFileName -= 1; AllocationLength += 1;
}
if (IsNonNtT2Find) {
//we'll get them all and filter on out side
RtlInitUnicodeString(&AllFiles, L"*.*");
FinalTemplate = &AllFiles;
}
SmbPutUnicodeStringAsOemString(&SmbFileName,FinalTemplate,&AllocationLength);
//already padded *SmbFileName = 0; SmbFileName+= sizeof(CHAR); //trailing NULL;
IF_DEBUG {
DbgDoit(smbtemplate.Buffer = (PWCHAR)&pFindFirst2Request->Buffer[0];);
DbgDoit(smbtemplate.Length = (USHORT)(SmbFileName - (PBYTE)smbtemplate.Buffer););
RxDbgTrace(0, Dbg, (" --> smbtemplate <%s>!\n",&pFindFirst2Request->Buffer[0]));
}
}
// SearchAttributes is hardcoded to the magic number 0x16
pFindFirst2Request->SearchAttributes =
(SMB_FILE_ATTRIBUTE_DIRECTORY
| SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN);
pFindFirst2Request->SearchCount = NumEntries;
pFindFirst2Request->Flags = SearchFlags;
pFindFirst2Request->InformationLevel = IsNonNtT2Find?SMB_INFO_QUERY_EA_SIZE:SmbFileInfoLevel;
pFindFirst2Request->SearchStorageType = 0;
SendParamsBuffer = (PBYTE)pFindFirst2Request;
SendParamsBufferLength = (ULONG)(SmbFileName - SendParamsBuffer);
ReceiveParamsBuffer = (PBYTE)&FindFirst2Response;
ReceiveParamsBufferLength = sizeof(FindFirst2Response);
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -