📄 fileinfo.c
字号:
if (!IsNonNtT2Find) {
//
// NT, we use the offsets that we stored earlier.........
FileNameLength = SmbGetUlong(ThisEntryInBuffer+FileNameLengthOffset);
FileNameBuffer = ThisEntryInBuffer+FileNameOffset;
resumekey = SmbGetUlong(ThisEntryInBuffer
+FIELD_OFFSET(FILE_FULL_DIR_INFORMATION,FileIndex));
NextEntryOffsetinBuffer = SmbGetUlong(ThisEntryInBuffer);
} else {
//
// for lanman, we always ask for stuff using the SMB_FIND_BUFFER2 to which
// we have prepended a resume key. so, the name is always at a fixed offset.
// Also, for nonNT we have read all the files and must filter out correctly; we
// save where we are in the user's buffer so that we can roll back.
FileNameLength = *(ThisEntryInBuffer
+FIELD_OFFSET(SMB_FIND_BUFFER2_WITH_RESUME,FileNameLength));
FileNameBuffer = ThisEntryInBuffer
+FIELD_OFFSET(SMB_FIND_BUFFER2_WITH_RESUME,FileName[0]);
resumekey = SmbGetUlong(ThisEntryInBuffer+
+FIELD_OFFSET(SMB_FIND_BUFFER2_WITH_RESUME,ResumeKey));
NextEntryOffsetinBuffer = FIELD_OFFSET(SMB_FIND_BUFFER2_WITH_RESUME,FileName[0])
+ FileNameLength + 1; //the +1 is for the null..we could have said Filename{1]
PreviousPreviousReturnedEntry = PreviousReturnedEntry; //save this for rollback on filterfail
}
// some servers lie about how many entries were returned and/or send partial entries
// dont let them trick us..........
if (EntryOffset+NextEntryOffsetinBuffer>TotalDataBytesReturned){
FilterFailure = TRUE;
FilesReturned = i; //we're done with this buffer........
break;
}
FileName.Buffer = FileNameBuffer;
FileName.Length = (USHORT)FileNameLength;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: EO,REO=%08lx,%08lx\n",
EntryOffset,ReturnedEntryOffset));
//check to see if this entry will fit
if (IsUnicode) {
NameSizeInUnicode = FileNameLength;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: length=%08lx/%08lx, name = %wZ\n",
FileNameLength,NameSizeInUnicode,&FileName));
} else {
NameSizeInUnicode = RtlxOemStringToUnicodeSize(&FileName)-sizeof(WCHAR);
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: length=%08lx/%08lx, name = %.*s\n",
FileNameLength,NameSizeInUnicode,FileNameLength,FileNameBuffer));
}
//
// now that we know the size of the name and its location, we need to copy it
// to the user's buffer
ThisEntrySize = FileNameOffset+NameSizeInUnicode;
if (((LONG)ThisEntrySize)>LocalLengthRemaining) {
break;
}
if (((LONG)ThisEntrySize)>LocalLengthRemaining-(LONG)sizeof(WCHAR)) {
TwoExtraBytes = FALSE;
}
ThisEntrySize = LongAlign(ThisEntrySize);
PreviousReturnedEntry = (PULONG)(((PBYTE)pBuffer)+ReturnedEntryOffset);
//
// next we compute where the next entry after this one will start. the definition is
// that it must be 8-byte aligned. we know already that it's 4byte aligned.
if (!IsPtrQuadAligned((PCHAR)(PreviousReturnedEntry)+ThisEntrySize) ){
ThisEntrySize += sizeof(ULONG);
}
if (i!=0) {
ASSERT(IsPtrQuadAligned(PreviousReturnedEntry));
}
//
// if this is an NT find, we can copy in the data now. for lanman, we
// copy in the data later........
if (!IsNonNtT2Find) {
//copy everything in the entry up to but not including the name info
RtlCopyMemory(PreviousReturnedEntry,UnalignedDirEntrySideBuffer+EntryOffset,FileNameOffset);
} else {
// clear out all fields i cannot support.
RtlZeroMemory(PreviousReturnedEntry,FileNameOffset);
}
// store the length of this entry and the size of the name...if this is the last
// entry returned, then the offset field will be cleared later
*PreviousReturnedEntry = ThisEntrySize;
*((PULONG)(((PBYTE)PreviousReturnedEntry)+FileNameLengthOffset)) = NameSizeInUnicode;
//copy in the name .........this is made difficult by the oem-->unicode routine that
// requires space for a NULL!
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: REO/buf/pentry=%08lx/%08lx/%08lx\n",
pBuffer,ReturnedEntryOffset,PreviousReturnedEntry));
ReturnedFileName.Buffer = (PWCH)(((PBYTE)PreviousReturnedEntry)+FileNameOffset);
if (!IsUnicode) {
if (TwoExtraBytes) {
ReturnedFileName.MaximumLength = sizeof(WCHAR)+(USHORT)NameSizeInUnicode;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: filenamebuf,length=%08lx/%08lx\n",
ReturnedFileName.Buffer,ReturnedFileName.MaximumLength));
StringStatus = RtlOemStringToUnicodeString(&ReturnedFileName,&FileName,FALSE); //false means don;t allocate
} else {
OEM_STRING LastChar;
UNICODE_STRING LastCharInUnicode;
WCHAR UnicodeCharBuffer[2];
ReturnedFileName.MaximumLength = (USHORT)NameSizeInUnicode;
FileName.Length -= 1;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: filenamebuf,length=%08lx/%08lx\n",
ReturnedFileName.Buffer,ReturnedFileName.MaximumLength));
StringStatus = RtlOemStringToUnicodeString(&ReturnedFileName,&FileName,FALSE); //false means don;t allocate
ASSERT(StringStatus==STATUS_SUCCESS);
LastChar.Buffer = FileName.Buffer+FileName.Length;
LastChar.Length = 1;
LastCharInUnicode.Buffer = (PWCH)UnicodeCharBuffer;
//LastCharInUnicode.Buffer = (PWCH)(((PBYTE)ReturnedFileName.Buffer)+ReturnedFileName.Length);
LastCharInUnicode.MaximumLength = sizeof(UnicodeCharBuffer);
StringStatus = RtlOemStringToUnicodeString(&LastCharInUnicode,&LastChar,FALSE); //false means don;t allocate
*((PWCH)(((PBYTE)ReturnedFileName.Buffer)+ReturnedFileName.Length)) = UnicodeCharBuffer[0];
}
ASSERT(StringStatus==STATUS_SUCCESS);
// Win95 returns the shortname in ascii....spread it out
if ((FileInformationClass == FileBothDirectoryInformation) && !IsNonNtT2Find) {
PFILE_BOTH_DIR_INFORMATION BothInfo = (PFILE_BOTH_DIR_INFORMATION)PreviousReturnedEntry;
OEM_STRING oemName;
UNICODE_STRING UnicodeName;
WCHAR wcharBuffer[MAX_PATH];
oemName.Buffer = (PBYTE)(&BothInfo->ShortName[0]);
oemName.Length =
oemName.MaximumLength = BothInfo->ShortNameLength;
UnicodeName.Buffer = wcharBuffer;
UnicodeName.Length = 0;
UnicodeName.MaximumLength = MAX_PATH * sizeof(WCHAR);
StringStatus = RtlOemStringToUnicodeString(&UnicodeName, &oemName, FALSE);
ASSERT(StringStatus==STATUS_SUCCESS);
BothInfo->ShortNameLength = (CHAR)UnicodeName.Length;
RtlCopyMemory(BothInfo->ShortName, UnicodeName.Buffer, UnicodeName.Length);
IF_DEBUG {
UNICODE_STRING LastName;
LastName.Buffer = (PWCHAR)wcharBuffer;
LastName.Length = (USHORT)UnicodeName.Length;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: unicodeshortnamename = %wZ\n", &LastName));
}
}
} else {
//here, it's already unicode.....just copy the bytes
RtlCopyMemory(ReturnedFileName.Buffer,FileName.Buffer,FileName.Length);
}
IF_DEBUG {
UNICODE_STRING LastName;
LastName.Buffer = ReturnedFileName.Buffer;
LastName.Length = (USHORT)NameSizeInUnicode;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: unicodename = %wZ\n", &LastName));
}
//now...setup to resume based on this entry
if (ResumeInfo != NULL) {
PREQ_FIND_NEXT2 pFindNext2Request = &ResumeInfo->FindNext2_Request;
//ULONG resumekey = ((PFILE_FULL_DIR_INFORMATION)PreviousReturnedEntry)->FileIndex;
pFindNext2Request->ResumeKey = resumekey;
RxDbgTrace(0,Dbg,("MRxSmbQueryDirectoryWin95: resumekey = %08lx\n", resumekey));
RtlCopyMemory(&pFindNext2Request->Buffer[0],FileNameBuffer,FileNameLength);
//buffer is a UCHAR...not WCHAR
if (IsUnicode) {
// In the case of UNICODE strings an additional NULL is required ( WCHAR NULL )
pFindNext2Request->Buffer[FileNameLength] = 0; //nullterminated
pFindNext2Request->Buffer[FileNameLength + 1] = 0; //nullterminated
smbFobx->Enumeration.ResumeInfo->ParametersLength
= (USHORT)(&pFindNext2Request->Buffer[FileNameLength+2] - (PBYTE)pFindNext2Request);
} else {
pFindNext2Request->Buffer[FileNameLength] = 0; //nullterminated
smbFobx->Enumeration.ResumeInfo->ParametersLength
= (USHORT)(&pFindNext2Request->Buffer[FileNameLength+1] - (PBYTE)pFindNext2Request);
}
}
//ASSERT(!IsNonNtT2Find);
//at this point, we have copied the name and the resume key. BUT, for nonnt we have to
//filter the names so we still may have to roll back
if (!IsNonNtT2Find) {
//no need for filtering on NT
FilterFailure = FALSE;
} else {
// here we have to filter out based on the template
RxCaptureFobx; //do this here so it's not on the NT path
FilterFailure = FALSE;
if (smbFobx->Enumeration.WildCardsFound ) {
FilterFailure = !FsRtlIsNameInExpression(
&capFobx->UnicodeQueryTemplate,
&ReturnedFileName,
TRUE,
NULL );
} else {
FilterFailure = !RtlEqualUnicodeString(
&capFobx->UnicodeQueryTemplate,
&ReturnedFileName,
TRUE ); //case-insensitive
}
if (!FilterFailure) {
// since we didn't copy the data before, we have to copy it now...
MRxSmbTranslateLanManFindBuffer(RxContext,PreviousReturnedEntry,ThisEntryInBuffer);
} else {
PreviousReturnedEntry = PreviousPreviousReturnedEntry; //rollback on filterfail
}
}
if (!FilterFailure) {
// filtering succeeded..... adjust returned sizes and counts
LocalLengthRemaining -= ThisEntrySize;
i++;
ReturnedEntryOffset += ThisEntrySize;
} else {
FilesReturned--; //we exit the loop if i passes filesreturned
}
//
// complicated test to keep going.......
//EntryOffset += SmbGetUlong(UnalignedDirEntrySideBuffer+EntryOffset);
EntryOffset += NextEntryOffsetinBuffer;
if ((i>=FilesReturned)
||(LocalLengthRemaining<0)
|| (RxContext->QueryDirectory.ReturnSingleEntry&&(i>0)) ) {
break;
}
}
//
// if we are not returning even one entry, either we didn't have space for even one entry
// OR we're filtering and no guys passed the filter. return an appropriate error in each case
if (i==0) {
Status = FilterFailure?STATUS_MORE_PROCESSING_REQUIRED:STATUS_BUFFER_OVERFLOW;
} else {
*PreviousReturnedEntry = 0; // this clears the "next" link for the last returned entry
}
//
// send back the right size
if (LocalLengthRemaining <= 0) {
*pLengthRemaining = 0;
} else {
*pLengthRemaining = (ULONG)LocalLengthRemaining;
}
//
// if we're finished with the sidebuffer, deallocate it.
// otherwise setup to resume........
if (i>=FilesReturned) {
RxLog(("sidebufdealloc %lx %lx\n",RxContext,smbFobx));
MRxSmbDeallocateSideBuffer(RxContext,smbFobx,"Tail");
if (EndOfSearchReached) {
//smbFobx->Enumeration.Flags &= ~SMBFOBX_ENUMFLAG_SEARCH_HANDLE_OPEN;
//we will close the search handle when the user's handle closes
smbFobx->Enumeration.ErrorStatus = STATUS_NO_MORE_FILES;
}
} else {
//set up to resume here
ASSERT(smbFobx->Enumeration.UnalignedDirEntrySideBuffer == UnalignedDirEntrySideBuffer);
smbFobx->Enumeration.EntryOffset = EntryOffset;
smbFobx->Enumeration.FilesReturned = FilesReturned - i;
}
return(Status);
}
ULONG MRxSmbWin95Retries = 0;
NTSTATUS
MRxSmbQueryDirectory(
IN OUT PRX_CONTEXT RxContext
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -