diff options
Diffstat (limited to 'e2fslib/nt_io.c')
-rw-r--r-- | e2fslib/nt_io.c | 1513 |
1 files changed, 0 insertions, 1513 deletions
diff --git a/e2fslib/nt_io.c b/e2fslib/nt_io.c deleted file mode 100644 index c39127c..0000000 --- a/e2fslib/nt_io.c +++ /dev/null @@ -1,1513 +0,0 @@ -/* - * nt_io.c --- This is the Nt I/O interface to the I/O manager. - * - * Implements a one-block write-through cache. - * - * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. - * Copyright (C) 1998 Andrey Shedel (andreys@ns.cr.cyco.com) - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -// -// I need some warnings to disable... -// - - -#pragma warning(disable:4514) // unreferenced inline function has been removed -#pragma warning(push,4) - -#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union) -#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int -#pragma warning(disable:4115) // named type definition in parentheses - -#include <ntddk.h> -#include <ntdddisk.h> -#include <ntstatus.h> - -#pragma warning(pop) - - -// -// Some native APIs. -// - -NTSYSAPI -ULONG -NTAPI -RtlNtStatusToDosError( - IN NTSTATUS Status - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtClose( - IN HANDLE Handle - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtOpenFile( - OUT PHANDLE FileHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG ShareAccess, - IN ULONG OpenOptions - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtFlushBuffersFile( - IN HANDLE FileHandle, - OUT PIO_STATUS_BLOCK IoStatusBlock - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtReadFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - OUT PVOID Buffer, - IN ULONG Length, - IN PLARGE_INTEGER ByteOffset OPTIONAL, - IN PULONG Key OPTIONAL - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtWriteFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PVOID Buffer, - IN ULONG Length, - IN PLARGE_INTEGER ByteOffset OPTIONAL, - IN PULONG Key OPTIONAL - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtDeviceIoControlFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG IoControlCode, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtFsControlFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG IoControlCode, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtDelayExecution( - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Interval - ); - - -#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -// -// useful macros -// - -#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0))) - - -// -// Include Win32 error codes. -// - -#include <winerror.h> - -// -// standard stuff -// - -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <malloc.h> - -#include <linux/types.h> -#include "ext2_fs.h" -#include <errno.h> - -#include "et/com_err.h" -#include "ext2fs/ext2fs.h" -#include "ext2fs/ext2_err.h" - - - - -// -// For checking structure magic numbers... -// - - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -#define EXT2_ET_MAGIC_NT_IO_CHANNEL 0x10ed - - -// -// Private data block -// - -typedef struct _NT_PRIVATE_DATA { - int magic; - HANDLE Handle; - int Flags; - PCHAR Buffer; - __u32 BufferBlockNumber; - ULONG BufferSize; - BOOLEAN OpenedReadonly; - BOOLEAN Written; -}NT_PRIVATE_DATA, *PNT_PRIVATE_DATA; - - - -// -// Standard interface prototypes -// - -static errcode_t nt_open(const char *name, int flags, io_channel *channel); -static errcode_t nt_close(io_channel channel); -static errcode_t nt_set_blksize(io_channel channel, int blksize); -static errcode_t nt_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t nt_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t nt_flush(io_channel channel); - -static struct struct_io_manager struct_nt_manager = { - EXT2_ET_MAGIC_IO_MANAGER, - "NT I/O Manager", - nt_open, - nt_close, - nt_set_blksize, - nt_read_blk, - nt_write_blk, - nt_flush -}; - - - -// -// function to get API -// - -io_manager nt_io_manager() -{ - return &struct_nt_manager; -} - - - - - -// -// This is a code to convert Win32 errors to unix errno -// - -typedef struct { - ULONG WinError; - int errnocode; -}ERROR_ENTRY; - -static ERROR_ENTRY ErrorTable[] = { - { ERROR_INVALID_FUNCTION, EINVAL }, - { ERROR_FILE_NOT_FOUND, ENOENT }, - { ERROR_PATH_NOT_FOUND, ENOENT }, - { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, - { ERROR_ACCESS_DENIED, EACCES }, - { ERROR_INVALID_HANDLE, EBADF }, - { ERROR_ARENA_TRASHED, ENOMEM }, - { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, - { ERROR_INVALID_BLOCK, ENOMEM }, - { ERROR_BAD_ENVIRONMENT, E2BIG }, - { ERROR_BAD_FORMAT, ENOEXEC }, - { ERROR_INVALID_ACCESS, EINVAL }, - { ERROR_INVALID_DATA, EINVAL }, - { ERROR_INVALID_DRIVE, ENOENT }, - { ERROR_CURRENT_DIRECTORY, EACCES }, - { ERROR_NOT_SAME_DEVICE, EXDEV }, - { ERROR_NO_MORE_FILES, ENOENT }, - { ERROR_LOCK_VIOLATION, EACCES }, - { ERROR_BAD_NETPATH, ENOENT }, - { ERROR_NETWORK_ACCESS_DENIED, EACCES }, - { ERROR_BAD_NET_NAME, ENOENT }, - { ERROR_FILE_EXISTS, EEXIST }, - { ERROR_CANNOT_MAKE, EACCES }, - { ERROR_FAIL_I24, EACCES }, - { ERROR_INVALID_PARAMETER, EINVAL }, - { ERROR_NO_PROC_SLOTS, EAGAIN }, - { ERROR_DRIVE_LOCKED, EACCES }, - { ERROR_BROKEN_PIPE, EPIPE }, - { ERROR_DISK_FULL, ENOSPC }, - { ERROR_INVALID_TARGET_HANDLE, EBADF }, - { ERROR_INVALID_HANDLE, EINVAL }, - { ERROR_WAIT_NO_CHILDREN, ECHILD }, - { ERROR_CHILD_NOT_COMPLETE, ECHILD }, - { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, - { ERROR_NEGATIVE_SEEK, EINVAL }, - { ERROR_SEEK_ON_DEVICE, EACCES }, - { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, - { ERROR_NOT_LOCKED, EACCES }, - { ERROR_BAD_PATHNAME, ENOENT }, - { ERROR_MAX_THRDS_REACHED, EAGAIN }, - { ERROR_LOCK_FAILED, EACCES }, - { ERROR_ALREADY_EXISTS, EEXIST }, - { ERROR_FILENAME_EXCED_RANGE, ENOENT }, - { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, - { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } -}; - - - - -static -unsigned -_MapDosError ( - IN ULONG WinError - ) -{ - int i; - - // - // Lookup - // - - for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) - { - if (WinError == ErrorTable[i].WinError) - { - return ErrorTable[i].errnocode; - } - } - - // - // not in table. Check ranges - // - - if ((WinError >= ERROR_WRITE_PROTECT) && - (WinError <= ERROR_SHARING_BUFFER_EXCEEDED)) - { - return EACCES; - } - else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) && - (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN)) - { - return ENOEXEC; - } - else - { - return EINVAL; - } -} - - - - - - - -// -// Function to map NT status to dos error. -// - -static -__inline -unsigned -_MapNtStatus( - IN NTSTATUS Status - ) -{ - return _MapDosError(RtlNtStatusToDosError(Status)); -} - - - - - -// -// Helper functions to make things easyer -// - -static -NTSTATUS -_OpenNtName( - IN PCSTR Name, - IN BOOLEAN Readonly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL - ) -{ - UNICODE_STRING UnicodeString; - ANSI_STRING AnsiString; - WCHAR Buffer[512]; - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - - // - // Make Unicode name from inlut string - // - - UnicodeString.Buffer = &Buffer[0]; - UnicodeString.Length = 0; - UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!! - - RtlInitAnsiString(&AnsiString, Name); - - Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); - - if(!NT_SUCCESS(Status)) - { - return Status; // Unpappable character? - } - - // - // Initialize object - // - - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - OBJ_CASE_INSENSITIVE, - NULL, - NULL ); - - // - // Try to open it in initial mode - // - - if(ARGUMENT_PRESENT(OpenedReadonly)) - { - *OpenedReadonly = Readonly; - } - - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - - if(!NT_SUCCESS(Status)) - { - // - // Maybe was just mounted? wait 0.5 sec and retry. - // - - LARGE_INTEGER Interval; - Interval.QuadPart = -5000000; // 0.5 sec. from now - - NtDelayExecution(FALSE, &Interval); - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - - // - // Try to satisfy mode - // - - if((STATUS_ACCESS_DENIED == Status) && !Readonly) - { - if(ARGUMENT_PRESENT(OpenedReadonly)) - { - *OpenedReadonly = TRUE; - } - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - } - } - - - - // - // done - // - - return Status; -} - - -static -NTSTATUS -_OpenDriveLetter( - IN CHAR Letter, - IN BOOLEAN ReadOnly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL - ) -{ - CHAR Buffer[100]; - - sprintf(Buffer, "\\DosDevices\\%c:", Letter); - - return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly); -} - - -// -// Flush device -// - -static -__inline -NTSTATUS -_FlushDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFlushBuffersFile(Handle, &IoStatusBlock); -} - - -// -// lock drive -// - -static -__inline -NTSTATUS -_LockDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0); -} - - -// -// unlock drive -// - -static -__inline -NTSTATUS -_UnlockDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0); -} - -static -__inline -NTSTATUS -_DismountDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); -} - - -// -// is mounted -// - -static -__inline -BOOLEAN -_IsMounted( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0); - return (BOOLEAN)(STATUS_SUCCESS == Status); -} - - -static -__inline -NTSTATUS -_CloseDisk( - IN HANDLE Handle - ) -{ - return NtClose(Handle); -} - - - - -// -// Make NT name from any recognized name -// - -static -PCSTR -_NormalizeDeviceName( - IN PCSTR Device, - IN PSTR NormalizedDeviceNameBuffer - ) -{ - int PartitionNumber = -1; - UCHAR DiskNumber; - PSTR p; - - - // - // Do not try to parse NT name - // - - if('\\' == *Device) - return Device; - - - - // - // Strip leading '/dev/' if any - // - - if(('/' == *(Device)) && - ('d' == *(Device + 1)) && - ('e' == *(Device + 2)) && - ('v' == *(Device + 3)) && - ('/' == *(Device + 4))) - { - Device += 5; - } - - if('\0' == *Device) - { - return NULL; - } - - - // - // forms: hda[n], fd[n] - // - - if('d' != *(Device + 1)) - { - return NULL; - } - - if('h' == *Device) - { - if((*(Device + 2) < 'a') || (*(Device + 2) > ('a' + 9)) || - ((*(Device + 3) != '\0') && - ((*(Device + 4) != '\0') || - ((*(Device + 3) < '0') || (*(Device + 3) > '9')) - ) - ) - ) - { - return NULL; - } - - DiskNumber = (UCHAR)(*(Device + 2) - 'a'); - - if(*(Device + 3) != '\0') - { - PartitionNumber = (*(Device + 3) - '0'); - } - - } - else if('f' == *Device) - { - // - // 3-d letted should be a digit. - // - - if((*(Device + 3) != '\0') || - (*(Device + 2) < '0') || (*(Device + 2) > '9')) - { - return NULL; - } - - DiskNumber = (UCHAR)(*(Device + 2) - '0'); - - } - else - { - // - // invalid prefix - // - - return NULL; - } - - - - // - // Prefix - // - - strcpy(NormalizedDeviceNameBuffer, "\\Device\\"); - - // - // Media name - // - - switch(*Device) - { - - case 'f': - strcat(NormalizedDeviceNameBuffer, "Floppy0"); - break; - - case 'h': - strcat(NormalizedDeviceNameBuffer, "Harddisk0"); - break; - } - - - p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; - *p = (CHAR)(*p + DiskNumber); - - - // - // Partition nr. - // - - if(PartitionNumber >= 0) - { - strcat(NormalizedDeviceNameBuffer, "\\Partition0"); - - p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; - *p = (CHAR)(*p + PartitionNumber); - } - - - return NormalizedDeviceNameBuffer; -} - - - - -static -VOID -_GetDeviceSize( - IN HANDLE h, - OUT unsigned __int64 *FsSize - ) -{ - PARTITION_INFORMATION pi; - DISK_GEOMETRY gi; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - - // - // Zero it - // - - *FsSize = 0; - - // - // Call driver - // - - RtlZeroMemory(&pi, sizeof(PARTITION_INFORMATION)); - - Status = NtDeviceIoControlFile( - h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO, - &pi, sizeof(PARTITION_INFORMATION), - &pi, sizeof(PARTITION_INFORMATION)); - - - if(NT_SUCCESS(Status)) - { - *FsSize = pi.PartitionLength.QuadPart; - } - else if(STATUS_INVALID_DEVICE_REQUEST == Status) - { - // - // No partitions: get device info. - // - - RtlZeroMemory(&gi, sizeof(DISK_GEOMETRY)); - - Status = NtDeviceIoControlFile( - h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, - &gi, sizeof(DISK_GEOMETRY), - &gi, sizeof(DISK_GEOMETRY)); - - - if(NT_SUCCESS(Status)) - { - *FsSize = - gi.BytesPerSector * - gi.SectorsPerTrack * - gi.TracksPerCylinder * - gi.Cylinders.QuadPart; - } - - } -} - - - -// -// Open device by name. -// - -static -BOOLEAN -_Ext2OpenDevice( - IN PCSTR Name, - IN BOOLEAN ReadOnly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL, - OUT unsigned *Errno OPTIONAL - ) -{ - CHAR NormalizedDeviceName[512]; - NTSTATUS Status; - - if(NULL == Name) - { - // - // Set not found - // - - if(ARGUMENT_PRESENT(Errno)) - *Errno = ENOENT; - - return FALSE; - } - - - if((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') && - (':' == *(Name + 1)) && ('\0' == *(Name + 2))) - { - Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly); - } - else - { - // - // Make name - // - - Name = _NormalizeDeviceName(Name, NormalizedDeviceName); - - if(NULL == Name) - { - // - // Set not found - // - - if(ARGUMENT_PRESENT(Errno)) - *Errno = ENOENT; - - return FALSE; - } - - // - // Try to open it - // - - Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly); - } - - - if(!NT_SUCCESS(Status)) - { - if(ARGUMENT_PRESENT(Errno)) - *Errno = _MapNtStatus(Status); - - return FALSE; - } - - return TRUE; -} - - -// -// Raw block io. Sets dos errno -// - -static -BOOLEAN -_BlockIo( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - IN OUT PCHAR Buffer, - IN BOOLEAN Read, - OUT unsigned* Errno - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - // - // Should be aligned - // - - ASSERT(0 == (Bytes % 512)); - ASSERT(0 == (Offset.LowPart % 512)); - - - // - // perform io - // - - if(Read) - { - Status = NtReadFile(Handle, NULL, NULL, NULL, - &IoStatusBlock, Buffer, Bytes, &Offset, NULL); - } - else - { - Status = NtWriteFile(Handle, NULL, NULL, NULL, - &IoStatusBlock, Buffer, Bytes, &Offset, NULL); - } - - - // - // translate error - // - - if(NT_SUCCESS(Status)) - { - *Errno = 0; - return TRUE; - } - - *Errno = _MapNtStatus(Status); - - return FALSE; -} - - - -__inline -BOOLEAN -_RawWrite( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - OUT const CHAR* Buffer, - OUT unsigned* Errno - ) -{ - return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno); -} - -__inline -BOOLEAN -_RawRead( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - IN PCHAR Buffer, - OUT unsigned* Errno - ) -{ - return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno); -} - - - -__inline -BOOLEAN -_SetPartType( - IN HANDLE Handle, - IN UCHAR Type - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return STATUS_SUCCESS == NtDeviceIoControlFile( - Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_PARTITION_INFO, - &Type, sizeof(Type), - NULL, 0); -} - - - -//--------------------- interface part - -// -// Interface functions. -// Is_mounted is set to 1 if the device is mounted, 0 otherwise -// - -errcode_t -ext2fs_check_if_mounted(const char *file, int *mount_flags) -{ - HANDLE h; - BOOLEAN Readonly; - - *mount_flags = 0; - - if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) - { - return 0; - } - - - __try{ - *mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0; - } - __finally{ - _CloseDisk(h); - } - - return 0; -} - - - -// -// Returns the number of blocks in a partition -// - -static __int64 FsSize = 0; -static char knowndevice[1024] = ""; - - -errcode_t -ext2fs_get_device_size(const char *file, int blocksize, - blk_t *retblocks) -{ - HANDLE h; - BOOLEAN Readonly; - - if((0 == FsSize) || (0 != strcmp(knowndevice, file))) - { - - if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) - { - return 0; - } - - - __try{ - - // - // Get size - // - - _GetDeviceSize(h, &FsSize); - strcpy(knowndevice, file); - } - __finally{ - _CloseDisk(h); - } - - } - - *retblocks = (blk_t)(unsigned __int64)(FsSize / blocksize); - UNREFERENCED_PARAMETER(file); - return 0; -} - - - - - - -// -// Table elements -// - - -static -errcode_t -nt_open(const char *name, int flags, io_channel *channel) -{ - io_channel io = NULL; - PNT_PRIVATE_DATA NtData = NULL; - errcode_t Errno = 0; - - // - // Check name - // - - if (NULL == name) - { - return EXT2_ET_BAD_DEVICE_NAME; - } - - __try{ - - // - // Allocate channel handle - // - - io = (io_channel) malloc(sizeof(struct struct_io_channel)); - - if (NULL == io) - { - Errno = ENOMEM; - __leave; - } - - RtlZeroMemory(io, sizeof(struct struct_io_channel)); - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - - NtData = (PNT_PRIVATE_DATA)malloc(sizeof(NT_PRIVATE_DATA)); - - if (NULL == NtData) - { - Errno = ENOMEM; - __leave; - } - - - io->manager = nt_io_manager(); - io->name = malloc(strlen(name) + 1); - if (NULL == io->name) - { - Errno = ENOMEM; - __leave; - } - - strcpy(io->name, name); - io->private_data = NtData; - io->block_size = 1024; - io->read_error = 0; - io->write_error = 0; - io->refcount = 1; - - // - // Initialize data - // - - RtlZeroMemory(NtData, sizeof(NT_PRIVATE_DATA)); - - NtData->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL; - NtData->BufferBlockNumber = 0xffffffff; - NtData->BufferSize = 1024; - NtData->Buffer = malloc(NtData->BufferSize); - - if (NULL == NtData->Buffer) - { - Errno = ENOMEM; - __leave; - } - - // - // Open it - // - - if(!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &NtData->Handle, &NtData->OpenedReadonly, &Errno)) - { - __leave; - } - - - // - // get size - // - - _GetDeviceSize(NtData->Handle, &FsSize); - strcpy(knowndevice, name); - - - // - // Lock/dismount - // - - if(!NT_SUCCESS(_LockDrive(NtData->Handle)) /*|| !NT_SUCCESS(_DismountDrive(NtData->Handle))*/) - { - NtData->OpenedReadonly = TRUE; - } - - // - // Done - // - - *channel = io; - - - } - __finally{ - - if(0 != Errno) - { - // - // Cleanup - // - - if (NULL != io) - { - if(NULL != io->name) - { - free(io->name); - } - - free(io); - } - - if (NULL != NtData) - { - if(NULL != NtData->Handle) - { - _UnlockDrive(NtData->Handle); - _CloseDisk(NtData->Handle); - } - - if(NULL != NtData->Buffer) - { - free(NtData->Buffer); - } - - free(NtData); - } - } - } - - return Errno; -} - - -// -// Close api -// - -static -errcode_t -nt_close(io_channel channel) -{ - PNT_PRIVATE_DATA NtData = NULL; - - if(NULL == channel) - { - return 0; - } - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if (--channel->refcount > 0) - { - return 0; - } - - if(NULL != channel->name) - { - free(channel->name); - } - - - free(channel); - - if (NULL != NtData) - { - if(NULL != NtData->Handle) - { - _DismountDrive(NtData->Handle); - _UnlockDrive(NtData->Handle); - _CloseDisk(NtData->Handle); - } - - if(NULL != NtData->Buffer) - { - free(NtData->Buffer); - } - - free(NtData); - } - - return 0; -} - - - -// -// set block size -// - -static -errcode_t -nt_set_blksize(io_channel channel, int blksize) -{ - PNT_PRIVATE_DATA NtData = NULL; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if (channel->block_size != blksize) - { - channel->block_size = blksize; - - free(NtData->Buffer); - NtData->BufferBlockNumber = 0xffffffff; - NtData->BufferSize = channel->block_size; - ASSERT(0 == (NtData->BufferSize % 512)); - - NtData->Buffer = malloc(NtData->BufferSize); - - if (NULL == NtData->Buffer) - { - return ENOMEM; - } - - } - - return 0; -} - - -// -// read block -// - -static -errcode_t -nt_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - PVOID BufferToRead; - ULONG SizeToRead; - ULONG Size; - LARGE_INTEGER Offset; - PNT_PRIVATE_DATA NtData = NULL; - unsigned Errno = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - // - // If it's in the cache, use it! - // - - if ((1 == count) && - (block == NtData->BufferBlockNumber) && - (NtData->BufferBlockNumber != 0xffffffff)) - { - memcpy(buf, NtData->Buffer, channel->block_size); - return 0; - } - - Size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size); - - Offset.QuadPart = block * channel->block_size; - - // - // If not fit to the block - // - - if(Size <= NtData->BufferSize) - { - // - // Update the cache - // - - NtData->BufferBlockNumber = block; - BufferToRead = NtData->Buffer; - SizeToRead = NtData->BufferSize; - } - else - { - SizeToRead = Size; - BufferToRead = buf; - ASSERT(0 == (SizeToRead % channel->block_size)); - } - - if(!_RawRead(NtData->Handle, Offset, SizeToRead, BufferToRead, &Errno)) - { - - if (channel->read_error) - { - return (channel->read_error)(channel, block, count, buf, - Size, 0, Errno); - } - else - { - return Errno; - } - } - - - if(BufferToRead != buf) - { - ASSERT(Size <= SizeToRead); - memcpy(buf, BufferToRead, Size); - } - - return 0; -} - - -// -// write block -// - -static -errcode_t -nt_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - ULONG SizeToWrite; - LARGE_INTEGER Offset; - PNT_PRIVATE_DATA NtData = NULL; - unsigned Errno = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if(NtData->OpenedReadonly) - { - return EACCES; - } - - if (count == 1) - { - SizeToWrite = channel->block_size; - } - else - { - NtData->BufferBlockNumber = 0xffffffff; - - if (count < 0) - { - SizeToWrite = (ULONG)(-count); - } - else - { - SizeToWrite = (ULONG)(count * channel->block_size); - } - } - - - ASSERT(0 == (SizeToWrite % 512)); - Offset.QuadPart = block * channel->block_size; - - if(!_RawWrite(NtData->Handle, Offset, SizeToWrite, buf, &Errno)) - { - if (channel->write_error) - { - return (channel->write_error)(channel, block, count, buf, - SizeToWrite, 0, Errno); - } - else - { - return Errno; - } - } - - - // - // Stash a copy. - // - - if(SizeToWrite >= NtData->BufferSize) - { - NtData->BufferBlockNumber = block; - memcpy(NtData->Buffer, buf, NtData->BufferSize); - } - - NtData->Written = TRUE; - - return 0; - -} - - - -// -// Flush data buffers to disk. Since we are currently using a -// write-through cache, this is a no-op. -// - -static -errcode_t -nt_flush(io_channel channel) -{ - PNT_PRIVATE_DATA NtData = NULL; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if(NtData->OpenedReadonly) - { - return 0; // EACCESS; - } - - - // - // Flush file buffers. - // - - _FlushDrive(NtData->Handle); - - - // - // Test and correct partition type. - // - - if(NtData->Written) - { - _SetPartType(NtData->Handle, 0x83); - } - - return 0; -} - - |