typedef struct _BL_ETFS_FILE
{
+ ULONG DiskOffset;
ULONG DirOffset;
ULONG DirEntOffset;
- ULONGLONG Size;
- ULONGLONG Offset;
- PWCHAR FsName;
- ULONG Flags;
+
+ BL_FILE_INFORMATION;
+
ULONG DeviceId;
} BL_ETFS_FILE, *PBL_ETFS_FILE;
_Out_ PBL_FILE_ENTRY *FileEntry
);
+NTSTATUS
+EtfsGetInformation (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _Out_ PBL_FILE_INFORMATION FileInfo
+ );
+
+NTSTATUS
+EtfsSetInformation (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _In_ PBL_FILE_INFORMATION FileInfo
+ );
+
+NTSTATUS
+EtfsRead (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _In_ PVOID Buffer,
+ _In_ ULONG Size,
+ _Out_opt_ PULONG BytesReturned
+ );
+
BL_FILE_CALLBACKS EtfsFunctionTable =
{
EtfsOpen,
+ NULL,
+ EtfsRead,
+ NULL,
+ NULL,
+ EtfsGetInformation,
+ EtfsSetInformation
};
/* FUNCTIONS *****************************************************************/
EtfsFile = DirectoryEntry->FsSpecificData;
DeviceId = EtfsFile->DeviceId;
- FileOffset = EtfsFile->Offset;
+ FileOffset = EtfsFile->DiskOffset;
EtfsDevice = EtfsDeviceTable[DeviceId];
DirectoryOffset = *DirentOffset;
DirentOffset = EtfsFile->DirEntOffset;
if ((KeepOffset) ||
- (ALIGN_DOWN_BY((DirentOffset + EtfsFile->Offset), CD_SECTOR_SIZE) ==
+ (ALIGN_DOWN_BY((DirentOffset + EtfsFile->DiskOffset), CD_SECTOR_SIZE) ==
EtfsDevice->Offset))
{
Status = EtfspGetDirent(DirectoryEntry, &Dirent, &DirentOffset);
return Status;
}
+NTSTATUS
+EtfsRead (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _In_ PVOID Buffer,
+ _In_ ULONG Size,
+ _Out_opt_ PULONG BytesReturned
+ )
+{
+ ULONG BytesRead;
+ PBL_ETFS_FILE EtfsFile;
+ NTSTATUS Status;
+
+ /* Assume failure for now */
+ BytesRead = 0;
+
+ /* Make sure that the read is within the file's boundaries */
+ EtfsFile = FileEntry->FsSpecificData;
+ if ((Size + EtfsFile->Offset) > EtfsFile->Size)
+ {
+ /* Bail out otherwise */
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ /* Read the offset that matches this file's offset, on the disk */
+ Status = BlDeviceReadAtOffset(FileEntry->DeviceId,
+ Size,
+ EtfsFile->Offset + EtfsFile->DiskOffset,
+ Buffer,
+ &BytesRead);
+ if (NT_SUCCESS(Status))
+ {
+ /* Update the file offset and return the size as having been read */
+ EtfsFile->Offset += Size;
+ BytesRead = Size;
+ }
+ }
+
+ /* Check if caller wanted to know how many bytes were read */
+ if (BytesReturned)
+ {
+ /* Return the value */
+ *BytesReturned = BytesRead;
+ }
+
+ /* All done */
+ return Status;
+}
+
+NTSTATUS
+EtfsSetInformation (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _In_ PBL_FILE_INFORMATION FileInfo
+ )
+{
+ PBL_ETFS_FILE EtfsFile;
+ BL_FILE_INFORMATION LocalFileInfo;
+
+ /* Get the underlying ETFS file data structure */
+ EtfsFile = (PBL_ETFS_FILE)FileEntry->FsSpecificData;
+
+ /* Make a copy of the incoming attributes, but ignore the new offset */
+ LocalFileInfo = *FileInfo;
+ LocalFileInfo.Offset = EtfsFile->Offset;
+
+ /* Check if these match exactly the current file */
+ if (!RtlEqualMemory(&LocalFileInfo, &EtfsFile->Size, sizeof(*FileInfo)))
+ {
+ /* Nope -- which means caller is trying to change an immutable */
+ EfiPrintf(L"Incorrect information change\r\n");
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Is the offset past the end of the file? */
+ if (FileInfo->Offset >= EtfsFile->Size)
+ {
+ /* Don't allow EOF */
+ EfiPrintf(L"Offset too large: %lx vs %lx \r\n", FileInfo->Offset, EtfsFile->Size);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Update the offset */
+ EtfsFile->Offset = FileInfo->Offset;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+EtfsGetInformation (
+ _In_ PBL_FILE_ENTRY FileEntry,
+ _Out_ PBL_FILE_INFORMATION FileInfo
+ )
+{
+ PBL_ETFS_FILE EtfsFile;
+
+ /* Get the underlying ETFS file data structure */
+ EtfsFile = (PBL_ETFS_FILE)FileEntry->FsSpecificData;
+
+ /* Copy the cached information structure within it */
+ RtlCopyMemory(FileInfo, &EtfsFile->Size, sizeof(*FileInfo));
+ return STATUS_SUCCESS;
+}
+
NTSTATUS
EtfsOpen (
_In_ PBL_FILE_ENTRY Directory,
RtlCopyMemory(&NewFile->Callbacks,
&EtfsFunctionTable,
sizeof(NewFile->Callbacks));
- EtfsFile->Offset = FileOffset;
+ EtfsFile->DiskOffset = FileOffset;
EtfsFile->DirOffset = DirOffset;
EtfsFile->Size = FileSize;
EtfsFile->DeviceId = DeviceId;
RootEntry->FsSpecificData = EtfsFile;
EtfsFile->DeviceId = DeviceId;
EtfsFile->Flags |= 1;
- EtfsFile->Offset = EtfsDevice->RootDirOffset;
+ EtfsFile->DiskOffset = EtfsDevice->RootDirOffset;
EtfsFile->DirOffset = 0;
EtfsFile->Size = EtfsDevice->RootDirSize;
EtfsFile->FsName = L"cdfs";
if (++FileEntry->ReferenceCount == 1)
{
/* Reset unknowns */
- FileEntry->Unknown1 = 0;
+ FileEntry->TotalBytesRead = 0;
FileEntry->Unknown2 = 0;
}
}
/* Validate file ID */
- if (FileEntries > FileId)
+ if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
}
/* Validate file ID */
- if (FileEntries > FileId)
+ if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
Size = 0;
/* Make sure we didn't overshoot */
- if (FileInformation->CurrentOffset > FileInformation->FileSize)
+ if (FileInformation->Offset > FileInformation->Size)
{
/* Bail out */
Status = STATUS_INVALID_PARAMETER;
/* Compute the appropriate 32-bit size of this read, based on file size */
Size = ULONG_MAX;
- if ((FileInformation->FileSize - FileInformation->CurrentOffset) <= ULONG_MAX)
+ if ((FileInformation->Size - FileInformation->Offset) <= ULONG_MAX)
{
- Size = (ULONG)(FileInformation->FileSize) - (ULONG)(FileInformation->CurrentOffset);
+ Size = (ULONG)(FileInformation->Size) - (ULONG)(FileInformation->Offset);
}
/* Check if the caller has an input buffer */
}
/* Bail out of the file ID is invalid */
- if (FileEntries > FileId)
+ if (FileId > FileEntries)
{
return STATUS_INVALID_PARAMETER;
}
}
/* Increment the number of bytes read */
- FileEntry->Unknown1 += RequiredSize;
+ FileEntry->TotalBytesRead += RequiredSize;
/* Check if the unknown flag on the device was changed during this routine */
if (ChangedUnknown)
}
/* Save the current offset, and overwrite it with the one we want */
- FileOffset = FileInfo.CurrentOffset;
- FileInfo.CurrentOffset = ByteOffset;
+ FileOffset = FileInfo.Offset;
+ FileInfo.Offset = ByteOffset;
/* Check the validity of the read and the actual size to read */
RequiredSize = Size;
if (!NT_SUCCESS(Status))
{
/* Bail out if the read is invalid */
+ EfiPrintf(L"File info check failure: %lx\n", Status);
return Status;
}
/* Check if the offset we're requesting is not the current offset */
- if (FileInfo.CurrentOffset != FileOffset)
+ if (FileInfo.Offset != FileOffset)
{
/* Set the new offset to use */
Status = BlFileSetInformation(FileId, &FileInfo);
if (!NT_SUCCESS(Status))
{
/* The read failed -- had we modified the offset? */
- if (FileInfo.CurrentOffset != FileOffset)
+ if (FileInfo.Offset != FileOffset)
{
/* Restore the offset back to its original value */
- FileInfo.CurrentOffset = FileOffset;
+ FileInfo.Offset = FileOffset;
BlFileSetInformation(FileId, &FileInfo);
}
}