You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
981 lines
24 KiB
981 lines
24 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
blio.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code that implements the switch function for
|
|
I/O operations between then operating system loader, the target file
|
|
system, and the target device.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 10-May-1991
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "bootlib.h"
|
|
#include "stdio.h"
|
|
|
|
|
|
//
|
|
// Define file table.
|
|
//
|
|
BL_FILE_TABLE BlFileTable[BL_FILE_TABLE_SIZE];
|
|
|
|
#if DBG
|
|
ULONG BlFilesOpened = 0;
|
|
#endif
|
|
|
|
#ifdef CACHE_DEVINFO
|
|
|
|
//
|
|
// Device close notification routines, are registered by the file system
|
|
// which are interested in device close events. This is primarily used for
|
|
// invalidating the internal cache, which the file system maintains
|
|
// using DeviceId as one of the keys
|
|
//
|
|
PARC_DEVICE_CLOSE_NOTIFICATION DeviceCloseNotify[MAX_DEVICE_CLOSE_NOTIFICATION_SIZE] = {0};
|
|
|
|
//
|
|
// Device to filesystem cache table
|
|
//
|
|
DEVICE_TO_FILESYS DeviceFSCache[BL_FILE_TABLE_SIZE];
|
|
|
|
ARC_STATUS
|
|
ArcCacheClose(
|
|
IN ULONG DeviceId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine invalidates the file system information
|
|
cached for the given device ID.
|
|
|
|
Arguments:
|
|
|
|
DeviceId : Device to close
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if the close is successful. Otherwise,
|
|
return an unsuccessful status.
|
|
|
|
--*/
|
|
{
|
|
ULONG Index;
|
|
|
|
//
|
|
// Notify all the registered file system about the device close
|
|
//
|
|
for (Index = 0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
|
|
if (DeviceCloseNotify[Index]) {
|
|
(DeviceCloseNotify[Index])(DeviceId);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update device to file system cache
|
|
//
|
|
|
|
for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index++) {
|
|
if (DeviceFSCache[Index].DeviceId == DeviceId){
|
|
DeviceFSCache[Index].DeviceId = UNINITIALIZED_DEVICE_ID;
|
|
}
|
|
}
|
|
|
|
return ((FIRMWARE_VECTOR_BLOCK->CloseRoutine)(DeviceId));
|
|
}
|
|
|
|
|
|
ARC_STATUS
|
|
ArcRegisterForDeviceClose(
|
|
PARC_DEVICE_CLOSE_NOTIFICATION FlushRoutine
|
|
)
|
|
{
|
|
ARC_STATUS Status = EINVAL;
|
|
|
|
if (FlushRoutine) {
|
|
ULONG Index;
|
|
|
|
Status = ENOENT;
|
|
|
|
for (Index=0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
|
|
if (!DeviceCloseNotify[Index]) {
|
|
DeviceCloseNotify[Index] = FlushRoutine;
|
|
Status = ESUCCESS;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
ARC_STATUS
|
|
ArcDeRegisterForDeviceClose(
|
|
PARC_DEVICE_CLOSE_NOTIFICATION FlushRoutine
|
|
)
|
|
{
|
|
ARC_STATUS Status = EINVAL;
|
|
|
|
if (FlushRoutine) {
|
|
ULONG Index;
|
|
|
|
Status = ENOENT;
|
|
|
|
for (Index=0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
|
|
if (DeviceCloseNotify[Index] == FlushRoutine) {
|
|
DeviceCloseNotify[Index] = NULL;
|
|
Status = ESUCCESS;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
#endif // CACHE_DEVINFO
|
|
|
|
|
|
ARC_STATUS
|
|
BlIoInitialize (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the file table used by the OS loader and
|
|
initializes the boot loader filesystems.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if the initialization is successful. Otherwise,
|
|
return an unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG Index;
|
|
ARC_STATUS Status;
|
|
|
|
#ifdef CACHE_DEVINFO
|
|
|
|
RtlZeroMemory(DeviceCloseNotify, sizeof(DeviceCloseNotify));
|
|
|
|
#endif
|
|
|
|
//
|
|
// Initialize the file table.
|
|
//
|
|
for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index += 1) {
|
|
BlFileTable[Index].Flags.Open = 0;
|
|
BlFileTable[Index].StructureContext = NULL;
|
|
|
|
#ifdef CACHE_DEVINFO
|
|
DeviceFSCache[Index].DeviceId = UNINITIALIZED_DEVICE_ID;
|
|
DeviceFSCache[Index].Context = NULL;
|
|
DeviceFSCache[Index].DevMethods = NULL;
|
|
#endif // for CACHE_DEVINFO
|
|
}
|
|
|
|
if((Status = NetInitialize()) != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
if((Status = FatInitialize()) != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
if((Status = NtfsInitialize()) != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
#ifndef DONT_USE_UDF
|
|
if((Status = UDFSInitialize()) != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
if((Status = CdfsInitialize()) != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
|
|
PBOOTFS_INFO
|
|
BlGetFsInfo(
|
|
IN ULONG DeviceId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns filesystem information for the filesystem on the specified device
|
|
|
|
Arguments:
|
|
|
|
FileId - Supplies the file table index of the device
|
|
|
|
Return Value:
|
|
|
|
PBOOTFS_INFO - Pointer to the BOOTFS_INFO structure for the filesystem
|
|
|
|
NULL - unknown filesystem
|
|
|
|
--*/
|
|
|
|
{
|
|
FS_STRUCTURE_CONTEXT FsStructure;
|
|
PBL_DEVICE_ENTRY_TABLE Table;
|
|
|
|
if ((Table = IsNetFileStructure(DeviceId, &FsStructure)) != NULL) {
|
|
return(Table->BootFsInfo);
|
|
}
|
|
|
|
if ((Table = IsFatFileStructure(DeviceId, &FsStructure)) != NULL) {
|
|
return(Table->BootFsInfo);
|
|
}
|
|
|
|
if ((Table = IsNtfsFileStructure(DeviceId, &FsStructure)) != NULL) {
|
|
return(Table->BootFsInfo);
|
|
}
|
|
|
|
if ((Table = IsCdfsFileStructure(DeviceId, &FsStructure)) != NULL) {
|
|
return(Table->BootFsInfo);
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlClose (
|
|
IN ULONG FileId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function closes a file or a device that is open.
|
|
|
|
Arguments:
|
|
|
|
FileId - Supplies the file table index.
|
|
|
|
Return Value:
|
|
|
|
If the specified file is open, then a close is attempted and
|
|
the status of the operation is returned. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// If the file is open, then attempt to close it. Otherwise return an
|
|
// access error.
|
|
//
|
|
|
|
if (BlFileTable[FileId].Flags.Open == 1) {
|
|
|
|
return (BlFileTable[FileId].DeviceEntryTable->Close)(FileId);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlMount (
|
|
IN PCHAR MountPath,
|
|
IN MOUNT_OPERATION Operation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(MountPath);
|
|
UNREFERENCED_PARAMETER(Operation);
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
|
|
ARC_STATUS
|
|
_BlOpen (
|
|
IN ULONG DeviceId,
|
|
IN PCHAR OpenPath,
|
|
IN OPEN_MODE OpenMode,
|
|
OUT PULONG FileId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function opens a file on the specified device. The type of file
|
|
system is automatically recognized.
|
|
|
|
Arguments:
|
|
|
|
DeviceId - Supplies the file table index of the device.
|
|
|
|
OpenPath - Supplies a pointer to the name of the file to be opened.
|
|
|
|
OpenMode - Supplies the mode of the open.
|
|
|
|
FileId - Supplies a pointer to a variable that receives the file
|
|
table index of the open file.
|
|
|
|
Return Value:
|
|
|
|
If a free file table entry is available and the file structure on
|
|
the specified device is recognized, then an open is attempted and
|
|
the status of the operation is returned. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Index;
|
|
FS_STRUCTURE_CONTEXT FsStructureTemp;
|
|
ULONG ContextSize;
|
|
ARC_STATUS Status;
|
|
|
|
#ifdef CACHE_DEVINFO
|
|
|
|
ULONG CacheIndex;
|
|
|
|
for (CacheIndex = 0; CacheIndex < BL_FILE_TABLE_SIZE; CacheIndex++) {
|
|
if (DeviceFSCache[CacheIndex].DeviceId == DeviceId){
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#endif // for CACHE_DEVINFO
|
|
|
|
//
|
|
// Search for a free file table entry.
|
|
//
|
|
for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index += 1) {
|
|
if (BlFileTable[Index].Flags.Open == 0) {
|
|
#ifdef CACHE_DEVINFO
|
|
if (CacheIndex >= BL_FILE_TABLE_SIZE) {
|
|
#endif // for CACHE_DEVINFO
|
|
|
|
//
|
|
// Attempt to recognize the file system on the specified
|
|
// device. If no one recognizes it then return an unsuccessful
|
|
// status.
|
|
//
|
|
if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsNetFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(NET_STRUCTURE_CONTEXT);
|
|
|
|
} else if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsFatFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(FAT_STRUCTURE_CONTEXT);
|
|
|
|
} else if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsNtfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(NTFS_STRUCTURE_CONTEXT);
|
|
#ifndef DONT_USE_UDF
|
|
} else if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsUDFSFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(UDFS_STRUCTURE_CONTEXT);
|
|
#endif
|
|
#if defined(ELTORITO)
|
|
//
|
|
// This must go before the check for Cdfs; otherwise Cdfs will be detected.
|
|
// Since BIOS calls already set up to use EDDS, reads will succeed, and checks
|
|
// against ISO will succeed. We check El Torito-specific fields here as well as ISO
|
|
//
|
|
} else if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsEtfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(ETFS_STRUCTURE_CONTEXT);
|
|
#endif
|
|
} else if ((BlFileTable[Index].DeviceEntryTable =
|
|
IsCdfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
|
|
ContextSize = sizeof(CDFS_STRUCTURE_CONTEXT);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
|
|
|
|
#ifndef CACHE_DEVINFO
|
|
|
|
//
|
|
// Cut down on the amount of heap we use by attempting to reuse
|
|
// the fs structure context instead of always allocating a
|
|
// new one. The NTFS structure context is over 4K; the FAT one
|
|
// is almost 2K. In the setup case we're loading dozens of files.
|
|
// Add in compression, where diamond may open each file multiple
|
|
// times, and we waste a lot of heap.
|
|
//
|
|
if(BlFileTable[Index].StructureContext == NULL) {
|
|
BlFileTable[Index].StructureContext = BlAllocateHeap(sizeof(FS_STRUCTURE_CONTEXT));
|
|
if(BlFileTable[Index].StructureContext == NULL) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
RtlZeroMemory(BlFileTable[Index].StructureContext, sizeof(FS_STRUCTURE_CONTEXT));
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
BlFileTable[Index].StructureContext,
|
|
&FsStructureTemp,
|
|
ContextSize
|
|
);
|
|
|
|
#else
|
|
//
|
|
// save the collected info in cache for future use
|
|
//
|
|
for (CacheIndex = 0; CacheIndex < BL_FILE_TABLE_SIZE; CacheIndex++) {
|
|
if (DeviceFSCache[CacheIndex].DeviceId == UNINITIALIZED_DEVICE_ID){
|
|
PVOID Context = DeviceFSCache[CacheIndex].Context;
|
|
|
|
DeviceFSCache[CacheIndex].DeviceId = DeviceId;
|
|
|
|
//
|
|
// Cut down on the amount of heap we use by attempting to reuse
|
|
// the fs structure context instead of always allocating a
|
|
// new one. The NTFS structure context is over 4K; the FAT one
|
|
// is almost 2K. In the setup case we're loading dozens of files.
|
|
// Add in compression, where diamond may open each file multiple
|
|
// times, and we waste a lot of heap.
|
|
//
|
|
if(Context == NULL) {
|
|
Context = BlAllocateHeap(sizeof(FS_STRUCTURE_CONTEXT));
|
|
|
|
if(Context == NULL) {
|
|
DeviceFSCache[CacheIndex].DeviceId = UNINITIALIZED_DEVICE_ID;
|
|
return ENOMEM;
|
|
}
|
|
|
|
RtlZeroMemory(Context, sizeof(FS_STRUCTURE_CONTEXT));
|
|
DeviceFSCache[CacheIndex].Context = Context;
|
|
}
|
|
|
|
RtlCopyMemory(Context,
|
|
&FsStructureTemp,
|
|
ContextSize);
|
|
|
|
BlFileTable[Index].StructureContext = Context;
|
|
|
|
//
|
|
// save the device table from the filetable entry
|
|
//
|
|
DeviceFSCache[CacheIndex].DevMethods = BlFileTable[Index].DeviceEntryTable;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (CacheIndex >= BL_FILE_TABLE_SIZE)
|
|
return ENOSPC;
|
|
|
|
} else {
|
|
#if 0
|
|
{
|
|
char Msg[128] = {0};
|
|
|
|
BlPositionCursor(1, 5);
|
|
sprintf(Msg,
|
|
"Using %d cached info %p, %p for device %d, %s",
|
|
CacheIndex,
|
|
DeviceFSCache[CacheIndex].Context,
|
|
DeviceFSCache[CacheIndex].DevMethods,
|
|
DeviceFSCache[CacheIndex].DeviceId,
|
|
OpenPath);
|
|
|
|
BlPrint(" ");
|
|
BlPositionCursor(1, 5);
|
|
BlPrint(Msg);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Reuse the already cached entry
|
|
//
|
|
BlFileTable[Index].DeviceEntryTable = DeviceFSCache[CacheIndex].DevMethods;
|
|
BlFileTable[Index].StructureContext = DeviceFSCache[CacheIndex].Context;
|
|
}
|
|
|
|
#endif // for ! CACHE_DEVINFO
|
|
|
|
//
|
|
// Someone has mounted the volume so now attempt to open the file.
|
|
//
|
|
*FileId = Index;
|
|
BlFileTable[Index].DeviceId = DeviceId;
|
|
|
|
|
|
Status = EBADF;
|
|
#if DBG
|
|
//
|
|
// Check and see if a user wants to replace this binary
|
|
// via a transfer through the kernel debugger. If this
|
|
// fails just continue on with the existing file.
|
|
//
|
|
if( BdDebuggerEnabled ) {
|
|
|
|
Status = BdPullRemoteFile( OpenPath,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_OVERWRITE_IF,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
*FileId );
|
|
if( Status == ESUCCESS ) {
|
|
DbgPrint( "BlLoadImageEx: Pulled %s from Kernel Debugger\r\n", OpenPath );
|
|
|
|
//
|
|
// Make absolutely sure we don't reuse this device filesystem cache
|
|
// entry because we've piggybacked on the net filesystem to bring
|
|
// the kdfile over the serial point. That means we really don't
|
|
// want to reuse this entry unless we're booting off the net, in which
|
|
// case we'll take the perf hit (slight) on DBG builds.
|
|
//
|
|
#ifdef CACHE_DEVINFO
|
|
DeviceFSCache[*FileId].DeviceId = UNINITIALIZED_DEVICE_ID;
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
if( Status != ESUCCESS ) {
|
|
Status = (BlFileTable[Index].DeviceEntryTable->Open)(OpenPath,
|
|
OpenMode,
|
|
FileId);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
}
|
|
|
|
//
|
|
// No free file table entry could be found.
|
|
//
|
|
|
|
return EACCES;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlOpen (
|
|
IN ULONG DeviceId,
|
|
IN PCHAR OpenPath,
|
|
IN OPEN_MODE OpenMode,
|
|
OUT PULONG FileId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Wrapper routine for BlOpen that attempts to locate the compressed
|
|
form of a filename before trying to locate the filename itself.
|
|
|
|
Callers need not know or care that a file x.exe actually exists
|
|
as a compressed file x.ex_. If the file is being opened for
|
|
read-only access and the decompressor indicates that it wants
|
|
to try locating the compressed form of the file, we transparently
|
|
locate that one instead of the one requested.
|
|
|
|
Arguments:
|
|
|
|
Same as _BlOpen().
|
|
|
|
Return Value:
|
|
|
|
Same as _BlOpen().
|
|
|
|
--*/
|
|
|
|
{
|
|
CHAR CompressedName[256];
|
|
ARC_STATUS Status;
|
|
|
|
if((OpenMode == ArcOpenReadOnly) && DecompGenerateCompressedName(OpenPath,CompressedName)) {
|
|
//
|
|
// Attempt to locate the compressed form of the filename.
|
|
//
|
|
Status = _BlOpen(DeviceId,CompressedName,OpenMode,FileId);
|
|
if(Status == ESUCCESS) {
|
|
|
|
Status = DecompPrepareToReadCompressedFile(CompressedName,*FileId);
|
|
|
|
if(Status == (ARC_STATUS)(-1)) {
|
|
//
|
|
// This is a special status indicating that the file is not
|
|
// to be processed for decompression. This typically happens
|
|
// when the decompressor opens the file to read the compressed
|
|
// data out of it.
|
|
//
|
|
Status = ESUCCESS;
|
|
#if DBG
|
|
BlFilesOpened++;
|
|
#endif
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
}
|
|
|
|
Status = (_BlOpen(DeviceId,OpenPath,OpenMode,FileId));
|
|
|
|
#if DBG
|
|
if (Status == ESUCCESS)
|
|
BlFilesOpened++;
|
|
#endif
|
|
|
|
return Status;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlRead (
|
|
IN ULONG FileId,
|
|
OUT PVOID Buffer,
|
|
IN ULONG Length,
|
|
OUT PULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads from a file or a device that is open.
|
|
|
|
Arguments:
|
|
|
|
FileId - Supplies the file table index.
|
|
|
|
Buffer - Supplies a pointer to the buffer that receives the data
|
|
read.
|
|
|
|
Length - Supplies the number of bytes that are to be read.
|
|
|
|
Count - Supplies a pointer to a variable that receives the number of
|
|
bytes actually transfered.
|
|
|
|
Return Value:
|
|
|
|
If the specified file is open for read, then a read is attempted
|
|
and the status of the operation is returned. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// If the file is open for read, then attempt to read from it. Otherwise
|
|
// return an access error.
|
|
//
|
|
|
|
if ((BlFileTable[FileId].Flags.Open == 1) &&
|
|
(BlFileTable[FileId].Flags.Read == 1)) {
|
|
return (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
|
|
Buffer,
|
|
Length,
|
|
Count);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlReadAtOffset(
|
|
IN ULONG FileId,
|
|
IN ULONG Offset,
|
|
IN ULONG Length,
|
|
OUT PVOID Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine seeks to the proper place in FileId and extracts Length bytes of data into
|
|
Data.
|
|
|
|
Arguments:
|
|
|
|
FileId - Supplies the file id where read operations are to be performed.
|
|
|
|
Offset - The absolute byte offset to start reading at.
|
|
|
|
Length - The number of bytes to read.
|
|
|
|
Data - Buffer to hold the read results.
|
|
|
|
--*/
|
|
{
|
|
ARC_STATUS Status;
|
|
LARGE_INTEGER LargeOffset;
|
|
ULONG Count;
|
|
|
|
LargeOffset.HighPart = 0;
|
|
LargeOffset.LowPart = Offset;
|
|
Status = BlSeek(FileId, &LargeOffset, SeekAbsolute);
|
|
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
Status = BlRead(FileId, Data, Length, &Count);
|
|
|
|
if ((Status == ESUCCESS) && (Count != Length)) {
|
|
return EINVAL;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
ARC_STATUS
|
|
BlGetReadStatus (
|
|
IN ULONG FileId
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER( FileId );
|
|
|
|
return ESUCCESS;
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlSeek (
|
|
IN ULONG FileId,
|
|
IN PLARGE_INTEGER Offset,
|
|
IN SEEK_MODE SeekMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
If the specified file is open, then a seek is attempted and
|
|
the status of the operation is returned. Otherwise, return an
|
|
unsuccessful status.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// If the file is open, then attempt to seek on it. Otherwise return an
|
|
// access error.
|
|
//
|
|
|
|
if (BlFileTable[FileId].Flags.Open == 1) {
|
|
return (BlFileTable[FileId].DeviceEntryTable->Seek)(FileId,
|
|
Offset,
|
|
SeekMode);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlWrite (
|
|
IN ULONG FileId,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length,
|
|
OUT PULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// If the file is open for write, then attempt to write to it. Otherwise
|
|
// return an access error.
|
|
//
|
|
|
|
if ((BlFileTable[FileId].Flags.Open == 1) &&
|
|
(BlFileTable[FileId].Flags.Write == 1)) {
|
|
return (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
|
|
Buffer,
|
|
Length,
|
|
Count);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlGetFileInformation (
|
|
IN ULONG FileId,
|
|
IN PFILE_INFORMATION FileInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// If the file is open, then attempt to get file information. Otherwise
|
|
// return an access error.
|
|
//
|
|
|
|
if (BlFileTable[FileId].Flags.Open == 1) {
|
|
return (BlFileTable[FileId].DeviceEntryTable->GetFileInformation)(FileId,
|
|
FileInformation);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
ARC_STATUS
|
|
BlSetFileInformation (
|
|
IN ULONG FileId,
|
|
IN ULONG AttributeFlags,
|
|
IN ULONG AttributeMask
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// If the file is open, then attempt to Set file information. Otherwise
|
|
// return an access error.
|
|
//
|
|
|
|
if (BlFileTable[FileId].Flags.Open == 1) {
|
|
return (BlFileTable[FileId].DeviceEntryTable->SetFileInformation)(FileId,
|
|
AttributeFlags,
|
|
AttributeMask);
|
|
|
|
} else {
|
|
return EACCES;
|
|
}
|
|
}
|
|
|
|
|
|
ARC_STATUS
|
|
BlRename(
|
|
IN ULONG FileId,
|
|
IN PCHAR NewName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Rename an open file or directory.
|
|
|
|
Arguments:
|
|
|
|
FileId - supplies a handle to an open file or directory. The file
|
|
need not be open for write access.
|
|
|
|
NewName - New name to give the file or directory (filename part only).
|
|
|
|
Return Value:
|
|
|
|
Status indicating result of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
if(BlFileTable[FileId].Flags.Open == 1) {
|
|
return(BlFileTable[FileId].DeviceEntryTable->Rename(FileId,
|
|
NewName
|
|
)
|
|
);
|
|
} else {
|
|
return(EACCES);
|
|
}
|
|
}
|
|
|
|
|