summaryrefslogtreecommitdiff
path: root/e2fslib/nt_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'e2fslib/nt_io.c')
-rw-r--r--e2fslib/nt_io.c1513
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;
-}
-
-