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); }
/* * 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; }