PNTFS_FCB
NtfsCreateFCB(PCWSTR FileName,
+ PCWSTR Stream,
PNTFS_VCB Vcb)
{
PNTFS_FCB Fcb;
}
}
+ if (Stream)
+ {
+ wcscpy(Fcb->Stream, Stream);
+ }
+ else
+ {
+ Fcb->Stream[0] = UNICODE_NULL;
+ }
+
ExInitializeResourceLite(&Fcb->MainResource);
Fcb->RFCB.Resource = &(Fcb->MainResource);
}
+BOOLEAN
+NtfsFCBIsCompressed(PNTFS_FCB Fcb)
+{
+ return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_COMPRESSED) == NTFS_FILE_TYPE_COMPRESSED);
+}
+
BOOLEAN
NtfsFCBIsRoot(PNTFS_FCB Fcb)
{
return NULL;
}
- FileName = GetFileNameFromRecord(MftRecord, NTFS_FILE_NAME_WIN32);
+ FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32);
if (!FileName)
{
ExFreePoolWithTag(MftRecord, TAG_NTFS);
return NULL;
}
- Fcb = NtfsCreateFCB(L"\\", Vcb);
+ Fcb = NtfsCreateFCB(L"\\", NULL, Vcb);
if (!Fcb)
{
ExFreePoolWithTag(MftRecord, TAG_NTFS);
}
-#if 0
-static VOID
-NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
- PDIR_RECORD Record,
- PWSTR Name)
-/*
- * FUNCTION: Retrieves the file name, be it in short or long file name format
- */
-{
- if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
- {
- wcscpy(Name, L".");
- }
- else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
- {
- wcscpy(Name, L"..");
- }
- else
- {
- if (DeviceExt->CdInfo.JolietLevel == 0)
- {
- ULONG i;
-
- for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
- Name[i] = (WCHAR)Record->FileId[i];
- Name[i] = 0;
- }
- else
- {
- NtfsSwapString(Name, Record->FileId, Record->FileIdLength);
- }
- }
-
- DPRINT("Name '%S'\n", Name);
-}
-#endif
-
-
NTSTATUS
NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
- PNTFS_FCB DirectoryFCB,
- PUNICODE_STRING Name,
- PFILE_RECORD_HEADER Record,
+ PNTFS_FCB DirectoryFCB,
+ PUNICODE_STRING Name,
+ PCWSTR Stream,
+ PFILE_RECORD_HEADER Record,
ULONGLONG MFTIndex,
- PNTFS_FCB * fileFCB)
+ PNTFS_FCB * fileFCB)
{
WCHAR pathName[MAX_PATH];
PFILENAME_ATTRIBUTE FileName;
PSTANDARD_INFORMATION StdInfo;
PNTFS_FCB rcFCB;
+ ULONGLONG Size, AllocatedSize;
- DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p)\n", Vcb, DirectoryFCB, Name, Record, fileFCB);
+ DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB);
- FileName = GetBestFileNameFromRecord(Record);
+ FileName = GetBestFileNameFromRecord(Vcb, Record);
if (!FileName)
{
return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
pathName[FileName->NameLength] = UNICODE_NULL;
}
- rcFCB = NtfsCreateFCB(pathName, Vcb);
+ Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize);
+
+ rcFCB = NtfsCreateFCB(pathName, Stream, Vcb);
if (!rcFCB)
{
return STATUS_INSUFFICIENT_RESOURCES;
memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
rcFCB->Entry.NameType = FileName->NameType;
- rcFCB->RFCB.FileSize.QuadPart = FileName->DataSize;
- rcFCB->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
- rcFCB->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
+ rcFCB->RFCB.FileSize.QuadPart = Size;
+ rcFCB->RFCB.ValidDataLength.QuadPart = Size;
+ rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize;
- StdInfo = GetStandardInformationFromRecord(Record);
+ StdInfo = GetStandardInformationFromRecord(Vcb, Record);
if (StdInfo != NULL)
{
rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute;
UNICODE_STRING File;
PFILE_RECORD_HEADER FileRecord;
ULONGLONG MFTIndex;
+ PWSTR Colon, OldColon;
+ PNTFS_ATTR_CONTEXT DataContext;
+ USHORT Length = 0;
DPRINT1("NtfsDirFindFile(%p, %p, %S, %p)\n", Vcb, DirectoryFcb, FileToFind, FoundFCB);
RtlInitUnicodeString(&File, FileToFind);
CurrentDir = DirectoryFcb->MFTIndex;
+ Colon = wcsrchr(FileToFind, L':');
+ if (Colon != NULL)
+ {
+ Length = File.Length;
+ File.Length = (Colon - FileToFind) * sizeof(WCHAR);
+
+ if (_wcsicmp(Colon + 1, L"$DATA") == 0)
+ {
+ OldColon = Colon;
+ Colon[0] = UNICODE_NULL;
+ Colon = wcsrchr(FileToFind, L':');
+ if (Colon != NULL)
+ {
+ Length = File.Length;
+ File.Length = (Colon - FileToFind) * sizeof(WCHAR);
+ }
+ else
+ {
+ Colon = OldColon;
+ Colon[0] = L':';
+ }
+ }
+
+ /* Skip colon */
+ ++Colon;
+ DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon);
+ }
+
Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &MFTIndex, CurrentDir);
if (!NT_SUCCESS(Status))
{
return Status;
}
- Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, FileRecord, MFTIndex, FoundFCB);
+ if (Length != 0)
+ {
+ File.Length = Length;
+ }
+
+ if ((FileRecord->Flags & FRH_DIRECTORY) && Colon != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ else if (Colon != 0)
+ {
+ Status = FindAttribute(Vcb, FileRecord, AttributeData, Colon, wcslen(Colon), &DataContext);
+ if (!NT_SUCCESS(Status))
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ ReleaseAttributeContext(DataContext);
+ }
+
+ Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, Colon, FileRecord, MFTIndex, FoundFCB);
ExFreePoolWithTag(FileRecord, TAG_NTFS);
return Status;