INT Ext2CheckJournal( PEXT2_VCB Vcb, PULONG jNo ) { struct ext3_super_block* esb = NULL; /* check ext3 super block */ esb = (struct ext3_super_block *)Vcb->SuperBlock; if (IsFlagOn(esb->s_feature_incompat, EXT3_FEATURE_INCOMPAT_RECOVER)) { SetLongFlag(Vcb->Flags, VCB_JOURNAL_RECOVER); } /* must stop here if volume is read-only */ if (IsVcbReadOnly(Vcb)) { goto errorout; } /* journal is external ? */ if (esb->s_journal_inum == 0) { goto errorout; } /* oops: volume is corrupted */ if (esb->s_journal_dev) { goto errorout; } /* return the journal inode number */ *jNo = esb->s_journal_inum; return TRUE; errorout: return FALSE; }
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; }
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 Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext) { PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; PFILE_OBJECT FileObject = NULL; PDEVICE_OBJECT DeviceObject = NULL; PIRP Irp = NULL; PIO_STACK_LOCATION IoStackLocation = NULL; PUCHAR Buffer = NULL; LARGE_INTEGER ByteOffset; ULONG ReturnedLength = 0; ULONG Length; NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN OpPostIrp = FALSE; BOOLEAN PagingIo = FALSE; BOOLEAN Nocache = FALSE; BOOLEAN SynchronousIo = FALSE; BOOLEAN RecursiveWriteThrough = FALSE; BOOLEAN MainResourceAcquired = FALSE; BOOLEAN PagingIoResourceAcquired = FALSE; BOOLEAN bDeferred = FALSE; BOOLEAN UpdateFileValidSize = FALSE; BOOLEAN FileSizesChanged = FALSE; BOOLEAN rc; __try { ASSERT(IrpContext); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext; Ccb = (PEXT2_CCB) FileObject->FsContext2; ASSERT(Fcb); ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); Length = IoStackLocation->Parameters.Write.Length; ByteOffset = IoStackLocation->Parameters.Write.ByteOffset; PagingIo = IsFlagOn(Irp->Flags, IRP_PAGING_IO); Nocache = IsFlagOn(Irp->Flags, IRP_NOCACHE); SynchronousIo = IsFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); if (PagingIo) { ASSERT(Nocache); } DEBUG(DL_INF, ("Ext2WriteFile: %wZ Offset=%I64xh Length=%xh Paging=%xh Nocache=%xh\n", &Fcb->Mcb->ShortName, ByteOffset.QuadPart, Length, PagingIo, Nocache)); if (IsSpecialFile(Fcb) || IsInodeSymLink(Fcb->Inode) ) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } if (IsFileDeleted(Fcb->Mcb) || (IsSymLink(Fcb) && IsFileDeleted(Fcb->Mcb->Target)) ) { Status = STATUS_FILE_DELETED; __leave; } if (Length == 0) { Irp->IoStatus.Information = 0; Status = STATUS_SUCCESS; __leave; } if (ByteOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && ByteOffset.HighPart == -1) { ByteOffset = FileObject->CurrentByteOffset; } else if (IsWritingToEof(ByteOffset)) { ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart; } if (Nocache && !PagingIo && ( (ByteOffset.LowPart & (SECTOR_SIZE - 1)) || (Length & (SECTOR_SIZE - 1))) ) { Status = STATUS_INVALID_PARAMETER; __leave; } if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) { ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC); Status = STATUS_PENDING; __leave; } if (!Nocache) { BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); BOOLEAN bWait = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED); if ( !CcCanIWrite( FileObject, Length, (bWait && bQueue), bAgain ) ) { Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoReadAccess); if (NT_SUCCESS(Status)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED); CcDeferWrite( FileObject, (PCC_POST_DEFERRED_WRITE)Ext2DeferWrite, IrpContext, Irp, Length, bAgain ); bDeferred = TRUE; Status = STATUS_PENDING; __leave; } } } if (IsDirectory(Fcb) && !PagingIo) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } if (IsFlagOn(Irp->Flags, IRP_SYNCHRONOUS_PAGING_IO) && !IrpContext->IsTopLevel) { PIRP TopIrp; TopIrp = IoGetTopLevelIrp(); if ( (ULONG_PTR)TopIrp > FSRTL_MAX_TOP_LEVEL_IRP_FLAG && NodeType(TopIrp) == IO_TYPE_IRP) { PIO_STACK_LOCATION IrpStack; IrpStack = IoGetCurrentIrpStackLocation(TopIrp); if ((IrpStack->MajorFunction == IRP_MJ_WRITE) && (IrpStack->FileObject->FsContext == FileObject->FsContext) && !FlagOn(TopIrp->Flags, IRP_NOCACHE) ) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH); RecursiveWriteThrough = TRUE; } } } if (PagingIo) { if (!ExAcquireResourceSharedLite(&Fcb->PagingIoResource, TRUE)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; if ( (ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; __leave; } else { ReturnedLength = (ULONG)(Fcb->Header.FileSize.QuadPart - ByteOffset.QuadPart); if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); } } else { ReturnedLength = Length; } } else { if (!Ext2CheckFileAccess(Vcb, Fcb->Mcb, Ext2FileCanWrite)) { Status = STATUS_ACCESS_DENIED; __leave; } if (IsDirectory(Fcb)) { __leave; } if (!ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE)) { Status = STATUS_PENDING; __leave; } MainResourceAcquired = TRUE; // // Do flushing for such cases // if (Nocache && Ccb != NULL && Fcb->SectionObject.DataSectionObject != NULL) { ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Fcb->PagingIoResource); CcFlushCache( &(Fcb->SectionObject), &ByteOffset, CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE), &(Irp->IoStatus)); ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); if (!NT_SUCCESS(Irp->IoStatus.Status)) { Status = Irp->IoStatus.Status; __leave; } ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Fcb->PagingIoResource); CcPurgeCacheSection( &(Fcb->SectionObject), &(ByteOffset), CEILING_ALIGNED(ULONG, Length, BLOCK_SIZE), FALSE ); } if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLockAnchor, Irp)) { Status = STATUS_FILE_LOCK_CONFLICT; __leave; } if (Ccb != NULL) { Status = FsRtlCheckOplock( &Fcb->Oplock, Irp, IrpContext, Ext2OplockComplete, Ext2LockIrp ); if (Status != STATUS_SUCCESS) { OpPostIrp = TRUE; __leave; } // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } // // Extend the inode size when the i/o is beyond the file end ? // if ((ByteOffset.QuadPart + Length) > Fcb->Header.FileSize.QuadPart) { LARGE_INTEGER AllocationSize, Last; if (!ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE)) { Status = STATUS_PENDING; __leave; } PagingIoResourceAcquired = TRUE; /* let this irp wait, since it has to be synchronous */ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); Last.QuadPart = Fcb->Header.AllocationSize.QuadPart; AllocationSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length); AllocationSize.QuadPart = CEILING_ALIGNED(ULONGLONG, (ULONGLONG)AllocationSize.QuadPart, (ULONGLONG)BLOCK_SIZE); /* tell Ext2ExpandFile to allocate unwritten extent or NULL blocks for indirect files, otherwise we might get gabage data in holes */ IrpContext->MajorFunction += IRP_MJ_MAXIMUM_FUNCTION; Status = Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &AllocationSize); IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION; if (AllocationSize.QuadPart > Last.QuadPart) { Fcb->Header.AllocationSize.QuadPart = AllocationSize.QuadPart; SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_WRITE); } ExReleaseResourceLite(&Fcb->PagingIoResource); PagingIoResourceAcquired = FALSE; if (ByteOffset.QuadPart >= Fcb->Header.AllocationSize.QuadPart) { if (NT_SUCCESS(Status)) { DbgBreak(); Status = STATUS_UNSUCCESSFUL; } __leave; } if (ByteOffset.QuadPart + Length > Fcb->Header.AllocationSize.QuadPart) { Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - ByteOffset.QuadPart); } Fcb->Header.FileSize.QuadPart = Fcb->Inode->i_size = ByteOffset.QuadPart + Length; Ext2SaveInode(IrpContext, Vcb, Fcb->Inode); if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED; FileSizesChanged = TRUE; if (Fcb->Header.FileSize.QuadPart >= 0x80000000 && !IsFlagOn(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { SetFlag(SUPER_BLOCK->s_feature_ro_compat, EXT2_FEATURE_RO_COMPAT_LARGE_FILE); Ext2SaveSuper(IrpContext, Vcb); } DEBUG(DL_IO, ("Ext2WriteFile: expanding %wZ to FS: %I64xh FA: %I64xh\n", &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart, Fcb->Header.AllocationSize.QuadPart)); } ReturnedLength = Length; } if (!Nocache) { if (FileObject->PrivateCacheMap == NULL) { CcInitializeCacheMap( FileObject, (PCC_FILE_SIZES)(&Fcb->Header.AllocationSize), FALSE, &Ext2Global->CacheManagerCallbacks, Fcb ); CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY ); } if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL)) { CcPrepareMdlWrite( FileObject, &ByteOffset, Length, &Irp->MdlAddress, &Irp->IoStatus ); Status = Irp->IoStatus.Status; } else { Buffer = Ext2GetUserBuffer(Irp); if (Buffer == NULL) { DbgBreak(); Status = STATUS_INVALID_USER_BUFFER; __leave; } if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { /* let this irp wait, since it has to be synchronous */ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); rc = Ext2ZeroData(IrpContext, Vcb, FileObject, &Fcb->Header.ValidDataLength, &ByteOffset); if (!rc) { Status = STATUS_PENDING; DbgBreak(); __leave; } } if (!CcCopyWrite(FileObject, &ByteOffset, Length, Ext2CanIWait(), Buffer)) { if (Ext2CanIWait() || !CcCopyWrite(FileObject, &ByteOffset, Length, TRUE, Buffer)) { Status = STATUS_PENDING; DbgBreak(); __leave; } } if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; } else { if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length) Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length; } CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); FileSizesChanged = TRUE; } Status = STATUS_SUCCESS; } if (NT_SUCCESS(Status)) { Irp->IoStatus.Information = Length; if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) { DEBUG(DL_FLP, ("Ext2WriteFile is starting FlushingDpc...\n")); Ext2StartFloppyFlushDpc(Vcb, Fcb, FileObject); } } } else { if (!PagingIo && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { if (ByteOffset.QuadPart > Fcb->Header.ValidDataLength.QuadPart) { /* let this irp wait, since it has to be synchronous */ SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); rc = Ext2ZeroData(IrpContext, Vcb, FileObject, &Fcb->Header.ValidDataLength, &ByteOffset); if (!rc) { Status = STATUS_PENDING; DbgBreak(); __leave; } } } Status = Ext2LockUserBuffer( IrpContext->Irp, Length, IoReadAccess ); if (!NT_SUCCESS(Status)) { __leave; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = ReturnedLength; Status = Ext2WriteInode( IrpContext, Vcb, Fcb->Mcb, (ULONGLONG)(ByteOffset.QuadPart), NULL, ReturnedLength, TRUE, &Length ); Irp = IrpContext->Irp; if (NT_SUCCESS(Status) && !RecursiveWriteThrough && !IsLazyWriter(Fcb)) { if (ByteOffset.QuadPart + Length > Fcb->Header.ValidDataLength.QuadPart ) { FileSizesChanged = TRUE; if (Fcb->Header.FileSize.QuadPart < ByteOffset.QuadPart + Length) { if (!PagingIo) Fcb->Header.FileSize.QuadPart = ByteOffset.QuadPart + Length; Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart; } else { if (Fcb->Header.ValidDataLength.QuadPart < ByteOffset.QuadPart + Length) Fcb->Header.ValidDataLength.QuadPart = ByteOffset.QuadPart + Length; } if (!PagingIo && CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } DEBUG(DL_IO, ("Ext2WriteFile: %wZ written FS: %I64xh FA: %I64xh BO: %I64xh LEN: %u\n", &Fcb->Mcb->ShortName, Fcb->Header.FileSize.QuadPart, Fcb->Header.AllocationSize.QuadPart, ByteOffset.QuadPart, Length)); } } } if (FileSizesChanged) { FileObject->Flags |= FO_FILE_SIZE_CHANGED | FO_FILE_MODIFIED; Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED ); } } __finally { /* * in case we got excpetions, we need revert MajorFunction * back to IRP_MJ_WRITE. The reason we do this, is to tell * Ext2ExpandFile to allocate unwritten extent or don't add * new blocks for indirect files. */ if (IrpContext->MajorFunction > IRP_MJ_MAXIMUM_FUNCTION) IrpContext->MajorFunction -= IRP_MJ_MAXIMUM_FUNCTION; if (Irp) { if (PagingIoResourceAcquired) { ExReleaseResourceLite(&Fcb->PagingIoResource); } if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } } if (!OpPostIrp && !IrpContext->ExceptionInProgress) { if (Irp) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT ) { if (!bDeferred) { Status = Ext2QueueRequest(IrpContext); } } else { if (NT_SUCCESS(Status) && !PagingIo) { if (SynchronousIo) { FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + Irp->IoStatus.Information; } SetFlag(FileObject->Flags, FO_FILE_MODIFIED); SetLongFlag(Fcb->Flags, FCB_FILE_MODIFIED); } Ext2CompleteIrpContext(IrpContext, Status); } } else { Ext2FreeIrpContext(IrpContext); } } } DEBUG(DL_IO, ("Ext2WriteFile: %wZ written at Offset=%I64xh Length=%xh PagingIo=%d Nocache=%d " "RetLen=%xh VDL=%I64xh FileSize=%I64xh i_size=%I64xh Status=%xh\n", &Fcb->Mcb->ShortName, ByteOffset, Length, PagingIo, Nocache, ReturnedLength, Fcb->Header.ValidDataLength.QuadPart,Fcb->Header.FileSize.QuadPart, Fcb->Inode->i_size, Status)); return Status; }
BOOLEAN Ext2QueryGlobalParameters( IN PUNICODE_STRING RegistryPath) { NTSTATUS Status; UNICODE_STRING ParameterPath; RTL_QUERY_REGISTRY_TABLE QueryTable[2]; ULONG WritingSupport = 0; ULONG CheckingBitmap = 0; ULONG Ext3ForceWriting = 0; ULONG AutoMount = 0; UNICODE_STRING UniName; ANSI_STRING AnsiName; WCHAR UniBuffer[CODEPAGE_MAXLEN]; USHORT Buffer[HIDINGPAT_LEN]; 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); /* querying value of WritingSupport */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = WRITING_SUPPORT; QueryTable[0].EntryContext = &WritingSupport; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); DEBUG(DL_ERR, ( "Ext2QueryParameters: WritingSupport=%xh\n", WritingSupport)); /* querying value of CheckingBitmap */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = CHECKING_BITMAP; QueryTable[0].EntryContext = &CheckingBitmap; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); DEBUG(DL_ERR, ( "Ext2QueryParameters: CheckingBitmap=%xh\n", CheckingBitmap)); /* querying value of Ext3ForceWriting */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = EXT3_FORCEWRITING; QueryTable[0].EntryContext = &Ext3ForceWriting; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext3ForceWriting=%xh\n", Ext3ForceWriting)); /* querying value of AutoMount */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = AUTO_MOUNT; QueryTable[0].EntryContext = &AutoMount; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); if (NT_SUCCESS(Status) && AutoMount == 0) { ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); } DEBUG(DL_ERR, ( "Ext2QueryParameters: AutoMount=%xh\n", AutoMount)); /* querying codepage */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = CODEPAGE_NAME; QueryTable[0].EntryContext = &(UniName); UniName.MaximumLength = CODEPAGE_MAXLEN * sizeof(WCHAR); UniName.Length = 0; UniName.Buffer = (PWSTR)UniBuffer; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); if (NT_SUCCESS(Status)) { DEBUG(DL_ERR, ( "Ext2QueryParameters: Ext2CodePage=%wZ\n", &UniName)); 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; /* querying name hiding patterns: prefix*/ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = HIDING_PREFIX; QueryTable[0].EntryContext = &(UniName); UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); UniName.Length = 0; UniName.Buffer = Buffer; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); if (NT_SUCCESS(Status)) { DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingPrefix=%wZ\n", &UniName)); 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; /* querying name hiding patterns: suffix */ RtlZeroMemory(&QueryTable[0], sizeof(RTL_QUERY_REGISTRY_TABLE) * 2); QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = HIDING_SUFFIX; QueryTable[0].EntryContext = &(UniName); UniName.MaximumLength = HIDINGPAT_LEN * sizeof(WCHAR); UniName.Length = 0; UniName.Buffer = Buffer; Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, ParameterPath.Buffer, &QueryTable[0], NULL, NULL ); if (NT_SUCCESS(Status)) { DEBUG(DL_ERR, ( "Ext2QueryParameters: HidingSuffix=%wZ\n", &UniName)); 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; { if (WritingSupport) { SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); } else { ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); } if (CheckingBitmap) { SetLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); } else { ClearLongFlag(Ext2Global->Flags, EXT2_CHECKING_BITMAP); } if (Ext3ForceWriting) { DbgPrint("Ext2Fsd -- Warning: Ext3ForceWriting enabled !!!\n"); SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); } else { ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); } } 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; }
NTSTATUS Ext2Cleanup (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PEXT2_VCB Vcb; PFILE_OBJECT FileObject; PEXT2_FCB Fcb; PEXT2_CCB Ccb; PIRP Irp; PEXT2_MCB Mcb; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN FcbPagingIoResourceAcquired = FALSE; __try { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_SUCCESS; __leave; } Irp = IrpContext->Irp; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); if (!IsVcbInited(Vcb)) { Status = STATUS_SUCCESS; __leave; } FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext; if (!Fcb || (Fcb->Identifier.Type != EXT2VCB && Fcb->Identifier.Type != EXT2FCB)) { Status = STATUS_SUCCESS; __leave; } Mcb = Fcb->Mcb; Ccb = (PEXT2_CCB) FileObject->FsContext2; if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { Status = STATUS_SUCCESS; __leave; } VcbResourceAcquired = ExAcquireResourceExclusiveLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); if (Fcb->Identifier.Type == EXT2VCB) { if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) && (Vcb->LockFile == FileObject) ) { ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Vcb->LockFile = NULL; Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED); } if (Ccb) { Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Vcb->OpenVolumeCount); } IoRemoveShareAccess(FileObject, &Vcb->ShareAccess); Status = STATUS_SUCCESS; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE)) { if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) { Status = Ext2FlushFile(IrpContext, Fcb, Ccb); } __leave; } if (Ccb == NULL) { Status = STATUS_SUCCESS; __leave; } if (IsDirectory(Fcb)) { if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); FsRtlNotifyFullChangeDirectory( Vcb->NotifySync, &Vcb->NotifyList, Ccb, NULL, FALSE, FALSE, 0, NULL, NULL, NULL ); } FsRtlNotifyCleanup(Vcb->NotifySync, &Vcb->NotifyList, Ccb); } ExReleaseResourceLite(&Vcb->MainResource); VcbResourceAcquired = FALSE; FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); Ext2DerefXcb(&Vcb->OpenHandleCount); Ext2DerefXcb(&Fcb->OpenHandleCount); if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED)) { Fcb->Mcb->FileAttr |= FILE_ATTRIBUTE_ARCHIVE; } if (IsDirectory(Fcb)) { ext3_release_dir(Fcb->Inode, &Ccb->filp); } else { if ( IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) && !IsFlagOn(Ccb->Flags, CCB_LAST_WRITE_UPDATED)) { LARGE_INTEGER SysTime; KeQuerySystemTime(&SysTime); Fcb->Inode->i_atime = Fcb->Inode->i_mtime = Ext2LinuxTime(SysTime); Fcb->Mcb->LastAccessTime = Fcb->Mcb->LastWriteTime = Ext2NtTime(Fcb->Inode->i_atime); Ext2SaveInode(IrpContext, Vcb, Fcb->Inode); Ext2NotifyReportChange( IrpContext, Vcb, Fcb->Mcb, FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS, FILE_ACTION_MODIFIED ); } FsRtlCheckOplock( &Fcb->Oplock, Irp, IrpContext, NULL, NULL ); Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) { Fcb->NonCachedOpenCount--; } if (IsFlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE)) { SetLongFlag(Fcb->Flags, FCB_DELETE_PENDING); } // // Drop any byte range locks this process may have on the file. // FsRtlFastUnlockAll( &Fcb->FileLockAnchor, FileObject, IoGetRequestorProcess(Irp), NULL ); // // If there are no byte range locks owned by other processes on the // file the fast I/O read/write functions doesn't have to check for // locks so we set IsFastIoPossible to FastIoIsPossible again. // if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE)) { if (Fcb->Header.IsFastIoPossible != FastIoIsPossible) { #if EXT2_DEBUG DEBUG(DL_INF, (": %-16.16s %-31s %wZ\n", Ext2GetCurrentProcessName(), "FastIoIsPossible", &Fcb->Mcb->FullName )); #endif Fcb->Header.IsFastIoPossible = FastIoIsPossible; } } if (Fcb->OpenHandleCount == 0 && (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE) || IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_WRITE)) ) { LARGE_INTEGER Size; ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE); FcbPagingIoResourceAcquired = TRUE; Size.QuadPart = CEILING_ALIGNED(ULONGLONG, (ULONGLONG)Fcb->Mcb->Inode.i_size, (ULONGLONG)BLOCK_SIZE); if (!IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size); Fcb->Header.ValidDataLength.QuadPart = Fcb->Header.FileSize.QuadPart = Fcb->Mcb->Inode.i_size; Fcb->Header.AllocationSize = Size; if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); } } ClearLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE|FCB_ALLOC_IN_WRITE); ExReleaseResourceLite(&Fcb->PagingIoResource); FcbPagingIoResourceAcquired = FALSE; } } if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING)) { if (Fcb->OpenHandleCount == 0 || (Mcb = Ccb->SymLink)) { // // Ext2DeleteFile will acquire these lock inside // if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); FcbResourceAcquired = FALSE; } // // this file is to be deleted ... // if (Ccb->SymLink) { Mcb = Ccb->SymLink; FileObject->DeletePending = FALSE; } Status = Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb); if (NT_SUCCESS(Status)) { if (IsMcbDirectory(Mcb)) { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED ); } else { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED ); } } // // re-acquire the main resource lock // FcbResourceAcquired = ExAcquireResourceExclusiveLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); if (CcIsFileCached(FileObject)) { CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize))); SetFlag(FileObject->Flags, FO_FILE_MODIFIED); } } } if (!IsDirectory(Fcb)) { if ( IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) && (Fcb->NonCachedOpenCount + 1 == Fcb->ReferenceCount) && (Fcb->SectionObject.DataSectionObject != NULL)) { if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) && !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED) ) { CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL); } if (ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE)) { ExReleaseResourceLite(&(Fcb->PagingIoResource)); } CcPurgeCacheSection( &Fcb->SectionObject, NULL, 0, FALSE ); } CcUninitializeCacheMap(FileObject, NULL, NULL); } IoRemoveShareAccess(FileObject, &Fcb->ShareAccess); DEBUG(DL_INF, ( "Ext2Cleanup: OpenCount=%u ReferCount=%u NonCahcedCount=%xh %wZ\n", Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName)); Status = STATUS_SUCCESS; if (FileObject) { SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE); } } __finally { if (FcbPagingIoResourceAcquired) { ExReleaseResourceLite(&Fcb->PagingIoResource); } if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueRequest(IrpContext); } else { IrpContext->Irp->IoStatus.Status = Status; Ext2CompleteIrpContext(IrpContext, Status); } } } return Status; }
NTSTATUS Ext2ProcessVolumeProperty( IN PEXT2_VCB Vcb, IN PEXT2_VOLUME_PROPERTY3 Property3, IN ULONG Length ) { struct nls_table * PageTable = NULL; PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3; PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN VcbResourceAcquired = FALSE; __try { ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE; if (Property->Command == APP_CMD_SET_PROPERTY || Property->Command == APP_CMD_QUERY_PROPERTY) { if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY2 || Property->Command == APP_CMD_QUERY_PROPERTY2) { if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY3 || Property->Command == APP_CMD_QUERY_PROPERTY3) { if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { Status = STATUS_INVALID_PARAMETER; __leave; } } switch (Property->Command) { case APP_CMD_SET_PROPERTY3: if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { if (Property3->AutoMount) SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); else ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); } if (Property3->Flags2 & EXT2_VPROP3_USERIDS) { SetFlag(Vcb->Flags, VCB_USER_IDS); Vcb->uid = Property3->uid; Vcb->gid = Property3->gid; if (Property3->EIDS) { Vcb->euid = Property3->euid; Vcb->egid = Property3->egid; SetFlag(Vcb->Flags, VCB_USER_EIDS); } else { Vcb->euid = Vcb->egid = 0; ClearFlag(Vcb->Flags, VCB_USER_EIDS); } } else { ClearFlag(Vcb->Flags, VCB_USER_IDS); ClearFlag(Vcb->Flags, VCB_USER_EIDS); Vcb->uid = Vcb->gid = 0; Vcb->euid = Vcb->egid = 0; } case APP_CMD_SET_PROPERTY2: RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN); if (Vcb->bHidingPrefix = Property2->bHidingPrefix) { RtlCopyMemory( Vcb->sHidingPrefix, Property2->sHidingPrefix, HIDINGPAT_LEN - 1); } RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN); if (Vcb->bHidingSuffix = Property2->bHidingSuffix) { RtlCopyMemory( Vcb->sHidingSuffix, Property2->sHidingSuffix, HIDINGPAT_LEN - 1); } Vcb->DrvLetter = Property2->DrvLetter; case APP_CMD_SET_PROPERTY: if (Property->bReadonly) { if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) { Ext2FlushFiles(NULL, Vcb, FALSE); Ext2FlushVolume(NULL, Vcb, FALSE); } SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else { if (Property->bExt3Writable) { SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING); } if (!Vcb->IsExt3fs) { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } else if (!Property->bExt3Writable) { SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); Ext2RecoverJournal(NULL, Vcb); if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) { SetLongFlag(Vcb->Flags, VCB_READ_ONLY); } else { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } } else { ClearLongFlag(Vcb->Flags, VCB_READ_ONLY); } } PageTable = load_nls(Property->Codepage); memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); Vcb->Codepage.PageTable = PageTable; if (Vcb->Codepage.PageTable) { Ext2InitializeLabel(Vcb, Vcb->SuperBlock); } break; case APP_CMD_QUERY_PROPERTY3: if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) { SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); Property3->AutoMount = TRUE; } else { ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT); Property3->AutoMount = FALSE; } if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) { SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); Property3->uid = Vcb->uid; Property3->gid = Vcb->gid; if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) { Property3->EIDS = TRUE; Property3->euid = Vcb->euid; Property3->egid = Vcb->egid; } else { Property3->EIDS = FALSE; } } else { ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS); } case APP_CMD_QUERY_PROPERTY2: RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16); Property2->DrvLetter = Vcb->DrvLetter; if (Property2->bHidingPrefix = Vcb->bHidingPrefix) { RtlCopyMemory( Property2->sHidingPrefix, Vcb->sHidingPrefix, HIDINGPAT_LEN); } else { RtlZeroMemory( Property2->sHidingPrefix, HIDINGPAT_LEN); } if (Property2->bHidingSuffix = Vcb->bHidingSuffix) { RtlCopyMemory( Property2->sHidingSuffix, Vcb->sHidingSuffix, HIDINGPAT_LEN); } else { RtlZeroMemory( Property2->sHidingSuffix, HIDINGPAT_LEN); } case APP_CMD_QUERY_PROPERTY: Property->bExt2 = TRUE; Property->bExt3 = Vcb->IsExt3fs; Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY); if (!Property->bReadonly && Vcb->IsExt3fs) { Property->bExt3Writable = TRUE; } else { Property->bExt3Writable = FALSE; } RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN); if (Vcb->Codepage.PageTable) { strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN); } else { strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN); } break; default: Status = STATUS_INVALID_PARAMETER; break; } } __finally { if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } } return Status; }
NTSTATUS Ext2ProcessGlobalProperty( IN PDEVICE_OBJECT DeviceObject, IN PEXT2_VOLUME_PROPERTY3 Property3, IN ULONG Length ) { PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3; PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3; struct nls_table * PageTable = NULL; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN GlobalDataResourceAcquired = FALSE; __try { if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) { Status = STATUS_INVALID_PARAMETER; __leave; } /* query Ext2Fsd's version and built date/time*/ if (Property->Command == APP_CMD_QUERY_VERSION) { PEXT2_VOLUME_PROPERTY_VERSION PVPV = (PEXT2_VOLUME_PROPERTY_VERSION) Property; if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) { Status = STATUS_INVALID_PARAMETER; __leave; } RtlZeroMemory(&PVPV->Date[0], 0x20); RtlZeroMemory(&PVPV->Time[0], 0x20); RtlZeroMemory(&PVPV->Version[0],0x1C); strncpy(&PVPV->Version[0], gVersion, 0x1B); strncpy(&PVPV->Date[0], gDate, 0x1F); strncpy(&PVPV->Time[0], gTime, 0x1F); __leave; } /* must be property query/set commands */ if (Property->Command == APP_CMD_SET_PROPERTY) { if (Length < sizeof(EXT2_VOLUME_PROPERTY)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY2) { if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else if (Property->Command == APP_CMD_SET_PROPERTY3) { if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) { Status = STATUS_INVALID_PARAMETER; __leave; } } else { Status = STATUS_INVALID_PARAMETER; __leave; } ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE); GlobalDataResourceAcquired = TRUE; switch (Property->Command) { case APP_CMD_SET_PROPERTY3: if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) { if (Property3->AutoMount) SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); else ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT); } case APP_CMD_SET_PROPERTY2: RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN); if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) { RtlCopyMemory( Ext2Global->sHidingPrefix, Property2->sHidingPrefix, HIDINGPAT_LEN - 1); } RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN); if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) { RtlCopyMemory( Ext2Global->sHidingSuffix, Property2->sHidingSuffix, HIDINGPAT_LEN - 1); } case APP_CMD_SET_PROPERTY: if (Property->bReadonly) { ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); } else { SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING); if (Property->bExt3Writable) { SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); } else { ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING); } } PageTable = load_nls(Property->Codepage); if (PageTable) { memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN); Ext2Global->Codepage.PageTable = PageTable; } break; default: break; } } __finally { if (GlobalDataResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); } } return Status; }
NTSTATUS Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN GlobalDataResourceAcquired = FALSE; __try { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } ExAcquireResourceExclusiveLite( &Ext2Global->Resource, TRUE ); GlobalDataResourceAcquired = TRUE; if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n")); Status = STATUS_ACCESS_DENIED; __leave; } { PEXT2_VCB Vcb; PLIST_ENTRY ListEntry; ListEntry = Ext2Global->VcbList.Flink; while (ListEntry != &(Ext2Global->VcbList)) { Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); ListEntry = ListEntry->Flink; if (Vcb && (!Vcb->ReferenceCount) && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Ext2RemoveVcb(Vcb); Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED); Ext2DestroyVcb(Vcb); } } } if (!IsListEmpty(&(Ext2Global->VcbList))) { DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n")); Status = STATUS_ACCESS_DENIED; __leave; } IoUnregisterFileSystem(Ext2Global->DiskdevObject); IoUnregisterFileSystem(Ext2Global->CdromdevObject); Ext2Global->DriverObject->DriverUnload = DriverUnload; SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING); Status = STATUS_SUCCESS; DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n")); } __finally { if (GlobalDataResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); } if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } return Status; }
NTSTATUS Ext2Close (IN PEXT2_IRP_CONTEXT IrpContext) { PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_SUCCESS; PEXT2_VCB Vcb = NULL; PFILE_OBJECT FileObject; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN bDeleteVcb = FALSE; BOOLEAN bBeingClosed = FALSE; BOOLEAN bSkipLeave = FALSE; __try { ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT))); DeviceObject = IrpContext->DeviceObject; if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_SUCCESS; Vcb = NULL; __leave; } Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); if (!ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE )) { DEBUG(DL_INF, ("Ext2Close: PENDING ... Vcb: %xh/%xh\n", Vcb->OpenHandleCount, Vcb->ReferenceCount)); Status = STATUS_PENDING; __leave; } VcbResourceAcquired = TRUE; bSkipLeave = TRUE; if (IsFlagOn(Vcb->Flags, VCB_BEING_CLOSED)) { bBeingClosed = TRUE; } else { SetLongFlag(Vcb->Flags, VCB_BEING_CLOSED); bBeingClosed = FALSE; } if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) { FileObject = NULL; Fcb = IrpContext->Fcb; Ccb = IrpContext->Ccb; } else { FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext; if (!Fcb) { Status = STATUS_SUCCESS; __leave; } ASSERT(Fcb != NULL); Ccb = (PEXT2_CCB) FileObject->FsContext2; } DEBUG(DL_INF, ( "Ext2Close: (VCB) bBeingClosed = %d Vcb = %p ReferCount = %d\n", bBeingClosed, Vcb, Vcb->ReferenceCount)); if (Fcb->Identifier.Type == EXT2VCB) { if (Ccb) { Ext2DerefXcb(&Vcb->ReferenceCount); Ext2FreeCcb(Vcb, Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } Status = STATUS_SUCCESS; __leave; } if ( Fcb->Identifier.Type != EXT2FCB || Fcb->Identifier.Size != sizeof(EXT2_FCB)) { __leave; } if (!ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE )) { Status = STATUS_PENDING; __leave; } FcbResourceAcquired = TRUE; Fcb->Header.IsFastIoPossible = FastIoIsNotPossible; if (!Ccb) { Status = STATUS_SUCCESS; __leave; } ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); if (IsFlagOn(Fcb->Flags, FCB_STATE_BUSY)) { SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_FILE_BUSY); DEBUG(DL_WRN, ( "Ext2Close: busy bit set: %wZ\n", &Fcb->Mcb->FullName )); Status = STATUS_PENDING; __leave; } DEBUG(DL_INF, ( "Ext2Close: Fcb = %p OpenHandleCount= %u ReferenceCount=%u NonCachedCount=%u %wZ\n", Fcb, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount, &Fcb->Mcb->FullName )); if (Ccb) { Ext2FreeCcb(Vcb, Ccb); if (FileObject) { FileObject->FsContext2 = Ccb = NULL; } } if (0 == Ext2DerefXcb(&Fcb->ReferenceCount)) { // // Remove Fcb from Vcb->FcbList ... // if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); FcbResourceAcquired = FALSE; } Ext2FreeFcb(Fcb); if (FileObject) { FileObject->FsContext = Fcb = NULL; } } Ext2DerefXcb(&Vcb->ReferenceCount); Status = STATUS_SUCCESS; } __finally { if (NT_SUCCESS(Status) && Vcb != NULL && IsVcbInited(Vcb)) { /* for Ext2Fsd driver open/close, Vcb is NULL */ if ((!bBeingClosed) && (Vcb->ReferenceCount == 0) && (!IsMounted(Vcb) || IsDispending(Vcb))) { bDeleteVcb = TRUE; } } if (bSkipLeave && !bBeingClosed) { ClearFlag(Vcb->Flags, VCB_BEING_CLOSED); } if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); } if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } if (!IrpContext->ExceptionInProgress) { if (Status == STATUS_PENDING) { Ext2QueueCloseRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); if (bDeleteVcb) { PVPB Vpb = Vcb->Vpb; DEBUG(DL_DBG, ( "Ext2Close: Try to free Vcb %p and Vpb %p\n", Vcb, Vpb)); Ext2CheckDismount(IrpContext, Vcb, FALSE); } } } } return Status; }