⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileinfo.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:

        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 + -