示例#1
0
NTSTATUS
CdfsDirFindFile(PDEVICE_EXTENSION DeviceExt,
                PFCB DirectoryFcb,
                PUNICODE_STRING FileToFind,
                PFCB *FoundFCB)
{
    UNICODE_STRING TempName;
    WCHAR Name[256];
    PVOID Block;
    ULONG DirSize;
    PDIR_RECORD Record;
    ULONG Offset;
    ULONG BlockOffset;
    NTSTATUS Status;

    LARGE_INTEGER StreamOffset, OffsetOfEntry;
    PVOID Context;

    WCHAR ShortNameBuffer[13];
    UNICODE_STRING ShortName;
    UNICODE_STRING LongName;
    UNICODE_STRING FileToFindUpcase;

    ASSERT(DeviceExt);
    ASSERT(DirectoryFcb);
    ASSERT(FileToFind);

    DPRINT("CdfsDirFindFile(VCB:%p, dirFCB:%p, File:%wZ)\n",
        DeviceExt,
        DirectoryFcb,
        FileToFind);
    DPRINT("Dir Path:%S\n", DirectoryFcb->PathName);

    /* default to '.' if no filename specified */
    if (FileToFind->Length == 0)
    {
        RtlInitUnicodeString(&TempName, L".");
        FileToFind = &TempName;
    }

    DirSize = DirectoryFcb->Entry.DataLengthL;
    StreamOffset.QuadPart = (LONGLONG)DirectoryFcb->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;

    if (!CcMapData(DeviceExt->StreamFileObject,
        &StreamOffset,
        BLOCKSIZE,
        TRUE,
        &Context,
        &Block))
    {
        DPRINT("CcMapData() failed\n");
        return STATUS_UNSUCCESSFUL;
    }

    Offset = 0;
    BlockOffset = 0;
    Record = (PDIR_RECORD)Block;

    /* Upper case the expression for FsRtlIsNameInExpression */
    Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    while(TRUE)
    {
        if (Record->RecordLength == 0)
        {
            DPRINT("RecordLength == 0  Stopped!\n");
            break;
        }

        DPRINT("RecordLength %u  ExtAttrRecordLength %u  NameLength %u\n",
            Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);

        CdfsGetDirEntryName(DeviceExt, Record, Name);
        DPRINT ("Name '%S'\n", Name);
        DPRINT ("Sector %lu\n", DirectoryFcb->Entry.ExtentLocationL);
        DPRINT ("Offset %lu\n", Offset);

        RtlInitUnicodeString(&LongName, Name);
        ShortName.Length = 0;
        ShortName.MaximumLength = 26;
        ShortName.Buffer = ShortNameBuffer;
        memset(ShortNameBuffer, 0, 26);

        OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
        CdfsShortNameCacheGet(DirectoryFcb, &OffsetOfEntry, &LongName, &ShortName);

        DPRINT("ShortName '%wZ'\n", &ShortName);

        if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
            FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
        {
            DPRINT("Match found, %S\n", Name);
            Status = CdfsMakeFCBFromDirEntry(DeviceExt,
                DirectoryFcb,
                Name,
                ShortNameBuffer,
                Record,
                DirectoryFcb->Entry.ExtentLocationL,
                Offset,
                FoundFCB);

            RtlFreeUnicodeString(&FileToFindUpcase);
            CcUnpinData(Context);

            return(Status);
        }

        Offset += Record->RecordLength;
        BlockOffset += Record->RecordLength;
        Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
        if (BlockOffset >= BLOCKSIZE || Record->RecordLength == 0)
        {
            DPRINT("Map next sector\n");
            CcUnpinData(Context);
            StreamOffset.QuadPart += BLOCKSIZE;
            Offset = ROUND_UP(Offset, BLOCKSIZE);
            BlockOffset = 0;

            if (!CcMapData(DeviceExt->StreamFileObject,
                &StreamOffset,
                BLOCKSIZE, TRUE,
                &Context, &Block))
            {
                DPRINT("CcMapData() failed\n");
                RtlFreeUnicodeString(&FileToFindUpcase);
                return(STATUS_UNSUCCESSFUL);
            }
            Record = (PDIR_RECORD)((ULONG_PTR)Block + BlockOffset);
        }

        if (Offset >= DirSize)
            break;
    }

    RtlFreeUnicodeString(&FileToFindUpcase);
    CcUnpinData(Context);

    return(STATUS_OBJECT_NAME_NOT_FOUND);
}
示例#2
0
文件: dirctl.c 项目: Strongc/reactos
/*
* FUNCTION: Find a file
*/
static NTSTATUS
CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
             PFCB Fcb,
             PFCB Parent,
             PUNICODE_STRING FileToFind,
             PULONG pDirIndex,
             PULONG pOffset)
{
    WCHAR name[256];
    WCHAR ShortNameBuffer[13];
    UNICODE_STRING TempString;
    UNICODE_STRING ShortName;
    UNICODE_STRING LongName;
    UNICODE_STRING FileToFindUpcase;
    PVOID Block;
    NTSTATUS Status;
    ULONG len;
    ULONG DirIndex;
    ULONG Offset = 0;
    BOOLEAN IsRoot;
    PVOID Context = NULL;
    ULONG DirSize;
    PDIR_RECORD Record;
    LARGE_INTEGER StreamOffset, OffsetOfEntry;

    DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
        Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
    DPRINT("FindFile: old Pathname %p, old Objectname %p)\n",
        Fcb->PathName, Fcb->ObjectName);

    IsRoot = FALSE;
    DirIndex = 0;

    if (FileToFind == NULL || FileToFind->Length == 0)
    {
        RtlInitUnicodeString(&TempString, L".");
        FileToFind = &TempString;
    }

    if (Parent)
    {
        if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart)
        {
            IsRoot = TRUE;
        }
    }
    else
    {
        IsRoot = TRUE;
    }

    if (IsRoot == TRUE)
    {
        StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE;
        DirSize = DeviceExt->CdInfo.RootSize;


        if (FileToFind->Buffer[0] == 0 ||
            (FileToFind->Buffer[0] == '\\' && FileToFind->Buffer[1] == 0) ||
            (FileToFind->Buffer[0] == '.' && FileToFind->Buffer[1] == 0))
        {
            /* it's root : complete essentials fields then return ok */
            RtlZeroMemory(Fcb, sizeof(FCB));
            RtlInitEmptyUnicodeString(&Fcb->PathName, Fcb->PathNameBuffer, sizeof(Fcb->PathNameBuffer));

            Fcb->PathNameBuffer[0] = '\\';
            Fcb->PathName.Length = sizeof(WCHAR);
            Fcb->ObjectName = &Fcb->PathNameBuffer[1];
            Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart;
            Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize;
            Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY;

            if (pDirIndex)
                *pDirIndex = 0;
            if (pOffset)
                *pOffset = 0;
            DPRINT("CdfsFindFile: new Pathname %wZ, new Objectname %S)\n",&Fcb->PathName, Fcb->ObjectName);
            return STATUS_SUCCESS;
        }
    }
    else
    {
        StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
        DirSize = Parent->Entry.DataLengthL;
    }

    DPRINT("StreamOffset %I64d  DirSize %u\n", StreamOffset.QuadPart, DirSize);

    if (pDirIndex && (*pDirIndex))
        DirIndex = *pDirIndex;

    if (pOffset && (*pOffset))
    {
        Offset = *pOffset;
        StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE);
    }

    if (!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
        BLOCKSIZE, TRUE, &Context, &Block))
    {
        DPRINT("CcMapData() failed\n");
        return STATUS_UNSUCCESSFUL;
    }

    Record = (PDIR_RECORD) ((ULONG_PTR)Block + Offset % BLOCKSIZE);
    if (Offset)
    {
        Offset += Record->RecordLength;
        Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
    }

    /* Upper case the expression for FsRtlIsNameInExpression */
    Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    while(TRUE)
    {
        DPRINT("RecordLength %u  ExtAttrRecordLength %u  NameLength %u\n",
            Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);

        Status = CdfsGetEntryName
            (DeviceExt, &Context, &Block, &StreamOffset,
            DirSize, (PVOID*)&Record, name, &DirIndex, &Offset);

        if (Status == STATUS_NO_MORE_ENTRIES)
        {
            break;
        }
        else if (Status == STATUS_UNSUCCESSFUL || Status == STATUS_DISK_CORRUPT_ERROR)
        {
            /* Note: the directory cache has already been unpinned */
            RtlFreeUnicodeString(&FileToFindUpcase);
            return Status;
        }

        DPRINT("Name '%S'\n", name);

        RtlInitUnicodeString(&LongName, name);

        ShortName.Length = 0;
        ShortName.MaximumLength = 26;
        ShortName.Buffer = ShortNameBuffer;

        OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
        CdfsShortNameCacheGet(Parent, &OffsetOfEntry, &LongName, &ShortName);

        DPRINT("ShortName '%wZ'\n", &ShortName);

        if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
            FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
        {
            if (Parent->PathName.Buffer[0])
            {
                RtlCopyUnicodeString(&Fcb->PathName, &Parent->PathName);
                len = Parent->PathName.Length / sizeof(WCHAR);
                Fcb->ObjectName=&Fcb->PathName.Buffer[len];
                if (len != 1 || Fcb->PathName.Buffer[0] != '\\')
                {
                    Fcb->ObjectName[0] = '\\';
                    Fcb->ObjectName = &Fcb->ObjectName[1];
                }
            }
            else
            {
                Fcb->ObjectName=Fcb->PathName.Buffer;
                Fcb->ObjectName[0]='\\';
                Fcb->ObjectName=&Fcb->ObjectName[1];
            }

            DPRINT("PathName '%wZ'  ObjectName '%S'\n", &Fcb->PathName, Fcb->ObjectName);

            memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD));
            wcsncpy(Fcb->ObjectName, name, min(wcslen(name) + 1,
                MAX_PATH - (Fcb->PathName.Length / sizeof(WCHAR)) + wcslen(Fcb->ObjectName)));

            /* Copy short name */
            Fcb->ShortNameU.Length = ShortName.Length;
            Fcb->ShortNameU.MaximumLength = ShortName.Length;
            Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
            memcpy(Fcb->ShortNameBuffer, ShortName.Buffer, ShortName.Length);

            if (pDirIndex)
                *pDirIndex = DirIndex;
            if (pOffset)
                *pOffset = Offset;

            DPRINT("FindFile: new Pathname %wZ, new Objectname %S, DirIndex %u\n",
                &Fcb->PathName, Fcb->ObjectName, DirIndex);

            RtlFreeUnicodeString(&FileToFindUpcase);
            CcUnpinData(Context);

            return STATUS_SUCCESS;
        }

        Offset += Record->RecordLength;
        Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
        DirIndex++;
    }

    RtlFreeUnicodeString(&FileToFindUpcase);
    CcUnpinData(Context);

    if (pDirIndex)
        *pDirIndex = DirIndex;

    if (pOffset)
        *pOffset = Offset;

    return STATUS_UNSUCCESSFUL;
}