📄 fileinfo.c
字号:
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
fileinfo.c
Abstract:
This module implements the mini redirector call down routines pertaining to retrieval/
update of file/directory/volume information.
--*/
#include "precomp.h"
#pragma hdrstop
#pragma warning(error:4101) // Unreferenced local variable
RXDT_DefineCategory(DIRCTRL);
#define Dbg (DEBUG_TRACE_DIRCTRL)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, __MRxSmbAllocateSideBuffer)
#pragma alloc_text(PAGE, MRxSmbDeallocateSideBuffer)
#pragma alloc_text(PAGE, MRxSmbTranslateLanManFindBuffer)
#pragma alloc_text(PAGE, MrxSmbUnalignedDirEntryCopyTail)
#pragma alloc_text(PAGE, MRxSmbQueryDirectory)
#pragma alloc_text(PAGE, MRxSmbQueryVolumeInformation)
#pragma alloc_text(PAGE, MRxSmbQueryVolumeInformationWithFullBuffer)
#pragma alloc_text(PAGE, MRxSmbSetVolumeInformation)
#pragma alloc_text(PAGE, MRxSmbQueryFileInformation)
#pragma alloc_text(PAGE, MRxSmbSetFileInformation)
#pragma alloc_text(PAGE, MRxSmbSetFileInformationAtCleanup)
#pragma alloc_text(PAGE, MRxSmbIsValidDirectory)
#pragma alloc_text(PAGE, MRxSmbQueryFileInformationFromPseudoOpen)
#endif
#define MRxSmbForceCoreInfo FALSE
//#define FORCECOREINFO
#if DBG
#ifdef FORCECOREINFO
#undef MRxSmbForceCoreInfo
BOOLEAN MRxSmbForceCoreInfo = TRUE;
#endif
#endif
BOOLEAN MRxSmbBypassDownLevelRename = FALSE;
//BOOLEAN MRxSmbBypassDownLevelRename = TRUE;
const ULONG UnalignedDirEntrySideBufferSize = 16384;
//
// All T2Find requests to the remote server request the 32 bit resume key
// so SMB_RFIND_BUFFER2 is used instead of SMB_FIND_BUFFER2.
//
typedef struct _SMB_FIND_BUFFER2_WITH_RESUME {
_ULONG( ResumeKey );
SMB_FIND_BUFFER2;
} SMB_FIND_BUFFER2_WITH_RESUME;
typedef SMB_FIND_BUFFER2_WITH_RESUME SMB_UNALIGNED *PSMB_FIND_BUFFER2_WITH_RESUME;
LIST_ENTRY MRxSmbSideBuffersList = {NULL,NULL};
ULONG MRxSmbSideBuffersSpinLock = 0;
ULONG MRxSmbSideBuffersCount = 0;
ULONG MRxSmbSideBuffersSerialNumber = 0;
BOOLEAN MRxSmbLoudSideBuffers = FALSE;
typedef struct _SIDE_BUFFER {
ULONG Signature;
LIST_ENTRY ListEntry;
PMRX_FCB Fcb;
PMRX_FOBX Fobx;
PMRX_SMB_FOBX smbFobx;
ULONG SerialNumber;
BYTE Buffer;
} SIDE_BUFFER, *PSIDE_BUFFER;
#if DBG
#define MRxSmbAllocateSideBuffer(a,b,c,d) __MRxSmbAllocateSideBuffer(a,b,c,d)
#else
#define MRxSmbAllocateSideBuffer(a,b,c,d) __MRxSmbAllocateSideBuffer(a,b,c)
#endif
NTSTATUS
MRxSmbCoreCheckPath(
SMBPSE_ORDINARY_EXCHANGE_ARGUMENT_SIGNATURE
);
VOID
__MRxSmbAllocateSideBuffer(
IN OUT PRX_CONTEXT RxContext,
IN OUT PMRX_SMB_FOBX smbFobx,
IN USHORT Setup
#if DBG
,IN PUNICODE_STRING smbtemplate
#endif
)
{
RxCaptureFcb;RxCaptureFobx;
PSIDE_BUFFER SideBuffer;
ULONG SideBufferSize;
POOL_TYPE PoolType;
PAGED_CODE();
__assume_bound( UnalignedDirEntrySideBufferSize );
SideBufferSize = UnalignedDirEntrySideBufferSize+sizeof(SIDE_BUFFER);
ASSERT( smbFobx->Enumeration.UnalignedDirEntrySideBuffer == NULL);
#ifdef _WIN64
//
// NT64: When PagedPool is used here, we get memory corruption on
// some findfirst/findnext operations. Find out why.
//
PoolType = NonPagedPool;
#else
PoolType = PagedPool;
#endif
SideBuffer = (PSIDE_BUFFER)RxAllocatePoolWithTag(
PoolType,
SideBufferSize,
MRXSMB_DIRCTL_POOLTAG);
if (SideBuffer==NULL) {
return;
}
ASSERT( smbFobx->Enumeration.UnalignedDirEntrySideBuffer == NULL);
SideBuffer->Signature = 'JLBS';
SideBuffer->smbFobx = smbFobx;
SideBuffer->Fobx = capFobx;
SideBuffer->Fcb = capFcb;
smbFobx->Enumeration.UnalignedDirEntrySideBuffer = &SideBuffer->Buffer;
RxLog(("Allocsidebuf %lx fo/f=%lx,%lx\n",
smbFobx->Enumeration.UnalignedDirEntrySideBuffer,
capFobx,capFcb));
smbFobx->Enumeration.SerialNumber = SideBuffer->SerialNumber = InterlockedIncrement(&MRxSmbSideBuffersSerialNumber);
InterlockedIncrement(&MRxSmbSideBuffersCount);
if (MRxSmbSideBuffersList.Flink==NULL) {
InitializeListHead(&MRxSmbSideBuffersList);
}
ExAcquireFastMutex(&MRxSmbSerializationMutex);
InsertTailList(&MRxSmbSideBuffersList,&SideBuffer->ListEntry);
ExReleaseFastMutex(&MRxSmbSerializationMutex);
if (!MRxSmbLoudSideBuffers) return;
KdPrint(("Allocating side buffer %08lx %08lx %08lx %08lx %08lxon <%wZ> %s %wZ\n",
&SideBuffer->Buffer,
MRxSmbSideBuffersCount,
smbFobx,capFobx,capFobx->pSrvOpen,
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),
(Setup == TRANS2_FIND_FIRST2)?"First":"Next",
smbtemplate
));
}
VOID
MRxSmbDeallocateSideBuffer(
IN OUT PRX_CONTEXT RxContext,
IN OUT PMRX_SMB_FOBX smbFobx,
__in PSTR where
)
{
PSIDE_BUFFER SideBuffer;
RxCaptureFcb;RxCaptureFobx;
PAGED_CODE();
if( smbFobx->Enumeration.UnalignedDirEntrySideBuffer == NULL) return;
SideBuffer = CONTAINING_RECORD(smbFobx->Enumeration.UnalignedDirEntrySideBuffer,SIDE_BUFFER,Buffer);
if (MRxSmbLoudSideBuffers){
DbgPrint("D--------- side buffer %08lx %08lx %08lx %08lx %08lxon <%wZ> %s\n",
&SideBuffer->Buffer,
MRxSmbSideBuffersCount,
smbFobx,capFobx,capFobx->pSrvOpen,
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),
where
);
}
ASSERT(SideBuffer->Signature == 'JLBS');
ASSERT(SideBuffer->Fobx == capFobx);
ASSERT(SideBuffer->Fcb == capFcb);
ASSERT(SideBuffer->smbFobx == smbFobx);
ASSERT(smbFobx->Enumeration.SerialNumber == SideBuffer->SerialNumber);
ExAcquireFastMutex(&MRxSmbSerializationMutex);
InterlockedDecrement(&MRxSmbSideBuffersCount);
RemoveEntryList(&SideBuffer->ListEntry);
ExReleaseFastMutex(&MRxSmbSerializationMutex);
RxLog(("Deallocsidebuf %lx fo/f=%lx,%lx\n",
smbFobx->Enumeration.UnalignedDirEntrySideBuffer,
capFobx,capFcb));
RxFreePool(SideBuffer);
smbFobx->Enumeration.UnalignedDirEntrySideBuffer = NULL;
}
VOID
MRxSmbTranslateLanManFindBuffer(
PRX_CONTEXT RxContext,
PULONG PreviousReturnedEntry,
PBYTE ThisEntryInBuffer
)
{
RxCaptureFcb; RxCaptureFobx;
PSMBCEDB_SERVER_ENTRY pServerEntry;
PSMBCE_SERVER Server;
ULONG FileInformationClass = RxContext->Info.FileInformationClass;
PFILE_FULL_DIR_INFORMATION NtBuffer = (PFILE_FULL_DIR_INFORMATION)PreviousReturnedEntry;
PSMB_FIND_BUFFER2_WITH_RESUME SmbBuffer = (PSMB_FIND_BUFFER2_WITH_RESUME)ThisEntryInBuffer;
SMB_TIME Time;
SMB_DATE Date;
PAGED_CODE();
if (FileInformationClass==FileNamesInformation) { return; }
pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
Server = &pServerEntry->Server;
SmbMoveTime (&Time, &SmbBuffer->CreationTime);
SmbMoveDate (&Date, &SmbBuffer->CreationDate);
NtBuffer->CreationTime = MRxSmbConvertSmbTimeToTime(Server, Time, Date);
SmbMoveTime (&Time, &SmbBuffer->LastAccessTime);
SmbMoveDate (&Date, &SmbBuffer->LastAccessDate);
NtBuffer->LastAccessTime = MRxSmbConvertSmbTimeToTime(Server, Time, Date);
SmbMoveTime (&Time, &SmbBuffer->LastWriteTime);
SmbMoveDate (&Date, &SmbBuffer->LastWriteDate);
NtBuffer->LastWriteTime = MRxSmbConvertSmbTimeToTime(Server, Time, Date);
NtBuffer->ChangeTime.QuadPart = 0;
NtBuffer->EndOfFile.QuadPart = SmbGetUlong(&SmbBuffer->DataSize);
NtBuffer->AllocationSize.QuadPart = SmbGetUlong(&SmbBuffer->AllocationSize);
NtBuffer->FileAttributes = MRxSmbMapSmbAttributes(SmbBuffer->Attributes);
if ((FileInformationClass==FileFullDirectoryInformation)
|| (FileInformationClass==FileBothDirectoryInformation)) {
NtBuffer->EaSize = SmbGetUlong(&SmbBuffer->EaSize);
}
}
NTSTATUS
MrxSmbUnalignedDirEntryCopyTail(
IN OUT PRX_CONTEXT RxContext,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN OUT PVOID pBuffer,
IN OUT PULONG pLengthRemaining,
IN OUT PMRX_SMB_FOBX smbFobx
)
/*++
Routine Description:
This routine copies the data from the side buffer into the users buffer and adjusts the
lengths remaining appropriately. this is called either if the server doesn't do unicode (w95) OR
if the server does not promise to quadalign entries OR if the user's buffer is not quadaligned.
this routine can be entered after a T2 finishes or to copy the last entries from a previous T2. in the second case, the
pUnalignedDirEntrySideBuffer ptr will be null and it will go to acquire the correct pointer from the smbFobx.
this routine has the responsibility to free the sidebufferptr when it is exhausted.
Arguments:
RxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
RxCaptureFcb;
ULONG i,NameSizeInUnicode;
LONG LocalLengthRemaining; //signed arithmetic makes it easier
PULONG PreviousReturnedEntry = NULL;
ULONG FileNameLengthOffset = smbFobx->Enumeration.FileNameLengthOffset;
ULONG FileNameOffset = smbFobx->Enumeration.FileNameOffset;
PBYTE UnalignedDirEntrySideBuffer = smbFobx->Enumeration.UnalignedDirEntrySideBuffer;
BOOLEAN IsUnicode = smbFobx->Enumeration.IsUnicode;
BOOLEAN IsNonNtT2Find = smbFobx->Enumeration.IsNonNtT2Find;
PMRX_SMB_DIRECTORY_RESUME_INFO ResumeInfo = smbFobx->Enumeration.ResumeInfo;
ULONG FilesReturned = smbFobx->Enumeration.FilesReturned;
ULONG EntryOffset = smbFobx->Enumeration.EntryOffset;
ULONG ReturnedEntryOffset = 0;// = smbFobx->Enumeration.ReturnedEntryOffset;
BOOLEAN EndOfSearchReached = smbFobx->Enumeration.EndOfSearchReached;
ULONG TotalDataBytesReturned = smbFobx->Enumeration.TotalDataBytesReturned;
BOOLEAN FilterFailure = FALSE;
PAGED_CODE();
LocalLengthRemaining = (LONG)(*pLengthRemaining);
//
// keep looping until we've filled in all we can or there're no more entries
for (i=ReturnedEntryOffset=0;;) {
ULONG FileNameLength,ThisEntrySize; PCHAR FileNameBuffer;
UNICODE_STRING ReturnedFileName;
OEM_STRING FileName;
NTSTATUS StringStatus;
BOOLEAN TwoExtraBytes = TRUE;
ULONG resumekey,NextEntryOffsetinBuffer;
PULONG PreviousPreviousReturnedEntry = NULL;
PBYTE ThisEntryInBuffer = UnalignedDirEntrySideBuffer+EntryOffset;
//
// don't EVER let yourself get past the data returned...servers return funny stuff.......
if (EntryOffset>=TotalDataBytesReturned){
FilterFailure = TRUE;
FilesReturned = i; //we're done with this buffer........
break;
}
//
// find the name, the length, and the resume key based on whether it is a NT-T2find or a nonNT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -