implement proper IRQL, DPCs, kernel and user APCs, alertable waits, async file I/O with cancellation, trap frames, selftests, a real driver/device model, native async FAT32, VFAT dotfile fixes, syscall ABI cleanup, async_apc and async_cancel tests, POSIX multi-volume paths, and pimp the readme.
This commit is contained in:
1 parent
f5fd7bdd75
commit
529f816166
75 files changed
+9969
-5675
No files matched your search
+199
-149
@@ -1,149 +1,199 @@
|
||||
#pragma once
|
||||
// io_file.h - VFS layer
|
||||
// Filesystem drivers register an IO_FILESYSTEM vtable via IoRegisterFilesystem.
|
||||
// Kernel and user code open files through IoOpenFile.
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <ke_status.h>
|
||||
#include <ob_object.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// KDIR_ENTRY - one directory entry returned by ReadDir / SYS_READ_DIR
|
||||
// Attribute flags match FAT32/Win32: ATTR_DIRECTORY=0x10, ATTR_ARCHIVE=0x20
|
||||
// ---------------------------------------------------------------------------
|
||||
#define KDIR_NAME_MAX 260
|
||||
|
||||
typedef struct KDIR_ENTRY {
|
||||
char Name[KDIR_NAME_MAX]; // null-terminated filename
|
||||
uint8_t Attr; // FAT attribute byte (0x10=dir, 0x20=file)
|
||||
uint32_t FileSize; // 0 for directories
|
||||
} KDIR_ENTRY;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Filesystem driver vtable - filled in by fat32.sys (or any future fs driver)
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct IO_FILESYSTEM {
|
||||
// Open a file by absolute path (e.g. "apps\\shell.exe").
|
||||
// Returns an opaque per-file driver cookie in* fileCtx.
|
||||
KSTATUS (*Open)(struct IO_FILESYSTEM* fs,
|
||||
const char* path, void **fileCtx);
|
||||
|
||||
// Read up to 'size' bytes at 'offset' into 'buf'.
|
||||
// Sets* bytesRead to actual bytes copied.
|
||||
KSTATUS (*Read)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, void* buf,
|
||||
size_t size, size_t* bytesRead);
|
||||
|
||||
KSTATUS (*Write)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, const void* buf,
|
||||
size_t size, size_t* bytesWritten);
|
||||
|
||||
// Create a new file at 'path'; returns an open fileCtx on success.
|
||||
KSTATUS (*Create)(struct IO_FILESYSTEM* fs, const char* path,
|
||||
void** fileCtx);
|
||||
|
||||
// Delete the file at 'path'.
|
||||
KSTATUS (*Delete)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Rename or move a file/directory within the same filesystem.
|
||||
KSTATUS (*Rename)(struct IO_FILESYSTEM* fs,
|
||||
const char* oldPath, const char* newPath);
|
||||
|
||||
// Create or remove directories.
|
||||
KSTATUS (*CreateDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
KSTATUS (*RemoveDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Truncate or extend the file to exactly 'newSize' bytes.
|
||||
KSTATUS (*Truncate)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t newSize);
|
||||
|
||||
// Return the file size in bytes.
|
||||
uint64_t (*GetSize)(struct IO_FILESYSTEM* fs, void* fileCtx);
|
||||
|
||||
// Release any resources the driver allocated for fileCtx.
|
||||
void (*Close)(struct IO_FILESYSTEM* fs, void* fileCtx);
|
||||
|
||||
// Optional driver-private data.
|
||||
void* DriverCtx;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Directory enumeration (optional - may be NULL if not supported)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Open a directory iterator for 'dirPath' (relative or drive-prefixed).
|
||||
// Returns an opaque per-iteration driver cookie in *dirCtx.
|
||||
KSTATUS (*OpenDir)(struct IO_FILESYSTEM* fs,
|
||||
const char* dirPath, void** dirCtx);
|
||||
|
||||
// Advance to the next entry.
|
||||
// Fills 'out' with name, attributes, and size.
|
||||
// Returns STATUS_NO_MORE_FILES when the directory is exhausted.
|
||||
KSTATUS (*ReadDir)(struct IO_FILESYSTEM* fs, void* dirCtx,
|
||||
struct KDIR_ENTRY* out);
|
||||
|
||||
// Release resources allocated by OpenDir.
|
||||
void (*CloseDir)(struct IO_FILESYSTEM* fs, void* dirCtx);
|
||||
} IO_FILESYSTEM;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// FILE_OBJECT - the kernel object returned to callers
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct FILE_OBJECT {
|
||||
OBJECT Header; // must be first
|
||||
IO_FILESYSTEM* Fs;
|
||||
void* FileCtx; // driver cookie
|
||||
uint64_t Size;
|
||||
uint64_t Offset; // current position for sequential reads
|
||||
} FILE_OBJECT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DIR_OBJECT - kernel object for an open directory iterator
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct DIR_OBJECT {
|
||||
OBJECT Header; // must be first
|
||||
IO_FILESYSTEM* Fs;
|
||||
void* DirCtx; // driver cookie (opaque iteration state)
|
||||
} DIR_OBJECT;
|
||||
|
||||
typedef struct IO_VOLUME_PARAMS {
|
||||
uint8_t DiskIndex; // which disk in HAL_DISK table
|
||||
uint64_t PartitionLba; // starting LBA of this partition
|
||||
uint64_t PartitionSize; // sectors, for bounds checking
|
||||
} IO_VOLUME_PARAMS;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registration - called by fat32.sys from DriverEntry
|
||||
// ---------------------------------------------------------------------------
|
||||
// driveIndex matches the index passed to IoRegisterDisk.
|
||||
__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel-side API
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out);
|
||||
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
size_t size, size_t* bytesRead);
|
||||
__declspec(dllexport) KSTATUS IoWriteFile (FILE_OBJECT* file, const void* buf,
|
||||
size_t size, size_t* bytesWritten);
|
||||
__declspec(dllexport) KSTATUS IoCreateFile (const char* path, FILE_OBJECT** out);
|
||||
__declspec(dllexport) KSTATUS IoDeleteFile (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRenameFile (const char* oldPath, const char* newPath);
|
||||
__declspec(dllexport) KSTATUS IoCreateDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRemoveDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize);
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
|
||||
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file);
|
||||
__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Directory enumeration API
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoOpenDir (const char* dirPath, DIR_OBJECT** out);
|
||||
__declspec(dllexport) KSTATUS IoReadDir (DIR_OBJECT* dir, KDIR_ENTRY* entryOut);
|
||||
__declspec(dllexport) void IoCloseDir(DIR_OBJECT* dir);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Current Working Directory
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoSetCwd(const char* path);
|
||||
__declspec(dllexport) KSTATUS IoGetCwd(char* buf, size_t size);
|
||||
#pragma once
|
||||
// io_file.h - VFS layer
|
||||
// Filesystem drivers register an IO_FILESYSTEM vtable via IoRegisterFilesystem.
|
||||
// Kernel and user code open files through IoOpenFile.
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <ke_status.h>
|
||||
#include <ob_object.h>
|
||||
#include <ke_spinlock.h>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// KDIR_ENTRY - one directory entry returned by ReadDir / SYS_READ_DIR
|
||||
// Attribute flags match FAT32/Win32: ATTR_DIRECTORY=0x10, ATTR_ARCHIVE=0x20
|
||||
// ---------------------------------------------------------------------------
|
||||
#define KDIR_NAME_MAX 260
|
||||
|
||||
typedef struct KDIR_ENTRY {
|
||||
char Name[KDIR_NAME_MAX]; // null-terminated filename
|
||||
uint8_t Attr; // FAT attribute byte (0x10=dir, 0x20=file)
|
||||
uint32_t FileSize; // 0 for directories
|
||||
} KDIR_ENTRY;
|
||||
|
||||
// Native asynchronous filesystem completion. Filesystems that provide
|
||||
// ReadAsync/WriteAsync accept the operation, return STATUS_PENDING, and later
|
||||
// call Complete(CompleteContext, status, information). Filesystems without
|
||||
// these callbacks fall back to the generic VFS async worker.
|
||||
typedef void (*IO_FS_ASYNC_COMPLETE)(void* completeContext,
|
||||
KSTATUS status,
|
||||
size_t information);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Filesystem driver vtable - filled in by fat32.sys (or any future fs driver)
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct IO_FILESYSTEM {
|
||||
// Open a file by absolute path (e.g. "apps\\shell.exe").
|
||||
// Returns an opaque per-file driver cookie in* fileCtx.
|
||||
KSTATUS (*Open)(struct IO_FILESYSTEM* fs,
|
||||
const char* path, void **fileCtx);
|
||||
|
||||
// Read up to 'size' bytes at 'offset' into 'buf'.
|
||||
// Sets* bytesRead to actual bytes copied.
|
||||
KSTATUS (*Read)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, void* buf,
|
||||
size_t size, size_t* bytesRead);
|
||||
|
||||
KSTATUS (*Write)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, const void* buf,
|
||||
size_t size, size_t* bytesWritten);
|
||||
|
||||
KSTATUS (*ReadAsync)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, void* buf, size_t size,
|
||||
IO_FS_ASYNC_COMPLETE complete,
|
||||
void* completeContext);
|
||||
|
||||
KSTATUS (*WriteAsync)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t offset, const void* buf, size_t size,
|
||||
IO_FS_ASYNC_COMPLETE complete,
|
||||
void* completeContext);
|
||||
|
||||
// Create a new file at 'path'; returns an open fileCtx on success.
|
||||
KSTATUS (*Create)(struct IO_FILESYSTEM* fs, const char* path,
|
||||
void** fileCtx);
|
||||
|
||||
// Delete the file at 'path'.
|
||||
KSTATUS (*Delete)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Rename or move a file/directory within the same filesystem.
|
||||
KSTATUS (*Rename)(struct IO_FILESYSTEM* fs,
|
||||
const char* oldPath, const char* newPath);
|
||||
|
||||
// Create or remove directories.
|
||||
KSTATUS (*CreateDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
KSTATUS (*RemoveDir)(struct IO_FILESYSTEM* fs, const char* path);
|
||||
|
||||
// Truncate or extend the file to exactly 'newSize' bytes.
|
||||
KSTATUS (*Truncate)(struct IO_FILESYSTEM* fs, void* fileCtx,
|
||||
uint64_t newSize);
|
||||
|
||||
// Return the file size in bytes.
|
||||
uint64_t (*GetSize)(struct IO_FILESYSTEM* fs, void* fileCtx);
|
||||
|
||||
// Release any resources the driver allocated for fileCtx.
|
||||
void (*Close)(struct IO_FILESYSTEM* fs, void* fileCtx);
|
||||
|
||||
// Optional driver-private data.
|
||||
void* DriverCtx;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Directory enumeration (optional - may be NULL if not supported)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Open a directory iterator for 'dirPath' (relative or drive-prefixed).
|
||||
// Returns an opaque per-iteration driver cookie in *dirCtx.
|
||||
KSTATUS (*OpenDir)(struct IO_FILESYSTEM* fs,
|
||||
const char* dirPath, void** dirCtx);
|
||||
|
||||
// Advance to the next entry.
|
||||
// Fills 'out' with name, attributes, and size.
|
||||
// Returns STATUS_NO_MORE_FILES when the directory is exhausted.
|
||||
KSTATUS (*ReadDir)(struct IO_FILESYSTEM* fs, void* dirCtx,
|
||||
struct KDIR_ENTRY* out);
|
||||
|
||||
// Release resources allocated by OpenDir.
|
||||
void (*CloseDir)(struct IO_FILESYSTEM* fs, void* dirCtx);
|
||||
} IO_FILESYSTEM;
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// IO_STATUS_BLOCK - completion status visible to async callers
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct IO_STATUS_BLOCK {
|
||||
volatile KSTATUS Status;
|
||||
volatile size_t Information;
|
||||
} IO_STATUS_BLOCK;
|
||||
|
||||
struct EVENT;
|
||||
struct KAPC;
|
||||
typedef struct IO_ASYNC_FILE_REQUEST_OBJECT IO_ASYNC_FILE_REQUEST_OBJECT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// FILE_OBJECT - the kernel object returned to callers
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct FILE_OBJECT {
|
||||
OBJECT Header; // must be first
|
||||
IO_FILESYSTEM* Fs;
|
||||
void* FileCtx; // driver cookie
|
||||
SPINLOCK Lock; // protects cached Size/Offset updates
|
||||
uint64_t Size;
|
||||
uint64_t Offset; // current position for sequential reads
|
||||
} FILE_OBJECT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DIR_OBJECT - kernel object for an open directory iterator
|
||||
// ---------------------------------------------------------------------------
|
||||
typedef struct DIR_OBJECT {
|
||||
OBJECT Header; // must be first
|
||||
IO_FILESYSTEM* Fs;
|
||||
void* DirCtx; // driver cookie (opaque iteration state)
|
||||
} DIR_OBJECT;
|
||||
|
||||
typedef struct IO_VOLUME_PARAMS {
|
||||
uint8_t DiskIndex; // registered disk DEVICE_OBJECT index
|
||||
uint64_t PartitionLba; // starting LBA of this partition
|
||||
uint64_t PartitionSize; // sectors, for bounds checking
|
||||
} IO_VOLUME_PARAMS;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Registration - called by fat32.sys from DriverEntry
|
||||
// ---------------------------------------------------------------------------
|
||||
// driveIndex matches the index passed to IoRegisterDiskDevice.
|
||||
__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Kernel-side API
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out);
|
||||
__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf,
|
||||
size_t size, size_t* bytesRead);
|
||||
__declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
void* buf, size_t size, size_t* bytesRead);
|
||||
__declspec(dllexport) KSTATUS IoWriteFile (FILE_OBJECT* file, const void* buf,
|
||||
size_t size, size_t* bytesWritten);
|
||||
__declspec(dllexport) KSTATUS IoWriteFileAt(FILE_OBJECT* file, uint64_t offset,
|
||||
const void* buf, size_t size,
|
||||
size_t* bytesWritten);
|
||||
__declspec(dllexport) KSTATUS IoReadFileAsyncKernel(FILE_OBJECT* file, void* buf,
|
||||
size_t size, uint64_t offset, IO_STATUS_BLOCK* iosb,
|
||||
struct EVENT* completionEvent, struct KAPC* completionApc,
|
||||
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
|
||||
__declspec(dllexport) KSTATUS IoWriteFileAsyncKernel(FILE_OBJECT* file, const void* buf,
|
||||
size_t size, uint64_t offset, IO_STATUS_BLOCK* iosb,
|
||||
struct EVENT* completionEvent, struct KAPC* completionApc,
|
||||
IO_ASYNC_FILE_REQUEST_OBJECT** requestOut);
|
||||
__declspec(dllexport) OBJECT* IoAsyncFileRequestObject(IO_ASYNC_FILE_REQUEST_OBJECT* request);
|
||||
__declspec(dllexport) KSTATUS IoCancelAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request);
|
||||
__declspec(dllexport) KSTATUS IoQueryAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* request,
|
||||
IO_STATUS_BLOCK* iosbOut);
|
||||
__declspec(dllexport) KSTATUS IoCreateFile (const char* path, FILE_OBJECT** out);
|
||||
__declspec(dllexport) KSTATUS IoDeleteFile (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRenameFile (const char* oldPath, const char* newPath);
|
||||
__declspec(dllexport) KSTATUS IoCreateDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoRemoveDir (const char* path);
|
||||
__declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize);
|
||||
__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset);
|
||||
__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file);
|
||||
__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Directory enumeration API
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoOpenDir (const char* dirPath, DIR_OBJECT** out);
|
||||
__declspec(dllexport) KSTATUS IoReadDir (DIR_OBJECT* dir, KDIR_ENTRY* entryOut);
|
||||
__declspec(dllexport) void IoCloseDir(DIR_OBJECT* dir);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Current Working Directory
|
||||
// ---------------------------------------------------------------------------
|
||||
__declspec(dllexport) KSTATUS IoSetCwd(const char* path);
|
||||
__declspec(dllexport) KSTATUS IoGetCwd(char* buf, size_t size);
|
||||
Reference in new issue
Block a user