diff --git a/Ext4Fsd/ext3/recover.c b/Ext4Fsd/ext3/recover.c index 025ef97..37800df 100644 --- a/Ext4Fsd/ext3/recover.c +++ b/Ext4Fsd/ext3/recover.c @@ -105,8 +105,6 @@ Ext2RecoverJournal( journal_t * journal = NULL; struct ext3_super_block *esb; - DbgPrint("Ext2RecoverJournal begin\n"); - ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); /* check journal inode number */ @@ -130,7 +128,7 @@ Ext2RecoverJournal( /* initialzation succeeds ? */ if (!journal) { - DbgPrint("jbd2_journal_init_inode failed\n"); + DEBUG(DL_ERR, ( "jbd2_journal_init_inode failed\n")); iput(ji); rc = -8; goto errorout; @@ -141,8 +139,8 @@ Ext2RecoverJournal( rc = jbd2_journal_load(journal); if (0 != rc) { - DbgPrint("Ext2Fsd: recover_journal: failed " - "to recover journal data. rc=%d\n", rc); + DEBUG(DL_ERR, ( "Ext2Fsd: recover_journal: failed " + "to recover journal data. rc=%d\n", rc)); rc = -9; //goto errorout; } @@ -180,7 +178,5 @@ errorout: ExReleaseResourceLite(&Vcb->MainResource); - DbgPrint("Ext2RecoverJournal end\n"); - return rc; } diff --git a/Ext4Fsd/ext4/ext4_csum.c b/Ext4Fsd/ext4/ext4_csum.c index bf80fed..b7cb42a 100644 --- a/Ext4Fsd/ext4/ext4_csum.c +++ b/Ext4Fsd/ext4/ext4_csum.c @@ -419,7 +419,7 @@ int ext4_inode_csum_verify(struct inode *inode, struct ext4_inode *raw, calculated &= 0xFFFF; if (provided != calculated) - DbgPrint("checksum verify failed on inode %u: %lx != %lx\n", inode->i_ino, provided, calculated); + DEBUG(DL_ERR, ( "checksum verify failed on inode %u: %lx != %lx\n", inode->i_ino, provided, calculated)); return provided == calculated; } @@ -437,7 +437,6 @@ void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw, if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE && offsetof(struct ext4_inode, i_checksum_hi) + sizeof(raw->i_checksum_hi) <= EXT4_GOOD_OLD_INODE_SIZE + raw->i_extra_isize) raw->i_checksum_hi = cpu_to_le16(csum >> 16); - //DbgPrint("set checksum on inode %u: csum == %lx\n", inode->i_ino, csum); ext4_inode_csum_verify(inode, raw, unused); } @@ -547,7 +546,7 @@ int ext4_dirent_csum_verify(struct inode *inode, struct ext4_dir_entry *dirent) t = get_dirent_tail(inode, dirent); if (!t) { - DbgPrint("No space for directory leaf checksum. Please run e2fsck -D.\n"); + DEBUG(DL_ERR, ( "No space for directory leaf checksum. Please run e2fsck -D.\n")); return 0; } @@ -568,7 +567,7 @@ void ext4_dirent_csum_set(struct inode *inode, t = get_dirent_tail(inode, dirent); if (!t) { - DbgPrint("No space for directory leaf checksum. Please run e2fsck -D.\n"); + DEBUG(DL_ERR, ( "No space for directory leaf checksum. Please run e2fsck -D.\n")); return; } @@ -633,14 +632,14 @@ int ext4_dx_csum_verify(struct inode *inode, c = get_dx_countlimit(inode, dirent, &count_offset); if (!c) { - DbgPrint("dir seems corrupt? Run e2fsck -D."); + DEBUG(DL_ERR, ( "dir seems corrupt? Run e2fsck -D.")); return 0; } limit = le16_to_cpu(c->limit); count = le16_to_cpu(c->count); if (count_offset + (limit * sizeof(struct dx_entry)) > EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) { - DbgPrint("warn_no_space_for_csum in inode\n"); + DEBUG(DL_ERR, ( "warn_no_space_for_csum in inode\n")); return 0; } t = (struct dx_tail *)(((struct dx_entry *)c) + limit); @@ -659,14 +658,14 @@ void ext4_dx_csum_set(struct inode *inode, struct ext4_dir_entry *dirent) c = get_dx_countlimit(inode, dirent, &count_offset); if (!c) { - DbgPrint("dir seems corrupt? Run e2fsck -D."); + DEBUG(DL_ERR, ( "dir seems corrupt? Run e2fsck -D.")); return; } limit = le16_to_cpu(c->limit); count = le16_to_cpu(c->count); if (count_offset + (limit * sizeof(struct dx_entry)) > EXT4_BLOCK_SIZE(inode->i_sb) - sizeof(struct dx_tail)) { - DbgPrint("warn_no_space_for_csum in inode\n"); + DEBUG(DL_ERR, ( "warn_no_space_for_csum in inode\n")); return; } t = (struct dx_tail *)(((struct dx_entry *)c) + limit); diff --git a/Ext4Fsd/fsctl.c b/Ext4Fsd/fsctl.c index 5450766..f97d098 100644 --- a/Ext4Fsd/fsctl.c +++ b/Ext4Fsd/fsctl.c @@ -2225,7 +2225,7 @@ Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext) } if (!ext4_superblock_csum_verify(&Vcb->sb, Ext2Sb)) { - DbgPrint("Found ext4 filesystem with invalid superblock checksum. Run e2fsck?\n"); + DEBUG(DL_ERR, ( "Found ext4 filesystem with invalid superblock checksum. Run e2fsck?\n")); } SetLongFlag(Vcb->Flags, VCB_MOUNTED); diff --git a/Ext4Fsd/init.c b/Ext4Fsd/init.c index 44c9fb5..5ad4615 100644 --- a/Ext4Fsd/init.c +++ b/Ext4Fsd/init.c @@ -1,837 +1,837 @@ -/* - * COPYRIGHT: See COPYRIGHT.TXT - * PROJECT: Ext2 File System Driver for WinNT/2K/XP - * FILE: init.c - * PROGRAMMER: Matt Wu - * HOMEPAGE: http://www.ext2fsd.com - * UPDATE HISTORY: - */ - -/* INCLUDES *****************************************************************/ - -#include "ext2fs.h" - -/* GLOBALS ***************************************************************/ - -PEXT2_GLOBAL Ext2Global = NULL; - -/* - * Ext2Fsd version, building date/time - */ - -CHAR gVersion[] = EXT2FSD_VERSION; -CHAR gTime[] = __TIME__; -CHAR gDate[] = __DATE__; - - -/* DEFINITIONS ***********************************************************/ - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(INIT, Ext2QueryGlobalParameters) -#pragma alloc_text(INIT, Ext2QueryRegistrySettings) -#pragma alloc_text(INIT, DriverEntry) -#if EXT2_UNLOAD -#pragma alloc_text(PAGE, DriverUnload) -#endif -#endif - -/* FUNCTIONS ***************************************************************/ - -DECLARE_INIT(journal_init); -DECLARE_EXIT(journal_exit); - -#if EXT2_UNLOAD - -/* - * FUNCTION: Called by the system to unload the driver - * ARGUMENTS: - * DriverObject = object describing this driver - * RETURNS: None - */ - -VOID -DriverUnload (IN PDRIVER_OBJECT DriverObject) -{ - - UNICODE_STRING DosDeviceName; - - DEBUG(DL_FUN, ( "Ext2Fsd: Unloading routine.\n")); - - /* - * stop reaper thread ... - */ - - - /* - * removing memory allocations and objects - */ - - RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); - IoDeleteSymbolicLink(&DosDeviceName); - - Ext2UnloadAllNls(); - - ExDeleteResourceLite(&Ext2Global->Resource); - - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2DentryLookasideList)); - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2ExtLookasideList)); - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2McbLookasideList)); - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2CcbLookasideList)); - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList)); - ExDeleteNPagedLookasideList(&(Ext2Global->Ext2IrpContextLookasideList)); - - ObDereferenceObject(Ext2Global->DiskdevObject); - ObDereferenceObject(Ext2Global->CdromdevObject); - - /* cleanup journal related caches */ - UNLOAD_MODULE(journal_exit); - - /* cleanup linux lib */ - ext2_destroy_linux(); - - Ext2FreePool(Ext2Global, 'LG2E'); - Ext2Global = NULL; -} - -#endif - -NTSTATUS -Ext2RegistryQueryCallback( - IN PWSTR ValueName, - IN ULONG ValueType, - IN PVOID ValueData, - IN ULONG ValueLength, - IN PVOID Context, - IN PVOID EntryContext - ) -{ - ULONG i = 0; - BYTE *s, *t; - - if (NULL == ValueName || NULL == ValueData) - return STATUS_SUCCESS; - - if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(WRITING_SUPPORT) && - _wcsnicmp(ValueName, WRITING_SUPPORT, wcslen(WRITING_SUPPORT)) == 0) { - - if (ValueData && ValueLength == sizeof(DWORD)) { - if (*((PULONG)ValueData)) { - SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); - } else { - ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); - } - } - } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(CHECKING_BITMAP) && - _wcsnicmp(ValueName, CHECKING_BITMAP, wcslen(CHECKING_BITMAP)) == 0) { - - if (ValueData && ValueLength == sizeof(DWORD)) { - if (*((PULONG)ValueData)) { - SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); - } else { - ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); - } - } - } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(EXT3_FORCEWRITING) && - _wcsnicmp(ValueName, EXT3_FORCEWRITING, wcslen(EXT3_FORCEWRITING)) == 0) { - - if (ValueData && ValueLength == sizeof(DWORD)) { - if (*((PULONG)ValueData)) { - SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); - SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); - } else { - ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); - } - } - } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(AUTO_MOUNT) && - _wcsnicmp(ValueName, AUTO_MOUNT, wcslen(AUTO_MOUNT)) == 0) { - - if (ValueData && ValueLength == sizeof(DWORD)) { - if (*((PULONG)ValueData)) { - SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - } else { - ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - } - } - } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(CODEPAGE_NAME) && - _wcsnicmp(ValueName, CODEPAGE_NAME, wcslen(CODEPAGE_NAME)) == 0) { - - if (ValueData && ValueLength <= sizeof(WCHAR) * CODEPAGE_MAXLEN) { - RtlCopyMemory(&Ext2Global->Codepage.PageName[0], - ValueData, ValueLength); - } - } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_PREFIX) && - _wcsnicmp(ValueName, HIDING_PREFIX, wcslen(HIDING_PREFIX)) == 0) { - - if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) { - RtlCopyMemory(&Ext2Global->wHidingPrefix[0], - ValueData, ValueLength); - } - } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_SUFFIX) && - _wcsnicmp(ValueName, HIDING_SUFFIX, wcslen(HIDING_SUFFIX)) == 0) { - - if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) { - RtlCopyMemory(&Ext2Global->wHidingSuffix[0], - ValueData, ValueLength); - } - } - - - return STATUS_SUCCESS; -} - -NTSTATUS -Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[8]; - int i = 0; - NTSTATUS Status; - - RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 8); - - /* - * 1 writing support - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = WRITING_SUPPORT; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - /* - * 2 checking bitmap - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = CHECKING_BITMAP; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - /* - * 3 force writing - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = EXT3_FORCEWRITING; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - /* - * 4 automount - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = AUTO_MOUNT; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - /* - * 5 codepage - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = CODEPAGE_NAME; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - /* - * 6 hidden prefix - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = HIDING_PREFIX; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - - /* - * 7 hidden suffix - */ - QueryTable[i].Flags = 0; - QueryTable[i].Name = HIDING_SUFFIX; - QueryTable[i].DefaultType = REG_NONE; - QueryTable[i].DefaultLength = 0; - QueryTable[i].DefaultData = NULL; - QueryTable[i].EntryContext = NULL; - QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; - i++; - - Status = RtlQueryRegistryValues( - RTL_REGISTRY_ABSOLUTE, - RegistryPath->Buffer, - &QueryTable[0], - NULL, - NULL - ); - - return NT_SUCCESS(Status); -} - - -BOOLEAN -Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath) -{ - UNICODE_STRING ParameterPath; - UNICODE_STRING UniName; - ANSI_STRING AnsiName; - - ULONG WritingSupport = 0; - ULONG CheckingBitmap = 0; - ULONG Ext3ForceWriting = 0; - ULONG AutoMount = 0; - - WCHAR UniBuffer[CODEPAGE_MAXLEN]; - USHORT Buffer[HIDINGPAT_LEN]; - - NTSTATUS Status; - - ParameterPath.Length = 0; - ParameterPath.MaximumLength = - RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR); - ParameterPath.Buffer = - (PWSTR) Ext2AllocatePool( - PagedPool, - ParameterPath.MaximumLength, - 'LG2E' - ); - if (!ParameterPath.Buffer) { - DbgBreak(); - DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n")); - return FALSE; - } - - RtlCopyUnicodeString(&ParameterPath, RegistryPath); - RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY); - - /* enable automount of ext2/3/4 volumes */ - SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); - - /* query parameter settings from registry */ - Ext2QueryGlobalParameters(&ParameterPath); - - /* set global codepage settings */ - if (wcslen(&Ext2Global->Codepage.PageName[0])) { - UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->Codepage.PageName[0]); - UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR); - UniName.Buffer = &Ext2Global->Codepage.PageName[0]; - AnsiName.MaximumLength = CODEPAGE_MAXLEN; - AnsiName.Length = 0; - AnsiName.Buffer = &Ext2Global->Codepage.AnsiName[0]; - Status = RtlUnicodeStringToAnsiString( - &AnsiName, - &UniName, - FALSE); - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName)); - RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8); - } - } else { - DEBUG(DL_ERR, ( "Ext2QueryParameters: CodePage not specified.\n")); - RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8); - } - Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0; - - - /* set global hidden prefix pattern */ - if (wcslen(&Ext2Global->wHidingPrefix[0])) { - UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingPrefix[0]); - UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); - UniName.Buffer = &Ext2Global->wHidingPrefix[0]; - AnsiName.MaximumLength = HIDINGPAT_LEN; - AnsiName.Length = 0; - AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]); - - Status = RtlUnicodeStringToAnsiString( - &AnsiName, - &UniName, - FALSE); - if (NT_SUCCESS(Status)) { - Ext2Global->bHidingPrefix = TRUE; - } else { - DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingPrefix ...\n")); - } - } else { - DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix not specified.\n")); - } - Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0; - - - /* set global hidden suffix pattern */ - if (wcslen(&Ext2Global->wHidingSuffix[0])) { - UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingSuffix[0]); - UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); - UniName.Buffer = &Ext2Global->wHidingSuffix[0]; - AnsiName.MaximumLength = HIDINGPAT_LEN; - AnsiName.Length = 0; - AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]); - - Status = RtlUnicodeStringToAnsiString( - &AnsiName, - &UniName, - FALSE); - if (NT_SUCCESS(Status)) { - Ext2Global->bHidingSuffix = TRUE; - } else { - DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingSuffix ...\n")); - } - } else { - DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix not specified.\n")); - } - Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0; - - Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer; - Ext2Global->RegistryPath.Length = 0; - Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength; - RtlCopyUnicodeString(&Ext2Global->RegistryPath, RegistryPath); - RtlAppendUnicodeToString(&Ext2Global->RegistryPath, VOLUMES_KEY); - - return TRUE; -} - - -#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo) - -#define FsRtlIsLeadDbcsCharacter(DBCS_CHAR) ( \ - (BOOLEAN)((UCHAR)(DBCS_CHAR) < 0x80 ? FALSE : \ - (NLS_MB_CODE_PAGE_TAG && \ - (NLS_OEM_LEAD_BYTE_INFO[(UCHAR)(DBCS_CHAR)] != 0))) \ -) - -VOID -Ext2EresourceAlignmentChecking() -{ - /* Verify ERESOURCE alignment in structures */ - CL_ASSERT((FIELD_OFFSET(EXT2_GLOBAL, Resource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MainResource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, PagingIoResource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, FcbLock) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, PagingIoResource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_FCB, MainResource) & 7) == 0); - CL_ASSERT((FIELD_OFFSET(EXT2_FCB, PagingIoResource) & 7) == 0); -} - -/* - * NAME: DriverEntry - * FUNCTION: Called by the system to initalize the driver - * - * ARGUMENTS: - * DriverObject = object describing this driver - * RegistryPath = path to our configuration entries - * RETURNS: Success or failure - */ -NTSTATUS -DriverEntry ( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath -) -{ - PDEVICE_OBJECT DiskdevObject = NULL; - PDEVICE_OBJECT CdromdevObject = NULL; - UNICODE_STRING DeviceName; - UNICODE_STRING DosDeviceName; - - PFAST_IO_DISPATCH FastIoDispatch; - PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks; - - NTSTATUS Status; - - int rc = 0; - BOOLEAN linux_lib_inited = FALSE; - BOOLEAN journal_module_inited = FALSE; - - /* Verity super block ... */ - ASSERT(sizeof(EXT2_SUPER_BLOCK) == 1024); - ASSERT(FIELD_OFFSET(EXT2_SUPER_BLOCK, s_magic) == 56); - - DbgPrint( - "Ext2Fsd --" -#ifdef _WIN2K_TARGET_ - " Win2k --" -#endif - " Version " - EXT2FSD_VERSION -#if EXT2_DEBUG - " Checked" -#else - " Free" -#endif - " -- " - __DATE__ " " - __TIME__ ".\n"); - - DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n")); - - /* initialize winlib structures */ - if (ext2_init_linux()) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - linux_lib_inited = TRUE; - - /* initialize journal module structures */ - LOAD_MODULE(journal_init); - if (rc != 0) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - journal_module_inited = TRUE; - - /* allocate memory for Ext2Global */ - Ext2Global = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_GLOBAL), 'LG2E'); - if (!Ext2Global) { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto errorout; - } - - /* initialize Ext2Global */ - RtlZeroMemory(Ext2Global, sizeof(EXT2_GLOBAL)); - Ext2Global->Identifier.Type = EXT2FGD; - Ext2Global->Identifier.Size = sizeof(EXT2_GLOBAL); - - InitializeListHead(&(Ext2Global->VcbList)); - ExInitializeResourceLite(&(Ext2Global->Resource)); - - /* query registry settings */ - Ext2QueryRegistrySettings(RegistryPath); - - /* create Ext2Fsd cdrom fs deivce */ - RtlInitUnicodeString(&DeviceName, CDROM_NAME); - Status = IoCreateDevice( - DriverObject, - 0, - &DeviceName, - FILE_DEVICE_CD_ROM_FILE_SYSTEM, - 0, - FALSE, - &CdromdevObject ); - - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( "IoCreateDevice cdrom device object error.\n")); - goto errorout; - } - - /* create Ext2Fsd disk fs deivce */ - RtlInitUnicodeString(&DeviceName, DEVICE_NAME); - Status = IoCreateDevice( - DriverObject, - 0, - &DeviceName, - FILE_DEVICE_DISK_FILE_SYSTEM, - 0, - FALSE, - &DiskdevObject ); - - if (!NT_SUCCESS(Status)) { - DEBUG(DL_ERR, ( "IoCreateDevice disk device object error.\n")); - goto errorout; - } - - Status= Ext2StartReaper( - &Ext2Global->FcbReaper, - Ext2FcbReaperThread); - if (!NT_SUCCESS(Status)) { - goto errorout; - } - - /* start resource reaper thread */ - Status= Ext2StartReaper( - &Ext2Global->McbReaper, - Ext2McbReaperThread); - if (!NT_SUCCESS(Status)) { - Ext2StopReaper(&Ext2Global->FcbReaper); - goto errorout; - } - - Status= Ext2StartReaper( - &Ext2Global->bhReaper, - Ext2bhReaperThread); - if (!NT_SUCCESS(Status)) { - Ext2StopReaper(&Ext2Global->FcbReaper); - Ext2StopReaper(&Ext2Global->McbReaper); - goto errorout; - } - -#ifdef _PNP_POWER_ - DiskdevObject->DeviceObjectExtension->PowerControlNeeded = FALSE; - CdromdevObject->DeviceObjectExtension->PowerControlNeeded = FALSE; -#endif - - /* initializing */ - Ext2Global->DiskdevObject = DiskdevObject; - Ext2Global->CdromdevObject = CdromdevObject; - - DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_READ] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = Ext2BuildRequest; - DriverObject->MajorFunction[IRP_MJ_SET_EA] = Ext2BuildRequest; - - DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2BuildRequest; - -#if (_WIN32_WINNT >= 0x0500) - DriverObject->MajorFunction[IRP_MJ_PNP] = Ext2BuildRequest; -#endif //(_WIN32_WINNT >= 0x0500) - -#if EXT2_UNLOAD - DriverObject->DriverUnload = DriverUnload; -#else - DriverObject->DriverUnload = NULL; -#endif - - // - // Initialize the fast I/O entry points - // - - FastIoDispatch = &(Ext2Global->FastIoDispatch); - - FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); - FastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible; - FastIoDispatch->FastIoRead = Ext2FastIoRead; - FastIoDispatch->FastIoWrite = Ext2FastIoWrite; - FastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo; - FastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStandardInfo; - FastIoDispatch->FastIoLock = Ext2FastIoLock; - FastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle; - FastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll; - FastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey; - FastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetworkOpenInfo; - - FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite; - FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite; - FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite; - FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite; - FastIoDispatch->AcquireForCcFlush = Ext2AcquireFileForCcFlush; - FastIoDispatch->ReleaseForCcFlush = Ext2ReleaseFileForCcFlush; - FastIoDispatch->AcquireFileForNtCreateSection = Ext2AcquireForCreateSection; - FastIoDispatch->ReleaseFileForNtCreateSection = Ext2ReleaseForCreateSection; - - DriverObject->FastIoDispatch = FastIoDispatch; - - // - // initializing structure sizes for statistics - // 1 means flexible/not fixed for all allocations (for different volumes). - // - Ext2Global->PerfStat.Magic = EXT2_PERF_STAT_MAGIC; - Ext2Global->PerfStat.Version = EXT2_PERF_STAT_VER2; - Ext2Global->PerfStat.Length = sizeof(EXT2_PERF_STATISTICS_V2); - - Ext2Global->PerfStat.Unit.Slot[PS_IRP_CONTEXT] = sizeof(EXT2_IRP_CONTEXT); /* 0 */ - Ext2Global->PerfStat.Unit.Slot[PS_VCB] = sizeof(EXT2_VCB); /* 1 */ - Ext2Global->PerfStat.Unit.Slot[PS_FCB] = sizeof(EXT2_FCB); /* 2 */ - Ext2Global->PerfStat.Unit.Slot[PS_CCB] = sizeof(EXT2_CCB); /* 3 */ - Ext2Global->PerfStat.Unit.Slot[PS_MCB] = sizeof(EXT2_MCB); /* 4 */ - Ext2Global->PerfStat.Unit.Slot[PS_EXTENT] = sizeof(EXT2_EXTENT); /* 5 */ - Ext2Global->PerfStat.Unit.Slot[PS_RW_CONTEXT] = sizeof(EXT2_RW_CONTEXT); /* 6 */ - Ext2Global->PerfStat.Unit.Slot[PS_VPB] = sizeof(VPB); /* 7 */ - Ext2Global->PerfStat.Unit.Slot[PS_FILE_NAME] = 1; /* 8 */ - Ext2Global->PerfStat.Unit.Slot[PS_MCB_NAME] = 1; /* 9 */ - Ext2Global->PerfStat.Unit.Slot[PS_INODE_NAME] = 1; /* a */ - Ext2Global->PerfStat.Unit.Slot[PS_DIR_ENTRY] = sizeof(EXT2_DIR_ENTRY2); /* b */ - Ext2Global->PerfStat.Unit.Slot[PS_DIR_PATTERN] = 1; /* c */ - Ext2Global->PerfStat.Unit.Slot[PS_DISK_EVENT] = sizeof(KEVENT); /* d */ - Ext2Global->PerfStat.Unit.Slot[PS_DISK_BUFFER] = 1; /* e */ - Ext2Global->PerfStat.Unit.Slot[PS_BLOCK_DATA] = 1; /* f */ - Ext2Global->PerfStat.Unit.Slot[PS_EXT2_INODE] = 1; /* 10 */ - Ext2Global->PerfStat.Unit.Slot[PS_DENTRY] = sizeof(struct dentry); /* 11 */ - Ext2Global->PerfStat.Unit.Slot[PS_BUFF_HEAD] = sizeof(struct buffer_head); /* 12 */ - - switch ( MmQuerySystemSize() ) { - - case MmSmallSystem: - - Ext2Global->MaxDepth = 64; - break; - - case MmMediumSystem: - - Ext2Global->MaxDepth = 128; - break; - - case MmLargeSystem: - - Ext2Global->MaxDepth = 256; - break; - } - - // - // Initialize the Cache Manager callbacks - // - - CacheManagerCallbacks = &(Ext2Global->CacheManagerCallbacks); - CacheManagerCallbacks->AcquireForLazyWrite = Ext2AcquireForLazyWrite; - CacheManagerCallbacks->ReleaseFromLazyWrite = Ext2ReleaseFromLazyWrite; - CacheManagerCallbacks->AcquireForReadAhead = Ext2AcquireForReadAhead; - CacheManagerCallbacks->ReleaseFromReadAhead = Ext2ReleaseFromReadAhead; - - Ext2Global->CacheManagerNoOpCallbacks.AcquireForLazyWrite = Ext2NoOpAcquire; - Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = Ext2NoOpRelease; - Ext2Global->CacheManagerNoOpCallbacks.AcquireForReadAhead = Ext2NoOpAcquire; - Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = Ext2NoOpRelease; - - -#ifndef _WIN2K_TARGET_ - // - // Initialize FS Filter callbacks - // - - RtlZeroMemory(&Ext2Global->FilterCallbacks, sizeof(FS_FILTER_CALLBACKS)); - Ext2Global->FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS); - Ext2Global->FilterCallbacks.PreAcquireForSectionSynchronization = Ext2PreAcquireForCreateSection; - FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &Ext2Global->FilterCallbacks ); - -#endif - - // - // Initialize the global data - // - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2IrpContextLookasideList), - NULL, - NULL, - 0, - sizeof(EXT2_IRP_CONTEXT), - 'PRIE', - 0 ); - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2FcbLookasideList), - NULL, - NULL, - 0, - sizeof(EXT2_FCB), - 'BCFE', - 0 ); - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2CcbLookasideList), - NULL, - NULL, - 0, - sizeof(EXT2_CCB), - 'BCCE', - 0 ); - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2McbLookasideList), - NULL, - NULL, - 0, - sizeof(EXT2_MCB), - 'BCME', - 0 ); - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2ExtLookasideList), - NULL, - NULL, - 0, - sizeof(EXT2_EXTENT), - 'STXE', - 0 ); - - ExInitializeNPagedLookasideList( &(Ext2Global->Ext2DentryLookasideList), - NULL, - NULL, - 0, - sizeof(struct dentry), - 'TNED', - 0 ); - - RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); - IoCreateSymbolicLink(&DosDeviceName, &DeviceName); - -#if EXT2_DEBUG - ProcessNameOffset = Ext2GetProcessNameOffset(); -#endif - - Ext2LoadAllNls(); - - Ext2Global->Codepage.PageTable = - load_nls(Ext2Global->Codepage.AnsiName); - - /* register file system devices for disk and cdrom */ - IoRegisterFileSystem(DiskdevObject); - ObReferenceObject(DiskdevObject); - - IoRegisterFileSystem(CdromdevObject); - ObReferenceObject(CdromdevObject); - -errorout: - - if (!NT_SUCCESS(Status)) { - - /* - * stop reaper thread ... - */ - - - /* - * cleanup resources ... - */ - - if (Ext2Global) { - ExDeleteResourceLite(&Ext2Global->Resource); - Ext2FreePool(Ext2Global, 'LG2E'); - } - - if (CdromdevObject) { - IoDeleteDevice(CdromdevObject); - } - - if (DiskdevObject) { - IoDeleteDevice(DiskdevObject); - } - - if (journal_module_inited) { - /* cleanup journal related caches */ - UNLOAD_MODULE(journal_exit); - } - - if (linux_lib_inited) { - /* cleanup linux lib */ - ext2_destroy_linux(); - } - } - - return Status; -} +/* + * COPYRIGHT: See COPYRIGHT.TXT + * PROJECT: Ext2 File System Driver for WinNT/2K/XP + * FILE: init.c + * PROGRAMMER: Matt Wu + * HOMEPAGE: http://www.ext2fsd.com + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include "ext2fs.h" + +/* GLOBALS ***************************************************************/ + +PEXT2_GLOBAL Ext2Global = NULL; + +/* + * Ext2Fsd version, building date/time + */ + +CHAR gVersion[] = EXT2FSD_VERSION; +CHAR gTime[] = __TIME__; +CHAR gDate[] = __DATE__; + + +/* DEFINITIONS ***********************************************************/ + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, Ext2QueryGlobalParameters) +#pragma alloc_text(INIT, Ext2QueryRegistrySettings) +#pragma alloc_text(INIT, DriverEntry) +#if EXT2_UNLOAD +#pragma alloc_text(PAGE, DriverUnload) +#endif +#endif + +/* FUNCTIONS ***************************************************************/ + +DECLARE_INIT(journal_init); +DECLARE_EXIT(journal_exit); + +#if EXT2_UNLOAD + +/* + * FUNCTION: Called by the system to unload the driver + * ARGUMENTS: + * DriverObject = object describing this driver + * RETURNS: None + */ + +VOID +DriverUnload (IN PDRIVER_OBJECT DriverObject) +{ + + UNICODE_STRING DosDeviceName; + + DEBUG(DL_FUN, ( "Ext2Fsd: Unloading routine.\n")); + + /* + * stop reaper thread ... + */ + + + /* + * removing memory allocations and objects + */ + + RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); + IoDeleteSymbolicLink(&DosDeviceName); + + Ext2UnloadAllNls(); + + ExDeleteResourceLite(&Ext2Global->Resource); + + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2DentryLookasideList)); + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2ExtLookasideList)); + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2McbLookasideList)); + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2CcbLookasideList)); + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2FcbLookasideList)); + ExDeleteNPagedLookasideList(&(Ext2Global->Ext2IrpContextLookasideList)); + + ObDereferenceObject(Ext2Global->DiskdevObject); + ObDereferenceObject(Ext2Global->CdromdevObject); + + /* cleanup journal related caches */ + UNLOAD_MODULE(journal_exit); + + /* cleanup linux lib */ + ext2_destroy_linux(); + + Ext2FreePool(Ext2Global, 'LG2E'); + Ext2Global = NULL; +} + +#endif + +NTSTATUS +Ext2RegistryQueryCallback( + IN PWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength, + IN PVOID Context, + IN PVOID EntryContext + ) +{ + ULONG i = 0; + BYTE *s, *t; + + if (NULL == ValueName || NULL == ValueData) + return STATUS_SUCCESS; + + if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(WRITING_SUPPORT) && + _wcsnicmp(ValueName, WRITING_SUPPORT, wcslen(WRITING_SUPPORT)) == 0) { + + if (ValueData && ValueLength == sizeof(DWORD)) { + if (*((PULONG)ValueData)) { + SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); + } else { + ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); + } + } + } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(CHECKING_BITMAP) && + _wcsnicmp(ValueName, CHECKING_BITMAP, wcslen(CHECKING_BITMAP)) == 0) { + + if (ValueData && ValueLength == sizeof(DWORD)) { + if (*((PULONG)ValueData)) { + SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); + } else { + ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); + } + } + } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(EXT3_FORCEWRITING) && + _wcsnicmp(ValueName, EXT3_FORCEWRITING, wcslen(EXT3_FORCEWRITING)) == 0) { + + if (ValueData && ValueLength == sizeof(DWORD)) { + if (*((PULONG)ValueData)) { + SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); + SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); + } else { + ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); + } + } + } else if (ValueType == REG_DWORD && wcslen(ValueName) == wcslen(AUTO_MOUNT) && + _wcsnicmp(ValueName, AUTO_MOUNT, wcslen(AUTO_MOUNT)) == 0) { + + if (ValueData && ValueLength == sizeof(DWORD)) { + if (*((PULONG)ValueData)) { + SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + } else { + ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + } + } + } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(CODEPAGE_NAME) && + _wcsnicmp(ValueName, CODEPAGE_NAME, wcslen(CODEPAGE_NAME)) == 0) { + + if (ValueData && ValueLength <= sizeof(WCHAR) * CODEPAGE_MAXLEN) { + RtlCopyMemory(&Ext2Global->Codepage.PageName[0], + ValueData, ValueLength); + } + } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_PREFIX) && + _wcsnicmp(ValueName, HIDING_PREFIX, wcslen(HIDING_PREFIX)) == 0) { + + if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) { + RtlCopyMemory(&Ext2Global->wHidingPrefix[0], + ValueData, ValueLength); + } + } else if (ValueType == REG_SZ && wcslen(ValueName) == wcslen(HIDING_SUFFIX) && + _wcsnicmp(ValueName, HIDING_SUFFIX, wcslen(HIDING_SUFFIX)) == 0) { + + if (ValueData && ValueLength <= sizeof(WCHAR) * HIDINGPAT_LEN) { + RtlCopyMemory(&Ext2Global->wHidingSuffix[0], + ValueData, ValueLength); + } + } + + + return STATUS_SUCCESS; +} + +NTSTATUS +Ext2QueryGlobalParameters(IN PUNICODE_STRING RegistryPath) +{ + RTL_QUERY_REGISTRY_TABLE QueryTable[8]; + int i = 0; + NTSTATUS Status; + + RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 8); + + /* + * 1 writing support + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = WRITING_SUPPORT; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + /* + * 2 checking bitmap + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = CHECKING_BITMAP; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + /* + * 3 force writing + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = EXT3_FORCEWRITING; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + /* + * 4 automount + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = AUTO_MOUNT; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + /* + * 5 codepage + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = CODEPAGE_NAME; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + /* + * 6 hidden prefix + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = HIDING_PREFIX; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + + /* + * 7 hidden suffix + */ + QueryTable[i].Flags = 0; + QueryTable[i].Name = HIDING_SUFFIX; + QueryTable[i].DefaultType = REG_NONE; + QueryTable[i].DefaultLength = 0; + QueryTable[i].DefaultData = NULL; + QueryTable[i].EntryContext = NULL; + QueryTable[i].QueryRoutine = Ext2RegistryQueryCallback; + i++; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + RegistryPath->Buffer, + &QueryTable[0], + NULL, + NULL + ); + + return NT_SUCCESS(Status); +} + + +BOOLEAN +Ext2QueryRegistrySettings(IN PUNICODE_STRING RegistryPath) +{ + UNICODE_STRING ParameterPath; + UNICODE_STRING UniName; + ANSI_STRING AnsiName; + + ULONG WritingSupport = 0; + ULONG CheckingBitmap = 0; + ULONG Ext3ForceWriting = 0; + ULONG AutoMount = 0; + + WCHAR UniBuffer[CODEPAGE_MAXLEN]; + USHORT Buffer[HIDINGPAT_LEN]; + + NTSTATUS Status; + + ParameterPath.Length = 0; + ParameterPath.MaximumLength = + RegistryPath->Length + sizeof(PARAMETERS_KEY) + sizeof(WCHAR); + ParameterPath.Buffer = + (PWSTR) Ext2AllocatePool( + PagedPool, + ParameterPath.MaximumLength, + 'LG2E' + ); + if (!ParameterPath.Buffer) { + DbgBreak(); + DEBUG(DL_ERR, ( "Ex2QueryParameters: failed to allocate Parameters...\n")); + return FALSE; + } + + RtlCopyUnicodeString(&ParameterPath, RegistryPath); + RtlAppendUnicodeToString(&ParameterPath, PARAMETERS_KEY); + + /* enable automount of ext2/3/4 volumes */ + SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); + + /* query parameter settings from registry */ + Ext2QueryGlobalParameters(&ParameterPath); + + /* set global codepage settings */ + if (wcslen(&Ext2Global->Codepage.PageName[0])) { + UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->Codepage.PageName[0]); + UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR); + UniName.Buffer = &Ext2Global->Codepage.PageName[0]; + AnsiName.MaximumLength = CODEPAGE_MAXLEN; + AnsiName.Length = 0; + AnsiName.Buffer = &Ext2Global->Codepage.AnsiName[0]; + Status = RtlUnicodeStringToAnsiString( + &AnsiName, + &UniName, + FALSE); + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong CodePage %wZ ...\n", &UniName)); + RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8); + } + } else { + DEBUG(DL_ERR, ( "Ext2QueryParameters: CodePage not specified.\n")); + RtlCopyMemory(&(Ext2Global->Codepage.AnsiName[0]),"default\0", 8); + } + Ext2Global->Codepage.AnsiName[CODEPAGE_MAXLEN - 1] = 0; + + + /* set global hidden prefix pattern */ + if (wcslen(&Ext2Global->wHidingPrefix[0])) { + UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingPrefix[0]); + UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); + UniName.Buffer = &Ext2Global->wHidingPrefix[0]; + AnsiName.MaximumLength = HIDINGPAT_LEN; + AnsiName.Length = 0; + AnsiName.Buffer = &(Ext2Global->sHidingPrefix[0]); + + Status = RtlUnicodeStringToAnsiString( + &AnsiName, + &UniName, + FALSE); + if (NT_SUCCESS(Status)) { + Ext2Global->bHidingPrefix = TRUE; + } else { + DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingPrefix ...\n")); + } + } else { + DEBUG(DL_INF, ( "Ext2QueryParameters: HidingPrefix not specified.\n")); + } + Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0; + + + /* set global hidden suffix pattern */ + if (wcslen(&Ext2Global->wHidingSuffix[0])) { + UniName.Length = sizeof(WCHAR) * wcslen(&Ext2Global->wHidingSuffix[0]); + UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); + UniName.Buffer = &Ext2Global->wHidingSuffix[0]; + AnsiName.MaximumLength = HIDINGPAT_LEN; + AnsiName.Length = 0; + AnsiName.Buffer = &(Ext2Global->sHidingSuffix[0]); + + Status = RtlUnicodeStringToAnsiString( + &AnsiName, + &UniName, + FALSE); + if (NT_SUCCESS(Status)) { + Ext2Global->bHidingSuffix = TRUE; + } else { + DEBUG(DL_ERR, ( "Ext2QueryParameters: Wrong HidingSuffix ...\n")); + } + } else { + DEBUG(DL_INF, ( "Ext2QueryParameters: HidingSuffix not specified.\n")); + } + Ext2Global->sHidingPrefix[HIDINGPAT_LEN - 1] = 0; + + Ext2Global->RegistryPath.Buffer = ParameterPath.Buffer; + Ext2Global->RegistryPath.Length = 0; + Ext2Global->RegistryPath.MaximumLength = ParameterPath.MaximumLength; + RtlCopyUnicodeString(&Ext2Global->RegistryPath, RegistryPath); + RtlAppendUnicodeToString(&Ext2Global->RegistryPath, VOLUMES_KEY); + + return TRUE; +} + + +#define NLS_OEM_LEAD_BYTE_INFO (*NlsOemLeadByteInfo) + +#define FsRtlIsLeadDbcsCharacter(DBCS_CHAR) ( \ + (BOOLEAN)((UCHAR)(DBCS_CHAR) < 0x80 ? FALSE : \ + (NLS_MB_CODE_PAGE_TAG && \ + (NLS_OEM_LEAD_BYTE_INFO[(UCHAR)(DBCS_CHAR)] != 0))) \ +) + +VOID +Ext2EresourceAlignmentChecking() +{ + /* Verify ERESOURCE alignment in structures */ + CL_ASSERT((FIELD_OFFSET(EXT2_GLOBAL, Resource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MainResource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, PagingIoResource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaInode) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, MetaBlock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, McbLock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, FcbLock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, bd.bd_bh_lock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_VCB, sbi.s_gd_lock) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, MainResource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_FCBVCB, PagingIoResource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_FCB, MainResource) & 7) == 0); + CL_ASSERT((FIELD_OFFSET(EXT2_FCB, PagingIoResource) & 7) == 0); +} + +/* + * NAME: DriverEntry + * FUNCTION: Called by the system to initalize the driver + * + * ARGUMENTS: + * DriverObject = object describing this driver + * RegistryPath = path to our configuration entries + * RETURNS: Success or failure + */ +NTSTATUS +DriverEntry ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath +) +{ + PDEVICE_OBJECT DiskdevObject = NULL; + PDEVICE_OBJECT CdromdevObject = NULL; + UNICODE_STRING DeviceName; + UNICODE_STRING DosDeviceName; + + PFAST_IO_DISPATCH FastIoDispatch; + PCACHE_MANAGER_CALLBACKS CacheManagerCallbacks; + + NTSTATUS Status; + + int rc = 0; + BOOLEAN linux_lib_inited = FALSE; + BOOLEAN journal_module_inited = FALSE; + + /* Verity super block ... */ + ASSERT(sizeof(EXT2_SUPER_BLOCK) == 1024); + ASSERT(FIELD_OFFSET(EXT2_SUPER_BLOCK, s_magic) == 56); + + DbgPrint( + "Ext2Fsd --" +#ifdef _WIN2K_TARGET_ + " Win2k --" +#endif + " Version " + EXT2FSD_VERSION +#if EXT2_DEBUG + " Checked" +#else + " Free" +#endif + " -- " + __DATE__ " " + __TIME__ ".\n"); + + DEBUG(DL_FUN, ( "Ext2 DriverEntry ...\n")); + + /* initialize winlib structures */ + if (ext2_init_linux()) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + linux_lib_inited = TRUE; + + /* initialize journal module structures */ + LOAD_MODULE(journal_init); + if (rc != 0) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + journal_module_inited = TRUE; + + /* allocate memory for Ext2Global */ + Ext2Global = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_GLOBAL), 'LG2E'); + if (!Ext2Global) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto errorout; + } + + /* initialize Ext2Global */ + RtlZeroMemory(Ext2Global, sizeof(EXT2_GLOBAL)); + Ext2Global->Identifier.Type = EXT2FGD; + Ext2Global->Identifier.Size = sizeof(EXT2_GLOBAL); + + InitializeListHead(&(Ext2Global->VcbList)); + ExInitializeResourceLite(&(Ext2Global->Resource)); + + /* query registry settings */ + Ext2QueryRegistrySettings(RegistryPath); + + /* create Ext2Fsd cdrom fs deivce */ + RtlInitUnicodeString(&DeviceName, CDROM_NAME); + Status = IoCreateDevice( + DriverObject, + 0, + &DeviceName, + FILE_DEVICE_CD_ROM_FILE_SYSTEM, + 0, + FALSE, + &CdromdevObject ); + + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( "IoCreateDevice cdrom device object error.\n")); + goto errorout; + } + + /* create Ext2Fsd disk fs deivce */ + RtlInitUnicodeString(&DeviceName, DEVICE_NAME); + Status = IoCreateDevice( + DriverObject, + 0, + &DeviceName, + FILE_DEVICE_DISK_FILE_SYSTEM, + 0, + FALSE, + &DiskdevObject ); + + if (!NT_SUCCESS(Status)) { + DEBUG(DL_ERR, ( "IoCreateDevice disk device object error.\n")); + goto errorout; + } + + Status= Ext2StartReaper( + &Ext2Global->FcbReaper, + Ext2FcbReaperThread); + if (!NT_SUCCESS(Status)) { + goto errorout; + } + + /* start resource reaper thread */ + Status= Ext2StartReaper( + &Ext2Global->McbReaper, + Ext2McbReaperThread); + if (!NT_SUCCESS(Status)) { + Ext2StopReaper(&Ext2Global->FcbReaper); + goto errorout; + } + + Status= Ext2StartReaper( + &Ext2Global->bhReaper, + Ext2bhReaperThread); + if (!NT_SUCCESS(Status)) { + Ext2StopReaper(&Ext2Global->FcbReaper); + Ext2StopReaper(&Ext2Global->McbReaper); + goto errorout; + } + +#ifdef _PNP_POWER_ + DiskdevObject->DeviceObjectExtension->PowerControlNeeded = FALSE; + CdromdevObject->DeviceObjectExtension->PowerControlNeeded = FALSE; +#endif + + /* initializing */ + Ext2Global->DiskdevObject = DiskdevObject; + Ext2Global->CdromdevObject = CdromdevObject; + + DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_READ] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = Ext2BuildRequest; + DriverObject->MajorFunction[IRP_MJ_SET_EA] = Ext2BuildRequest; + + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Ext2BuildRequest; + +#if (_WIN32_WINNT >= 0x0500) + DriverObject->MajorFunction[IRP_MJ_PNP] = Ext2BuildRequest; +#endif //(_WIN32_WINNT >= 0x0500) + +#if EXT2_UNLOAD + DriverObject->DriverUnload = DriverUnload; +#else + DriverObject->DriverUnload = NULL; +#endif + + // + // Initialize the fast I/O entry points + // + + FastIoDispatch = &(Ext2Global->FastIoDispatch); + + FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); + FastIoDispatch->FastIoCheckIfPossible = Ext2FastIoCheckIfPossible; + FastIoDispatch->FastIoRead = Ext2FastIoRead; + FastIoDispatch->FastIoWrite = Ext2FastIoWrite; + FastIoDispatch->FastIoQueryBasicInfo = Ext2FastIoQueryBasicInfo; + FastIoDispatch->FastIoQueryStandardInfo = Ext2FastIoQueryStandardInfo; + FastIoDispatch->FastIoLock = Ext2FastIoLock; + FastIoDispatch->FastIoUnlockSingle = Ext2FastIoUnlockSingle; + FastIoDispatch->FastIoUnlockAll = Ext2FastIoUnlockAll; + FastIoDispatch->FastIoUnlockAllByKey = Ext2FastIoUnlockAllByKey; + FastIoDispatch->FastIoQueryNetworkOpenInfo = Ext2FastIoQueryNetworkOpenInfo; + + FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite; + FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite; + FastIoDispatch->AcquireForModWrite = Ext2AcquireFileForModWrite; + FastIoDispatch->ReleaseForModWrite = Ext2ReleaseFileForModWrite; + FastIoDispatch->AcquireForCcFlush = Ext2AcquireFileForCcFlush; + FastIoDispatch->ReleaseForCcFlush = Ext2ReleaseFileForCcFlush; + FastIoDispatch->AcquireFileForNtCreateSection = Ext2AcquireForCreateSection; + FastIoDispatch->ReleaseFileForNtCreateSection = Ext2ReleaseForCreateSection; + + DriverObject->FastIoDispatch = FastIoDispatch; + + // + // initializing structure sizes for statistics + // 1 means flexible/not fixed for all allocations (for different volumes). + // + Ext2Global->PerfStat.Magic = EXT2_PERF_STAT_MAGIC; + Ext2Global->PerfStat.Version = EXT2_PERF_STAT_VER2; + Ext2Global->PerfStat.Length = sizeof(EXT2_PERF_STATISTICS_V2); + + Ext2Global->PerfStat.Unit.Slot[PS_IRP_CONTEXT] = sizeof(EXT2_IRP_CONTEXT); /* 0 */ + Ext2Global->PerfStat.Unit.Slot[PS_VCB] = sizeof(EXT2_VCB); /* 1 */ + Ext2Global->PerfStat.Unit.Slot[PS_FCB] = sizeof(EXT2_FCB); /* 2 */ + Ext2Global->PerfStat.Unit.Slot[PS_CCB] = sizeof(EXT2_CCB); /* 3 */ + Ext2Global->PerfStat.Unit.Slot[PS_MCB] = sizeof(EXT2_MCB); /* 4 */ + Ext2Global->PerfStat.Unit.Slot[PS_EXTENT] = sizeof(EXT2_EXTENT); /* 5 */ + Ext2Global->PerfStat.Unit.Slot[PS_RW_CONTEXT] = sizeof(EXT2_RW_CONTEXT); /* 6 */ + Ext2Global->PerfStat.Unit.Slot[PS_VPB] = sizeof(VPB); /* 7 */ + Ext2Global->PerfStat.Unit.Slot[PS_FILE_NAME] = 1; /* 8 */ + Ext2Global->PerfStat.Unit.Slot[PS_MCB_NAME] = 1; /* 9 */ + Ext2Global->PerfStat.Unit.Slot[PS_INODE_NAME] = 1; /* a */ + Ext2Global->PerfStat.Unit.Slot[PS_DIR_ENTRY] = sizeof(EXT2_DIR_ENTRY2); /* b */ + Ext2Global->PerfStat.Unit.Slot[PS_DIR_PATTERN] = 1; /* c */ + Ext2Global->PerfStat.Unit.Slot[PS_DISK_EVENT] = sizeof(KEVENT); /* d */ + Ext2Global->PerfStat.Unit.Slot[PS_DISK_BUFFER] = 1; /* e */ + Ext2Global->PerfStat.Unit.Slot[PS_BLOCK_DATA] = 1; /* f */ + Ext2Global->PerfStat.Unit.Slot[PS_EXT2_INODE] = 1; /* 10 */ + Ext2Global->PerfStat.Unit.Slot[PS_DENTRY] = sizeof(struct dentry); /* 11 */ + Ext2Global->PerfStat.Unit.Slot[PS_BUFF_HEAD] = sizeof(struct buffer_head); /* 12 */ + + switch ( MmQuerySystemSize() ) { + + case MmSmallSystem: + + Ext2Global->MaxDepth = 64; + break; + + case MmMediumSystem: + + Ext2Global->MaxDepth = 128; + break; + + case MmLargeSystem: + + Ext2Global->MaxDepth = 256; + break; + } + + // + // Initialize the Cache Manager callbacks + // + + CacheManagerCallbacks = &(Ext2Global->CacheManagerCallbacks); + CacheManagerCallbacks->AcquireForLazyWrite = Ext2AcquireForLazyWrite; + CacheManagerCallbacks->ReleaseFromLazyWrite = Ext2ReleaseFromLazyWrite; + CacheManagerCallbacks->AcquireForReadAhead = Ext2AcquireForReadAhead; + CacheManagerCallbacks->ReleaseFromReadAhead = Ext2ReleaseFromReadAhead; + + Ext2Global->CacheManagerNoOpCallbacks.AcquireForLazyWrite = Ext2NoOpAcquire; + Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = Ext2NoOpRelease; + Ext2Global->CacheManagerNoOpCallbacks.AcquireForReadAhead = Ext2NoOpAcquire; + Ext2Global->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = Ext2NoOpRelease; + + +#ifndef _WIN2K_TARGET_ + // + // Initialize FS Filter callbacks + // + + RtlZeroMemory(&Ext2Global->FilterCallbacks, sizeof(FS_FILTER_CALLBACKS)); + Ext2Global->FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS); + Ext2Global->FilterCallbacks.PreAcquireForSectionSynchronization = Ext2PreAcquireForCreateSection; + FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &Ext2Global->FilterCallbacks ); + +#endif + + // + // Initialize the global data + // + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2IrpContextLookasideList), + NULL, + NULL, + 0, + sizeof(EXT2_IRP_CONTEXT), + 'PRIE', + 0 ); + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2FcbLookasideList), + NULL, + NULL, + 0, + sizeof(EXT2_FCB), + 'BCFE', + 0 ); + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2CcbLookasideList), + NULL, + NULL, + 0, + sizeof(EXT2_CCB), + 'BCCE', + 0 ); + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2McbLookasideList), + NULL, + NULL, + 0, + sizeof(EXT2_MCB), + 'BCME', + 0 ); + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2ExtLookasideList), + NULL, + NULL, + 0, + sizeof(EXT2_EXTENT), + 'STXE', + 0 ); + + ExInitializeNPagedLookasideList( &(Ext2Global->Ext2DentryLookasideList), + NULL, + NULL, + 0, + sizeof(struct dentry), + 'TNED', + 0 ); + + RtlInitUnicodeString(&DosDeviceName, DOS_DEVICE_NAME); + IoCreateSymbolicLink(&DosDeviceName, &DeviceName); + +#if EXT2_DEBUG + ProcessNameOffset = Ext2GetProcessNameOffset(); +#endif + + Ext2LoadAllNls(); + + Ext2Global->Codepage.PageTable = + load_nls(Ext2Global->Codepage.AnsiName); + + /* register file system devices for disk and cdrom */ + IoRegisterFileSystem(DiskdevObject); + ObReferenceObject(DiskdevObject); + + IoRegisterFileSystem(CdromdevObject); + ObReferenceObject(CdromdevObject); + +errorout: + + if (!NT_SUCCESS(Status)) { + + /* + * stop reaper thread ... + */ + + + /* + * cleanup resources ... + */ + + if (Ext2Global) { + ExDeleteResourceLite(&Ext2Global->Resource); + Ext2FreePool(Ext2Global, 'LG2E'); + } + + if (CdromdevObject) { + IoDeleteDevice(CdromdevObject); + } + + if (DiskdevObject) { + IoDeleteDevice(DiskdevObject); + } + + if (journal_module_inited) { + /* cleanup journal related caches */ + UNLOAD_MODULE(journal_exit); + } + + if (linux_lib_inited) { + /* cleanup linux lib */ + ext2_destroy_linux(); + } + } + + return Status; +} diff --git a/README.md b/README.md index b266bfc..717e3e8 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ About still install the oficial release and then copy this driver over the old in \windows\system32\drivers. The current status of the development is that all metadata checksums is implemented and jbd2 is ported to support 64-bit blocknumbers. + The driver is now ready to be tested! This work is dedicated to my mother Berit Ingegerd Branten. Bo Branten @@ -35,6 +36,9 @@ Active Developers KaHo Ng : http://github.com/ngkaho1234 + Bo Branten : http://github.com/bobranten + http://www.acc.umu.se/~bosse + Supported Features by Ext3Fsd -----------------------------