Пример #1
0
NTSTATUS
FFSLockVcb(
	IN PFFS_VCB     Vcb,
	IN PFILE_OBJECT FileObject)
{
	NTSTATUS           Status;

    PAGED_CODE();

	_SEH2_TRY
	{
		if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
		{
			FFSPrint((DBG_INFO, "FFSLockVolume: Volume is already locked.\n"));

			Status = STATUS_ACCESS_DENIED;

			_SEH2_LEAVE;
		}

		if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0))
		{
			FFSPrint((DBG_INFO, "FFSLockVcb: There are still opened files.\n"));

			Status = STATUS_ACCESS_DENIED;

			_SEH2_LEAVE;
		}

		if (!FFSIsHandleCountZero(Vcb))
		{
			FFSPrint((DBG_INFO, "FFSLockVcb: Thare are still opened files.\n"));

			Status = STATUS_ACCESS_DENIED;

			_SEH2_LEAVE;
		}

		SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);

		FFSSetVpbFlag(Vcb->Vpb, VPB_LOCKED);

		Vcb->LockFile = FileObject;

		FFSPrint((DBG_INFO, "FFSLockVcb: Volume locked.\n"));

		Status = STATUS_SUCCESS;
	}

	_SEH2_FINALLY
	{
		// Nothing
	} _SEH2_END;

	return Status;
}
Пример #2
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPurgeFile(
	IN PFFS_FCB Fcb,
	IN BOOLEAN  FlushBeforePurge)
{
	IO_STATUS_BLOCK    IoStatus;

    PAGED_CODE();

	ASSERT(Fcb != NULL);

	ASSERT((Fcb->Identifier.Type == FFSFCB) &&
			(Fcb->Identifier.Size == sizeof(FFS_FCB)));


	if(!IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) && FlushBeforePurge &&
			!IsFlagOn(Fcb->Vcb->Flags, VCB_WRITE_PROTECTED))
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcFlushCache on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResourceLite(&Fcb->PagingIoResource);

		CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus);

		ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
	}

	if (Fcb->SectionObject.ImageSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: MmFlushImageSection on %s.\n", 
					Fcb->AnsiFileName.Buffer));

		MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite);
	}

	if (Fcb->SectionObject.DataSectionObject)
	{

		FFSPrint((DBG_INFO, "FFSPurgeFile: CcPurgeCacheSection on %s.\n",
					Fcb->AnsiFileName.Buffer));

		CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
	}

	return STATUS_SUCCESS;
}
Пример #3
0
BOOLEAN
FFSIsHandleCountZero(
	IN PFFS_VCB Vcb)
{
	PFFS_FCB   Fcb;
	PLIST_ENTRY List;

    PAGED_CODE();

	for(List = Vcb->FcbList.Flink;
			List != &Vcb->FcbList;
			List = List->Flink)
	{
		Fcb = CONTAINING_RECORD(List, FFS_FCB, Next);

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		FFSPrint((DBG_INFO, "FFSIsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n",
					Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, Fcb->OpenHandleCount));

		if (Fcb->OpenHandleCount)
		{
			return FALSE;
		}
	}

	return TRUE;
}
Пример #4
0
NTSTATUS
FFSUnlockVcb(
	IN PFFS_VCB     Vcb,
	IN PFILE_OBJECT FileObject)
{
	NTSTATUS        Status;

    PAGED_CODE();

	_SEH2_TRY
	{
		if (FileObject && FileObject->FsContext != Vcb)
		{
			Status = STATUS_NOT_LOCKED;
			_SEH2_LEAVE;
		}

		if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
		{
			FFSPrint((DBG_ERROR, ": FFSUnlockVcb: Volume is not locked.\n"));
			Status = STATUS_NOT_LOCKED;
			_SEH2_LEAVE;
		}

		if (Vcb->LockFile == FileObject)
		{
			ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);

			FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);

			FFSPrint((DBG_INFO, "FFSUnlockVcb: Volume unlocked.\n"));

			Status = STATUS_SUCCESS;
		}
		else
		{
			Status = STATUS_NOT_LOCKED;
		}
	}

	_SEH2_FINALLY
	{
		// Nothing
	} _SEH2_END;

	return Status;
}
Пример #5
0
__drv_mustHoldCriticalRegion
VOID
FFSFreeMcb(
	IN PFFS_MCB Mcb)
{
#ifndef __REACTOS__
    PFFS_MCB   Parent = Mcb->Parent;
#endif
    PAGED_CODE();

	ASSERT(Mcb != NULL);

	ASSERT((Mcb->Identifier.Type == FFSMCB) &&
			(Mcb->Identifier.Size == sizeof(FFS_MCB)));

	FFSPrint((DBG_INFO, "FFSFreeMcb: Mcb %S will be freed.\n", Mcb->ShortName.Buffer));

	if (Mcb->ShortName.Buffer)
		ExFreePool(Mcb->ShortName.Buffer);

	if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
	{
		ExFreePool(Mcb);
	}
	else
	{
		ExAcquireResourceExclusiveLite(
				&FFSGlobal->LAResource,
				TRUE);

		ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);

		ExReleaseResourceForThreadLite(
				&FFSGlobal->LAResource,
				ExGetCurrentResourceThread());
	}

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->McbAllocated--;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());
}
Пример #6
0
VOID
FFSFloppyFlushDpc(
	IN PKDPC Dpc,
	IN PVOID DeferredContext,
	IN PVOID SystemArgument1,
	IN PVOID SystemArgument2)
{
	PFFS_FLPFLUSH_CONTEXT Context;

	Context = (PFFS_FLPFLUSH_CONTEXT)DeferredContext;

	FFSPrint((DBG_USER, "FFSFloppyFlushDpc is to be started...\n"));

	ExInitializeWorkItem(&Context->Item,
			FFSFloppyFlush,
			Context);

	ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
}
Пример #7
0
VOID
FFSFloppyFlush(
	IN PVOID Parameter)
{
	PFFS_FLPFLUSH_CONTEXT Context;
	PFILE_OBJECT          FileObject;
	PFFS_FCB              Fcb;
	PFFS_VCB              Vcb;

	Context = (PFFS_FLPFLUSH_CONTEXT) Parameter;
	FileObject = Context->FileObject;
	Fcb = Context->Fcb;
	Vcb = Context->Vcb;

	FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n"));

	IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);

	if (Vcb)
	{
		ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
		ExReleaseResource(&Vcb->PagingIoResource);

		CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
	}

	if (FileObject)
	{
		ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext);

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResource(&Fcb->PagingIoResource);

		CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);

		ObDereferenceObject(FileObject);
	}

	IoSetTopLevelIrp(NULL);

	ExFreePool(Parameter);
}
Пример #8
0
VOID
FFSAddMcbNode(
	PFFS_VCB Vcb,
	PFFS_MCB Parent,
	PFFS_MCB Child)
{
	PFFS_MCB TmpMcb = Parent->Child;

    PAGED_CODE();

	if(IsFlagOn(Child->Flags, MCB_IN_TREE))
	{
		FFSBreakPoint();
		FFSPrint((DBG_ERROR, "FFSAddMcbNode: Child Mcb is alreay in the tree.\n"));
		return;
	}

	if (TmpMcb)
	{
		ASSERT(TmpMcb->Parent == Parent);

		while (TmpMcb->Next)
		{
			TmpMcb = TmpMcb->Next;
			ASSERT(TmpMcb->Parent == Parent);
		}

		TmpMcb->Next = Child;
		Child->Parent = Parent;
		Child->Next = NULL;
	}
	else
	{
		Parent->Child = Child;
		Child->Parent = Parent;
		Child->Next = NULL;
	}

	InsertTailList(&(Vcb->McbList), &(Child->Link));
	SetFlag(Child->Flags, MCB_IN_TREE);
}
Пример #9
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSFileSystemControl(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS    Status;

    PAGED_CODE();

	ASSERT(IrpContext);

	ASSERT((IrpContext->Identifier.Type == FFSICX) &&
			(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

	switch (IrpContext->MinorFunction)
	{
		case IRP_MN_USER_FS_REQUEST:
			Status = FFSUserFsRequest(IrpContext);
			break;

		case IRP_MN_MOUNT_VOLUME:
			Status = FFSMountVolume(IrpContext);
			break;

		case IRP_MN_VERIFY_VOLUME:
			Status = FFSVerifyVolume(IrpContext);
			break;

		default:

			FFSPrint((DBG_ERROR, "FFSFilsSystemControl: Invalid Device Request.\n"));
			Status = STATUS_INVALID_DEVICE_REQUEST;
			FFSCompleteIrpContext(IrpContext,  Status);
	}

	return Status;
}
Пример #10
0
NTSTATUS
FFSDispatchRequest(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	ASSERT(IrpContext);

	ASSERT((IrpContext->Identifier.Type == FFSICX) &&
			(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

	switch (IrpContext->MajorFunction)
	{
		case IRP_MJ_CREATE:
			return FFSCreate(IrpContext);

		case IRP_MJ_CLOSE:
			return FFSClose(IrpContext);

		case IRP_MJ_READ:
			return FFSRead(IrpContext);

		case IRP_MJ_WRITE:
			return FFSWrite(IrpContext);

		case IRP_MJ_FLUSH_BUFFERS:
			return FFSFlush(IrpContext);

		case IRP_MJ_QUERY_INFORMATION:
			return FFSQueryInformation(IrpContext);

		case IRP_MJ_SET_INFORMATION:
			return FFSSetInformation(IrpContext);

		case IRP_MJ_QUERY_VOLUME_INFORMATION:
			return FFSQueryVolumeInformation(IrpContext);

		case IRP_MJ_SET_VOLUME_INFORMATION:
			return FFSSetVolumeInformation(IrpContext);

		case IRP_MJ_DIRECTORY_CONTROL:
			return FFSDirectoryControl(IrpContext);

		case IRP_MJ_FILE_SYSTEM_CONTROL:
			return FFSFileSystemControl(IrpContext);

		case IRP_MJ_DEVICE_CONTROL:
			return FFSDeviceControl(IrpContext);

		case IRP_MJ_LOCK_CONTROL:
			return FFSLockControl(IrpContext);

		case IRP_MJ_CLEANUP:
			return FFSCleanup(IrpContext);

		case IRP_MJ_SHUTDOWN:
			return FFSShutDown(IrpContext);

#if (_WIN32_WINNT >= 0x0500)
		case IRP_MJ_PNP:
			return FFSPnp(IrpContext);
#endif //(_WIN32_WINNT >= 0x0500)        
		default:
			FFSPrint((DBG_ERROR, "FFSDispatchRequest: Unexpected major function: %xh\n",
						IrpContext->MajorFunction));

			FFSCompleteIrpContext(IrpContext, STATUS_DRIVER_INTERNAL_ERROR);

			return STATUS_DRIVER_INTERNAL_ERROR;
	}
}
Пример #11
0
PFFS_MCB
FFSAllocateMcb(
	PFFS_VCB        Vcb,
	PUNICODE_STRING FileName,
	ULONG           FileAttr)
{
	PFFS_MCB    Mcb = NULL;
	PLIST_ENTRY List = NULL;

	ULONG       Extra = 0;

#define MCB_NUM_SHIFT   0x04

	if (FFSGlobal->McbAllocated > (FFSGlobal->MaxDepth << MCB_NUM_SHIFT))
		Extra = FFSGlobal->McbAllocated - 
			(FFSGlobal->MaxDepth << MCB_NUM_SHIFT) +
			FFSGlobal->MaxDepth;

	FFSPrint((DBG_INFO,
				"FFSAllocateMcb: CurrDepth=%xh/%xh/%xh FileName=%S\n", 
				FFSGlobal->McbAllocated,
				FFSGlobal->MaxDepth << MCB_NUM_SHIFT,
				FFSGlobal->FcbAllocated,
				FileName->Buffer));

	List = Vcb->McbList.Flink;

	while ((List != &(Vcb->McbList)) && (Extra > 0))
	{
		Mcb = CONTAINING_RECORD(List, FFS_MCB, Link);
		List = List->Flink;

		if ((Mcb->Inode != 2) && (Mcb->Child == NULL) &&
				(Mcb->FFSFcb == NULL) && (!IsMcbUsed(Mcb)))
		{
			FFSPrint((DBG_INFO, "FFSAllocateMcb: Mcb %S will be freed.\n",
						Mcb->ShortName.Buffer));

			if (FFSDeleteMcbNode(Vcb, Vcb->McbTree, Mcb))
			{
				FFSFreeMcb(Mcb);

				Extra--;
			}
		}
	}

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->LAResource,
			TRUE);

	Mcb = (PFFS_MCB)(ExAllocateFromPagedLookasideList(
				&(FFSGlobal->FFSMcbLookasideList)));

	ExReleaseResourceForThreadLite(
			&FFSGlobal->LAResource,
			ExGetCurrentResourceThread());

	if (Mcb == NULL)
	{
		Mcb = (PFFS_MCB)ExAllocatePool(PagedPool, sizeof(FFS_MCB));

		RtlZeroMemory(Mcb, sizeof(FFS_MCB));

		SetFlag(Mcb->Flags, MCB_FROM_POOL);
	}
	else
	{
		RtlZeroMemory(Mcb, sizeof(FFS_MCB));
	}

	if (!Mcb)
	{
		return NULL;
	}

	Mcb->Identifier.Type = FFSMCB;
	Mcb->Identifier.Size = sizeof(FFS_MCB);

	if (FileName && FileName->Length)
	{
		Mcb->ShortName.Length = FileName->Length;
		Mcb->ShortName.MaximumLength = Mcb->ShortName.Length + 2;

		Mcb->ShortName.Buffer = ExAllocatePool(PagedPool, Mcb->ShortName.MaximumLength);

		if (!Mcb->ShortName.Buffer)
			goto errorout;

		RtlZeroMemory(Mcb->ShortName.Buffer, Mcb->ShortName.MaximumLength);
		RtlCopyMemory(Mcb->ShortName.Buffer, FileName->Buffer, Mcb->ShortName.Length);
	} 

	Mcb->FileAttr = FileAttr;

	ExAcquireResourceExclusiveLite(
			&FFSGlobal->CountResource,
			TRUE);

	FFSGlobal->McbAllocated++;

	ExReleaseResourceForThreadLite(
			&FFSGlobal->CountResource,
			ExGetCurrentResourceThread());

	return Mcb;

errorout:

	if (Mcb)
	{
		if (Mcb->ShortName.Buffer)
			ExFreePool(Mcb->ShortName.Buffer);

		if (FlagOn(Mcb->Flags, MCB_FROM_POOL))
		{
			ExFreePool(Mcb);
		}
		else
		{
			ExAcquireResourceExclusiveLite(
					&FFSGlobal->LAResource,
					TRUE);

			ExFreeToPagedLookasideList(&(FFSGlobal->FFSMcbLookasideList), Mcb);

			ExReleaseResourceForThreadLite(
					&FFSGlobal->LAResource,
					ExGetCurrentResourceThread());
		}
	}

	return NULL;
}
Пример #12
0
VOID
FFSFreeVcb(
	IN PFFS_VCB Vcb)
{
	ASSERT(Vcb != NULL);

	ASSERT((Vcb->Identifier.Type == FFSVCB) &&
			(Vcb->Identifier.Size == sizeof(FFS_VCB)));

	FsRtlNotifyUninitializeSync(&Vcb->NotifySync);

	if (Vcb->StreamObj)
	{
		if (IsFlagOn(Vcb->StreamObj->Flags, FO_FILE_MODIFIED))
		{
			IO_STATUS_BLOCK IoStatus;

			CcFlushCache(&(Vcb->SectionObject), NULL, 0, &IoStatus);
			ClearFlag(Vcb->StreamObj->Flags, FO_FILE_MODIFIED);
		}

		if (Vcb->StreamObj->PrivateCacheMap)
			FFSSyncUninitializeCacheMap(Vcb->StreamObj);

		ObDereferenceObject(Vcb->StreamObj);
		Vcb->StreamObj = NULL;
	}

#if DBG
	if (FsRtlNumberOfRunsInLargeMcb(&(Vcb->DirtyMcbs)) != 0)
	{
		LONGLONG            DirtyVba;
		LONGLONG            DirtyLba;
		LONGLONG            DirtyLength;
		int                 i;

		for (i = 0; FsRtlGetNextLargeMcbEntry (&(Vcb->DirtyMcbs), i, &DirtyVba, &DirtyLba, &DirtyLength); i++)
		{
			FFSPrint((DBG_INFO, "DirtyVba = %I64xh\n", DirtyVba));
			FFSPrint((DBG_INFO, "DirtyLba = %I64xh\n", DirtyLba));
			FFSPrint((DBG_INFO, "DirtyLen = %I64xh\n\n", DirtyLength));
		}

		FFSBreakPoint();
	}
#endif

	FsRtlUninitializeLargeMcb(&(Vcb->DirtyMcbs));

	FFSFreeMcbTree(Vcb->McbTree);

	if (Vcb->ffs_super_block)
	{
		ExFreePool(Vcb->ffs_super_block);
		Vcb->ffs_super_block = NULL;
	}

	ExDeleteResourceLite(&Vcb->McbResource);

	ExDeleteResourceLite(&Vcb->PagingIoResource);

	ExDeleteResourceLite(&Vcb->MainResource);

	IoDeleteDevice(Vcb->DeviceObject);
}
Пример #13
0
BOOLEAN
FFSCheckSetBlock(
	PFFS_IRP_CONTEXT IrpContext,
	PFFS_VCB         Vcb,
	ULONG            Block)
{
#if 0
	ULONG           Group, dwBlk, Length;

	RTL_BITMAP      BlockBitmap;
	PVOID           BitmapCache;
	PBCB            BitmapBcb;

	LARGE_INTEGER   Offset;

	BOOLEAN         bModified = FALSE;


	//Group = (Block - FFS_FIRST_DATA_BLOCK) / BLOCKS_PER_GROUP;

	dwBlk = (Block - FFS_FIRST_DATA_BLOCK) % BLOCKS_PER_GROUP;


	Offset.QuadPart = (LONGLONG) Vcb->BlockSize;
	Offset.QuadPart = Offset.QuadPart * Vcb->ffs_group_desc[Group].bg_block_bitmap;

	if (Group == Vcb->ffs_groups - 1)
	{
		Length = TOTAL_BLOCKS % BLOCKS_PER_GROUP;

		/* s_blocks_count is integer multiple of s_blocks_per_group */
		if (Length == 0)
			Length = BLOCKS_PER_GROUP;
	}
	else
	{
		Length = BLOCKS_PER_GROUP;
	}

	if (dwBlk >= Length)
		return FALSE;

	if (!CcPinRead(Vcb->StreamObj,
				&Offset,
				Vcb->BlockSize,
				PIN_WAIT,
				&BitmapBcb,
				&BitmapCache))
	{
		FFSPrint((DBG_ERROR, "FFSDeleteBlock: PinReading error ...\n"));
		return FALSE;
	}

	RtlInitializeBitMap(&BlockBitmap,
			BitmapCache,
			Length);

	if (RtlCheckBit(&BlockBitmap, dwBlk) == 0)
	{
		FFSBreakPoint();
		RtlSetBits(&BlockBitmap, dwBlk, 1);
		bModified = TRUE;
	}

	if (bModified)
	{
		CcSetDirtyPinnedData(BitmapBcb, NULL);

		FFSRepinBcb(IrpContext, BitmapBcb);

		FFSAddMcbEntry(Vcb, Offset.QuadPart, (LONGLONG)Vcb->BlockSize);
	}

	{
		CcUnpinData(BitmapBcb);
		BitmapBcb = NULL;
		BitmapCache = NULL;

		RtlZeroMemory(&BlockBitmap, sizeof(RTL_BITMAP));
	}

	return (!bModified);
#endif
	return FALSE;
}
Пример #14
0
ULONG
FFSProcessDirEntry(
	IN PFFS_VCB                Vcb,
	IN FILE_INFORMATION_CLASS  FileInformationClass,
	IN ULONG                   in,
	IN PVOID                   Buffer,
	IN ULONG                   UsedLength,
	IN ULONG                   Length,
	IN ULONG                   FileIndex,
	IN PUNICODE_STRING         pName,
	IN BOOLEAN                 Single)
{
	FFSv1_INODE dinode1;
	FFSv2_INODE dinode2;
	PFILE_DIRECTORY_INFORMATION FDI;
	PFILE_FULL_DIR_INFORMATION FFI;
	PFILE_BOTH_DIR_INFORMATION FBI;
	PFILE_NAMES_INFORMATION FNI;

	ULONG InfoLength = 0;
	ULONG NameLength = 0;
	ULONG dwBytes = 0;

    PAGED_CODE();

	NameLength = pName->Length;

	if (!in)
	{
		FFSPrint((DBG_ERROR, "FFSPricessDirEntry: ffs_dir_entry is empty.\n"));
		return 0;
	}

	InfoLength = FFSGetInfoLength(FileInformationClass);

	if (!InfoLength || InfoLength + NameLength - sizeof(WCHAR) > Length)
	{
		FFSPrint((DBG_INFO, "FFSPricessDirEntry: Buffer is not enough.\n"));
		return 0;
	}

	if (FS_VERSION == 1)
	{
		if(!FFSv1LoadInode(Vcb, in, &dinode1))
		{
			FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));

			FFSBreakPoint();

			return 0;
		}
	}
	else
	{
		if(!FFSv2LoadInode(Vcb, in, &dinode2))
		{
			FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));

			FFSBreakPoint();

			return 0;
		}
	}

	switch(FileInformationClass)
	{
		case FileDirectoryInformation:
			FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength);
			if (!Single)
				FDI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
			else
				FDI->NextEntryOffset = 0;
			FDI->FileIndex = FileIndex;

			if (FS_VERSION == 1)
			{
				FDI->CreationTime = FFSSysTime(dinode1.di_ctime);
				FDI->LastAccessTime = FFSSysTime(dinode1.di_atime);
				FDI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
				FDI->ChangeTime = FFSSysTime(dinode1.di_mtime);
				FDI->EndOfFile.QuadPart = dinode1.di_size;
				FDI->AllocationSize.QuadPart = dinode1.di_size;
				FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
				{
					SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode1.di_mode & IFMT) == IFDIR)
					FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

				FDI->FileNameLength = NameLength;
				RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
				break;
			}
			else
			{
				FDI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
				FDI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
				FDI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
				FDI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
				FDI->EndOfFile.QuadPart = dinode2.di_size;
				FDI->AllocationSize.QuadPart = dinode2.di_size;
				FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
				{
					SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode2.di_mode & IFMT) == IFDIR)
					FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

				FDI->FileNameLength = NameLength;
				RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 
				break;
			}

		case FileFullDirectoryInformation:
			FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
			if (!Single)
				FFI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
			else
				FFI->NextEntryOffset = 0;
			FFI->FileIndex = FileIndex;

			if (FS_VERSION == 1)
			{
				FFI->CreationTime = FFSSysTime(dinode1.di_ctime);
				FFI->LastAccessTime = FFSSysTime(dinode1.di_atime);
				FFI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
				FFI->ChangeTime = FFSSysTime(dinode1.di_mtime);
				FFI->EndOfFile.QuadPart = dinode1.di_size;
				FFI->AllocationSize.QuadPart = dinode1.di_size;
				FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)  || FFSIsReadOnly(dinode1.di_mode))
				{
					SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode1.di_mode & IFMT) == IFDIR)
					FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

				FFI->FileNameLength = NameLength;
				RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

				break;
			}
			else
			{
				FFI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
				FFI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
				FFI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
				FFI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
				FFI->EndOfFile.QuadPart = dinode2.di_size;
				FFI->AllocationSize.QuadPart = dinode2.di_size;
				FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)  || FFSIsReadOnly(dinode2.di_mode))
				{
					SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode2.di_mode & IFMT) == IFDIR)
					FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

				FFI->FileNameLength = NameLength;
				RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

				break;
			}

		case FileBothDirectoryInformation:
			FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
			if (!Single)
				FBI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
			else
				FBI->NextEntryOffset = 0;

			if (FS_VERSION == 1)
			{
				FBI->CreationTime = FFSSysTime(dinode1.di_ctime);
				FBI->LastAccessTime = FFSSysTime(dinode1.di_atime);
				FBI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
				FBI->ChangeTime = FFSSysTime(dinode1.di_mtime);

				FBI->FileIndex = FileIndex;
				FBI->EndOfFile.QuadPart = dinode1.di_size;
				FBI->AllocationSize.QuadPart = dinode1.di_size;
				FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
				{
					SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode1.di_mode & IFMT) == IFDIR)
					FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
				FBI->FileNameLength = NameLength;
				RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

				break;
			}
			else
			{
				FBI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
				FBI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
				FBI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
				FBI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);

				FBI->FileIndex = FileIndex;
				FBI->EndOfFile.QuadPart = dinode2.di_size;
				FBI->AllocationSize.QuadPart = dinode2.di_size;
				FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

				if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
				{
					SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
				}

				if ((dinode2.di_mode & IFMT) == IFDIR)
					FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
				FBI->FileNameLength = NameLength;
				RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
				dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

				break;
			}

		case FileNamesInformation:
			FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength);
			if (!Single)
				FNI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
			else
				FNI->NextEntryOffset = 0;
			FNI->FileNameLength = NameLength;
			RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength);
			dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

			break;

		default:
			break;
	}

	return dwBytes;
}
Пример #15
0
NTSTATUS
FFSLoadDiskLabel(
	PDEVICE_OBJECT  DeviceObject,
	IN PFFS_VCB     Vcb)
{
	NTSTATUS         Status;
	PFFS_SUPER_BLOCK FFSSb;
	PDISKLABEL       Disklabel;
	int              i;
	int              RootFS_VERSION;
	ULONGLONG        StartOffset = 0;
	ULONGLONG        FSOffset = 0;
	ULONGLONG        FSRootOffset = 0;

    PAGED_CODE();

	Disklabel = (PDISKLABEL)ExAllocatePoolWithTag(PagedPool, sizeof(DISKLABEL), FFS_POOL_TAG);
	
	FFSReadDisk(Vcb, (LABELSECTOR * SECTOR_SIZE + LABELOFFSET), sizeof(DISKLABEL), (PVOID)Disklabel, FALSE);

	if (Disklabel->d_magic == DISKMAGIC)
	{
		KdPrint(("FFSLoadDiskLabel() Disklabel magic ok\n"));

		Status = STATUS_SUCCESS;
	}
	else
	{
			KdPrint(("FFSLoadDiskLabel() No BSD disklabel found, trying to find BSD file system on \"normal\" partition.\n"));

			if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) &&
				(FFSSb->fs_magic == FS_UFS1_MAGIC))
			{
				FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv1 file system is found.\n"));
/*
				if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
				{
					FFSGlobal->RootPartition = i;
					FSRootOffset = FSOffset;
					RootFS_VERSION = 1;
				}
*/
				FS_VERSION = 1;
                Vcb->FSOffset[0] = 0;
                Vcb->PartitionNumber = 0;
				Vcb->ffs_super_block = FFSSb;
				Status = STATUS_SUCCESS;
                return Status;
			}
			else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) &&
					(FFSSb->fs_magic == FS_UFS2_MAGIC))
			{
				FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() \"normal\" partition of FFSv2 file system is found.\n"));
/*
				if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
				{
					FFSGlobal->RootPartition = i;
					FSRootOffset = FSOffset;
					RootFS_VERSION = 2;
				}
*/
				FS_VERSION = 2;
                Vcb->FSOffset[0] = 0;
                Vcb->PartitionNumber = 0;
				Vcb->ffs_super_block = FFSSb;
				Status = STATUS_SUCCESS;
                return Status;
			}
            else
            {
                KdPrint(("FFSLoadDiskLabel() No BSD file system was found on the \"normal\" partition.\n"));
                Status = STATUS_UNRECOGNIZED_VOLUME;
                return Status;
            }
	}

	Status = FFSGetPartition(DeviceObject, &StartOffset);
	if (!NT_SUCCESS(Status))
	{
		KdPrint(("FFSLoadDiskLabel() Slice info failed, Status %u\n", Status));
		return Status;
	}

    Vcb->PartitionNumber = FFSGlobal->PartitionNumber;

	KdPrint(("FFSLoadDiskLabel() Selected BSD Label : %d, StartOffset : %x\n", Vcb->PartitionNumber, StartOffset));

	for (i = 0; i < MAXPARTITIONS; i++)
	{
		if (Disklabel->d_partitions[i].p_fstype == FS_BSDFFS)
		{
			/* Important */
			FSOffset = Disklabel->d_partitions[i].p_offset;
			FSOffset = FSOffset * SECTOR_SIZE;
			//FSOffset = FSOffset - StartOffset;
			Vcb->FSOffset[i] = FSOffset;
			/* Important */

			KdPrint(("FFSLoadDiskLabel() Label %d, FS_BSDFFS, %x\n", i, Vcb->FSOffset[i]));

			if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) &&
				(FFSSb->fs_magic == FS_UFS1_MAGIC))
			{
				FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv1 file system is found.\n", i));

				if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
				{
					Vcb->RootPartition = i;
					FSRootOffset = FSOffset;
					RootFS_VERSION = 1;
				}

				FS_VERSION = 1;
				
				if (i == (int)Vcb->PartitionNumber)
				{
					Vcb->ffs_super_block = FFSSb;
				}

				Status = STATUS_SUCCESS;
			}
			else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) &&
					(FFSSb->fs_magic == FS_UFS2_MAGIC))
			{
				FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Label %d of FFSv2 file system is found.\n", i));

				if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
				{
					Vcb->RootPartition = i;
					FSRootOffset = FSOffset;
					RootFS_VERSION = 2;
				}

				FS_VERSION = 2;

				if (i == (int)Vcb->PartitionNumber)
				{
					Vcb->ffs_super_block = FFSSb;
				}

				Status = STATUS_SUCCESS;
			}
		}
#if 0
		else if (i == (int)FFSGlobal->PartitionNumber)
		{
			/* 선택된 BSD 파티션이 디스크에 없을 경우 Root 파티션으로 대체 */
			if (RootFS_VERSION == 1)
			{
				FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS1);
				Vcb->ffs_super_block = FFSSb;
				FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
			}
			else
			{
				FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS2);
				Vcb->ffs_super_block = FFSSb;
				FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
			}
		}
#endif
	}

	if (Vcb->ffs_super_block == NULL)
		Status = STATUS_UNRECOGNIZED_VOLUME;

	return Status;
}
Пример #16
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSUserFsRequest(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PIRP                Irp;
	PIO_STACK_LOCATION  IoStackLocation;
	ULONG               FsControlCode;
	NTSTATUS            Status;

    PAGED_CODE();

	ASSERT(IrpContext);

	ASSERT((IrpContext->Identifier.Type == FFSICX) &&
			(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

	Irp = IrpContext->Irp;

	IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
	FsControlCode =
		IoStackLocation->Parameters.FileSystemControl.FsControlCode;
#else
	FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)
			IoStackLocation)->Parameters.FileSystemControl.FsControlCode;
#endif

	switch (FsControlCode)
	{
		case FSCTL_LOCK_VOLUME:
			Status = FFSLockVolume(IrpContext);
			break;

		case FSCTL_UNLOCK_VOLUME:
			Status = FFSUnlockVolume(IrpContext);
			break;

		case FSCTL_DISMOUNT_VOLUME:
			Status = FFSDismountVolume(IrpContext);
			break;

		case FSCTL_IS_VOLUME_MOUNTED:
			Status = FFSIsVolumeMounted(IrpContext);
			break;

		case FSCTL_INVALIDATE_VOLUMES:
			Status = FFSInvalidateVolumes(IrpContext);
			break;

#if (_WIN32_WINNT >= 0x0500)
		case FSCTL_ALLOW_EXTENDED_DASD_IO:
			Status = FFSAllowExtendedDasdIo(IrpContext);
			break;
#endif //(_WIN32_WINNT >= 0x0500)

		default:

			FFSPrint((DBG_ERROR, "FFSUserFsRequest: Invalid User Request: %xh.\n", FsControlCode));
			Status = STATUS_INVALID_DEVICE_REQUEST;

			FFSCompleteIrpContext(IrpContext,  Status);
	}

	return Status;
}
Пример #17
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSCleanup(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT  DeviceObject;
	NTSTATUS        Status = STATUS_SUCCESS;
	PFFS_VCB        Vcb = 0;
	BOOLEAN	        VcbResourceAcquired = FALSE;
	PFILE_OBJECT    FileObject;
	PFFS_FCB        Fcb = 0;
	BOOLEAN	        FcbResourceAcquired = FALSE;
	BOOLEAN	        FcbPagingIoAcquired = FALSE;
	PFFS_CCB        Ccb;
	PIRP            Irp;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
			(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;
		
		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}
		
		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
			(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
		if (!ExAcquireResourceExclusiveLite(
				&Vcb->MainResource,
				IrpContext->IsSynchronous))
		{
			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		VcbResourceAcquired = TRUE;

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		if (!Fcb)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		if (Fcb->Identifier.Type == FFSVCB)
		{
			if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
				(Vcb->LockFile == FileObject))
			{
				ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
				Vcb->LockFile = NULL;

				FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
			}

			Vcb->OpenHandleCount--;

			if (!Vcb->OpenHandleCount)
			{
				IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
			}

			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
			(Fcb->Identifier.Size == sizeof(FFS_FCB)));

/*
		if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
			 !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
*/
		{
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
			if (!ExAcquireResourceExclusiveLite(
					&Fcb->MainResource,
					IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				_SEH2_LEAVE;
			}

			FcbResourceAcquired = TRUE;
		}
		
		Ccb = (PFFS_CCB)FileObject->FsContext2;

		if (!Ccb)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		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 = FFSFlushFile(Fcb);
			}

			_SEH2_LEAVE;
		}
		
		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
			(Ccb->Identifier.Size == sizeof(FFS_CCB)));		
		Irp = IrpContext->Irp;

		Fcb->OpenHandleCount--;

		if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
		{
			Fcb->NonCachedOpenCount--;
		}

		Vcb->OpenFileHandleCount--;

		if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))
		{
			SetFlag(Fcb->Flags, FCB_DELETE_PENDING);

			if (IsDirectory(Fcb))
			{
				FsRtlNotifyFullChangeDirectory(
											Vcb->NotifySync,
											&Vcb->NotifyList,
											Fcb,
											NULL,
											FALSE,
											FALSE,
											0,
											NULL,
											NULL,
											NULL);
			}
		}

		if (IsDirectory(Fcb))
		{
			FsRtlNotifyCleanup(
				Vcb->NotifySync,
				&Vcb->NotifyList,
				Ccb);
		}
		else
		{
			//
			// 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)
				{
					FFSPrint((
						DBG_INFO, ": %-16.16s %-31s %s\n",
						FFSGetCurrentProcessName(),
						"FastIoIsPossible",
						Fcb->AnsiFileName.Buffer));

					Fcb->Header.IsFastIoPossible = FastIoIsPossible;
				}
			}
		}

		if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
			 (Fcb->NonCachedOpenCount != 0) &&
			 (Fcb->NonCachedOpenCount == 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);
			}

			ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
			ExReleaseResourceLite(&(Fcb->PagingIoResource));

			CcPurgeCacheSection(&Fcb->SectionObject,
								NULL,
								0,
								FALSE);
		}

#if !FFS_READ_ONLY
		if (Fcb->OpenHandleCount == 0)
		{
			if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
			{
				BOOLEAN	 bDeleted = FALSE;

				//
				//  Have to delete this file...
				//
#ifdef _MSC_VER
#pragma prefast( suppress: 28137, "by design" )
#endif
				if (!ExAcquireResourceExclusiveLite(
						 &Fcb->PagingIoResource,
						 IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					_SEH2_LEAVE;
				}

				FcbPagingIoAcquired = TRUE;

				bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb);

				if (bDeleted)
				{
					if (IsDirectory(Fcb))
					{
						FFSNotifyReportChange(IrpContext, Vcb, Fcb,
												FILE_NOTIFY_CHANGE_DIR_NAME,
												FILE_ACTION_REMOVED);
					}
					else
					{
						FFSNotifyReportChange(IrpContext, Vcb, Fcb,
												FILE_NOTIFY_CHANGE_FILE_NAME,
												FILE_ACTION_REMOVED);
					}
				}

				if (FcbPagingIoAcquired)
				{
					ExReleaseResourceForThreadLite(
						&Fcb->PagingIoResource,
						ExGetCurrentResourceThread());

					FcbPagingIoAcquired = FALSE;
				}

/*
				if (bDeleted)
				{
					FFSPurgeFile(Fcb, FALSE);
				}
*/
			}
		}
#endif // !FFS_READ_ONLY

		if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap)
		{
			FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n",
								  Fcb->AnsiFileName.Buffer));

			CcUninitializeCacheMap(
					FileObject,
					(PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
					NULL);
		}

		if (!Fcb->OpenHandleCount)
		{
			IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
		}

		FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n",
			Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));

		Status = STATUS_SUCCESS;

		if (FileObject)
		{
			SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
		}
	}

	_SEH2_FINALLY
	{
	   
		if (FcbPagingIoAcquired)
		{
			ExReleaseResourceForThreadLite(
				&Fcb->PagingIoResource,
				ExGetCurrentResourceThread());
		}

		if (FcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
				&Fcb->MainResource,
				ExGetCurrentResourceThread());
		}

		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
				&Vcb->MainResource,
				ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				FFSQueueRequest(IrpContext);
			}
			else
			{
				IrpContext->Irp->IoStatus.Status = Status;

				FFSCompleteIrpContext(IrpContext, Status);
			}
		}
	} _SEH2_END;

	return Status;
}
Пример #18
0
NTSTATUS
FFSv1WriteInode(
	IN PFFS_IRP_CONTEXT     IrpContext,
	IN PFFS_VCB             Vcb,
	IN PFFSv1_INODE         dinode1,
	IN ULONGLONG            offset,
	IN PVOID                Buffer,
	IN ULONG                size,
	IN BOOLEAN              bWriteToDisk,
	OUT PULONG              dwRet)
{
	PFFS_BDL    ffs_bdl = NULL;
	ULONG       blocks, i;
	NTSTATUS    Status = STATUS_UNSUCCESSFUL;
	ULONG       Totalblocks;
	LONGLONG    AllocSize;

	if (dwRet)
	{
		*dwRet = 0;
	}

	Totalblocks = (dinode1->di_blocks);
	AllocSize = ((LONGLONG)(FFSDataBlocks(Vcb, Totalblocks)) << BLOCK_BITS);

	if ((LONGLONG)offset >= AllocSize)
	{
		FFSPrint((DBG_ERROR, "FFSv1WriteInode: beyond the file range.\n"));
		return STATUS_SUCCESS;
	}

	if ((LONGLONG)offset + size > AllocSize)
	{
		size = (ULONG)(AllocSize - offset);
	}

	blocks = FFSv1BuildBDL(IrpContext, Vcb, dinode1, offset, size, &ffs_bdl);

	if (blocks <= 0)
	{
		return STATUS_SUCCESS;
	}

#if DBG
	{
		ULONG   dwTotal = 0;
		FFSPrint((DBG_INFO, "FFSv1WriteInode: BDLCount = %xh Size=%xh Off=%xh\n",
					blocks, size, offset));
		for(i = 0; i < blocks; i++)
		{
			FFSPrint((DBG_INFO, "FFSv1WriteInode: Lba=%I64xh Len=%xh Off=%xh\n",
						ffs_bdl[i].Lba, ffs_bdl[i].Length, ffs_bdl[i].Offset));
			dwTotal += ffs_bdl[i].Length;
		}

		if (dwTotal != size)
		{
			FFSBreakPoint();
		}

		FFSPrint((DBG_INFO, "FFSv1WriteInode: Total = %xh (WriteToDisk=%x)\n",
					dwTotal, bWriteToDisk));
	}
#endif

	if (bWriteToDisk)
	{

#if 0
		for(i = 0; i < blocks; i++)
		{
			{
				CcFlushCache(&(Vcb->SectionObject),
						(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
						ffs_bdl[i].Length,
						NULL);

				if (Vcb->SectionObject.DataSectionObject != NULL)
				{
					ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
					ExReleaseResource(&Vcb->PagingIoResource);

					CcPurgeCacheSection(&(Vcb->SectionObject),
							(PLARGE_INTEGER)&(ffs_bdl[i].Lba),
							ffs_bdl[i].Length,
							FALSE);
				}
			}
		}
#endif

		// assume offset is aligned.
		Status = FFSReadWriteBlocks(IrpContext, Vcb, ffs_bdl, size, blocks, FALSE);
	}
	else
	{
		for(i = 0; i < blocks; i++)
		{
			if(!FFSSaveBuffer(IrpContext, Vcb, ffs_bdl[i].Lba, ffs_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ffs_bdl[i].Offset)))
				goto errorout;
		}

		if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
		{
			FFSPrint((DBG_USER, "FFSv1WriteInode is starting FlushingDpc...\n"));
			FFSStartFloppyFlushDpc(Vcb, NULL, NULL);
		}

		Status = STATUS_SUCCESS;
	}

errorout:

	if (ffs_bdl)
		ExFreePool(ffs_bdl);

	if (NT_SUCCESS(Status))
	{
		if (dwRet) *dwRet = size;
	}

	return Status;
}
Пример #19
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSVerifyVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT          DeviceObject;
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	PFFS_SUPER_BLOCK        FFSSb = NULL;
	PFFS_VCB                Vcb = 0;
	BOOLEAN                 VcbResourceAcquired = FALSE;
	BOOLEAN                 GlobalResourceAcquired = FALSE;
	PIRP                    Irp;
	PIO_STACK_LOCATION      IoStackLocation;
	ULONG                   ChangeCount;
	ULONG                   dwReturn;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;
		//
		// This request is not allowed on the main device object
		//
		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		ExAcquireResourceExclusiveLite(
				&FFSGlobal->Resource,
				TRUE);

		GlobalResourceAcquired = TRUE;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ExAcquireResourceExclusiveLite(
				&Vcb->MainResource,
				TRUE);

		VcbResourceAcquired = TRUE;

		if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME))
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		if (!IsMounted(Vcb))
		{
			Status = STATUS_WRONG_VOLUME;
			_SEH2_LEAVE;
		}

		dwReturn = sizeof(ULONG);
		Status = FFSDiskIoControl(
				Vcb->TargetDeviceObject,
				IOCTL_DISK_CHECK_VERIFY,
				NULL,
				0,
				&ChangeCount,
				&dwReturn);

		if (ChangeCount != Vcb->ChangeCount)
		{
			Status = STATUS_WRONG_VOLUME;
			_SEH2_LEAVE;
		}

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		if (((((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS1)) != NULL) && (FFSSb->fs_magic == FS_UFS1_MAGIC)) ||
			 (((FFSSb = FFSLoadSuper(Vcb, TRUE, SBLOCK_UFS2)) != NULL) && (FFSSb->fs_magic == FS_UFS2_MAGIC))) &&
				(memcmp(FFSSb->fs_id, SUPER_BLOCK->fs_id, 8) == 0) &&
				(memcmp(FFSSb->fs_volname, SUPER_BLOCK->fs_volname, 16) == 0))
		{
			ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

			if (FFSIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject))
			{
				SetFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}
			else
			{
				ClearFlag(Vcb->Flags, VCB_WRITE_PROTECTED);
			}

			FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify succeeded.\n"));

			Status = STATUS_SUCCESS;
		}
		else
		{
			Status = STATUS_WRONG_VOLUME;

			FFSPurgeVolume(Vcb, FALSE);

			SetFlag(Vcb->Flags, VCB_DISMOUNT_PENDING);

			ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);

			FFSPrint((DBG_INFO, "FFSVerifyVolume: Volume verify failed.\n"));
		}
	}

	_SEH2_FINALLY
	{
		if (FFSSb)
			ExFreePool(FFSSb);

		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (GlobalResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&FFSGlobal->Resource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			FFSCompleteIrpContext(IrpContext,  Status);
		}
	} _SEH2_END;

	return Status;
}
Пример #20
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSDismountVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT  DeviceObject;
	NTSTATUS        Status = STATUS_UNSUCCESSFUL;
	PFFS_VCB        Vcb = 0;
	BOOLEAN         VcbResourceAcquired = FALSE;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		//
		// This request is not allowed on the main device object
		//
		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			_SEH2_LEAVE;
		}

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ASSERT(IsMounted(Vcb));

		ExAcquireResourceExclusiveLite(
				&Vcb->MainResource,
				TRUE);

		VcbResourceAcquired = TRUE;

		if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
		{
			Status = STATUS_VOLUME_DISMOUNTED;
			_SEH2_LEAVE;
		}

		/*        
		if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
		{
			FFSPrint((DBG_ERROR, "FFSDismount: Volume is not locked.\n"));

			Status = STATUS_ACCESS_DENIED;
			_SEH2_LEAVE;
		}
		*/

		FFSFlushFiles(Vcb, FALSE);

		FFSFlushVolume(Vcb, FALSE);

		FFSPurgeVolume(Vcb, TRUE);

		ExReleaseResourceForThreadLite(
				&Vcb->MainResource,
				ExGetCurrentResourceThread());

		VcbResourceAcquired = FALSE;

		FFSCheckDismount(IrpContext, Vcb, TRUE);

		FFSPrint((DBG_INFO, "FFSDismount: Volume dismount pending.\n"));

		Status = STATUS_SUCCESS;
	}
	_SEH2_FINALLY
	{
		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			FFSCompleteIrpContext(IrpContext,  Status);
		}
	} _SEH2_END;

	return Status;
}
Пример #21
0
NTSTATUS
FFSWriteVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_CCB            Ccb = NULL;
	PFFS_FCBVCB         FcbOrVcb  = NULL;
	PFILE_OBJECT        FileObject  = NULL;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;

		ASSERT(FcbOrVcb);

		if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		// For the case of "Direct Access Storage Device", we
		// need flush/purge the cache

		if (Ccb != NULL)
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			Status = FFSPurgeVolume(Vcb, TRUE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;

			if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
			{
				if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
				{
					Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
				}
			}

			{
				FFS_BDL BlockArray;

				if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
						(Length & (SECTOR_SIZE - 1)))
				{
					Status = STATUS_INVALID_PARAMETER;
					__leave;
				}

				Status = FFSLockUserBuffer(
							IrpContext->Irp,
							Length,
							IoReadAccess);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				BlockArray.Irp = NULL;
				BlockArray.Lba = ByteOffset.QuadPart;;
				BlockArray.Offset = 0;
				BlockArray.Length = Length;

				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							&BlockArray,
							Length,
							1,
							FALSE);
				Irp = IrpContext->Irp;

				__leave;
			}
		}                    

		if (Nocache &&
				(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 (ByteOffset.QuadPart >=
				Vcb->PartitionInformation.PartitionLength.QuadPart)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_END_OF_FILE;
			__leave;
		}

#if FALSE

		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))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;

				__leave;
			}
		}

#endif

		if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcFlushCache(&(Vcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcPurgeCacheSection(&(Vcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Vcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);

			FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/

			if (Ccb)
			{
				if (!ExAcquireResourceSharedLite(
							&Vcb->PagingIoResource,
							IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				PagingIoResourceAcquired = TRUE;
			}
		}

		if (!Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart
			)
			{
				Length = (ULONG) (
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{

				CcPrepareMdlWrite(
						Vcb->StreamObj,
						&ByteOffset,
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();

					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(Vcb->StreamObj,
							(PLARGE_INTEGER)(&ByteOffset),
							Length,
							TRUE,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
				FFSAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;
			}
		}
		else
		{
			PFFS_BDL            ffs_bdl = NULL;
			ULONG               Blocks = 0;

			LONGLONG            DirtyStart;
			LONGLONG            DirtyLba;
			LONGLONG            DirtyLength;
			LONGLONG            RemainLength;

			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart)
			{
				Length = (ULONG)(
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			ffs_bdl = ExAllocatePool(PagedPool, 
					(Length / Vcb->BlockSize) *
					sizeof(FFS_BDL));

			if (!ffs_bdl)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			DirtyLba = ByteOffset.QuadPart;
			RemainLength = (LONGLONG)Length;

			while (RemainLength > 0)
			{
				DirtyStart = DirtyLba;

				if (FFSLookupMcbEntry(Vcb, 
							DirtyStart,
							&DirtyLba,
							&DirtyLength,
							(PLONGLONG)NULL,
							(PLONGLONG)NULL,
							(PULONG)NULL))
				{

					if (DirtyLba == -1)
					{
						DirtyLba = DirtyStart + DirtyLength;

						RemainLength = ByteOffset.QuadPart + 
							(LONGLONG)Length -
							DirtyLba;
						continue;
					}

					ffs_bdl[Blocks].Irp = NULL;
					ffs_bdl[Blocks].Lba = DirtyLba;
					ffs_bdl[Blocks].Offset = (ULONG)((LONGLONG)Length +
							DirtyStart -
							RemainLength - 
							DirtyLba);

					if (DirtyLba + DirtyLength > DirtyStart + RemainLength)
					{
						ffs_bdl[Blocks].Length = (ULONG)(DirtyStart +
								RemainLength -
								DirtyLba);
						RemainLength = 0;
					}
					else
					{
						ffs_bdl[Blocks].Length = (ULONG)DirtyLength;
						RemainLength =  (DirtyStart + RemainLength) -
							(DirtyLba + DirtyLength);
					}

					DirtyLba = DirtyStart + DirtyLength;
					Blocks++;
				}
				else
				{
					if (Blocks == 0)
					{
						if (ffs_bdl)
							ExFreePool(ffs_bdl);

						//
						// Lookup fails at the first time, ie. 
						// no dirty blocks in the run
						//

						FFSBreakPoint();

						if (RemainLength == (LONGLONG)Length)
							Status = STATUS_SUCCESS;
						else
							Status = STATUS_UNSUCCESSFUL;

						__leave;
					}
					else
					{
						break;
					}
				}
			}

			if (Blocks > 0)
			{
				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							ffs_bdl,
							Length,
							Blocks,
							FALSE);
				Irp = IrpContext->Irp;

				if (NT_SUCCESS(Status))
				{
					ULONG   i;

					for (i = 0; i < Blocks; i++)
					{
						FFSRemoveMcbEntry(Vcb,
								ffs_bdl[i].Lba,
								ffs_bdl[i].Length);
					}
				}

				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				if (!Irp)
					__leave;

			}
			else
			{
				if (ffs_bdl)
					ExFreePool(ffs_bdl);

				Irp->IoStatus.Information = Length;

				Status = STATUS_SUCCESS;
				__leave;
			}
		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if(!bDeferred)
					{
						Status = FFSLockUserBuffer(
								IrpContext->Irp,
								Length,
								IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;
}
Пример #22
0
BOOLEAN
FFSIsDirectoryEmpty(
	PFFS_VCB Vcb,
	PFFS_FCB Dcb)
{
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;

	PFFS_DIR_ENTRY          pTarget = NULL;

	ULONG                   dwBytes = 0;
	ULONG                   dwRet;

	BOOLEAN                 bRet = TRUE;

    PAGED_CODE();

	if (!IsFlagOn(Dcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
		return TRUE;

	_SEH2_TRY
	{
		pTarget = (PFFS_DIR_ENTRY)ExAllocatePoolWithTag(PagedPool,
				FFS_DIR_REC_LEN(FFS_NAME_LEN), FFS_POOL_TAG);
		if (!pTarget)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			_SEH2_LEAVE;
		}

		dwBytes = 0;


		while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart)
		{
			RtlZeroMemory(pTarget, FFS_DIR_REC_LEN(FFS_NAME_LEN));

			if (FS_VERSION == 1)
			{
				Status = FFSv1ReadInode(
						NULL,
						Vcb,
						Dcb->dinode1,
						dwBytes,
						(PVOID)pTarget,
						FFS_DIR_REC_LEN(FFS_NAME_LEN),
						&dwRet);
			}
			else
			{
				Status = FFSv2ReadInode(
						NULL,
						Vcb,
						Dcb->dinode2,
						dwBytes,
						(PVOID)pTarget,
						FFS_DIR_REC_LEN(FFS_NAME_LEN),
						&dwRet);
			}

			if (!NT_SUCCESS(Status))
			{
				FFSPrint((DBG_ERROR, "FFSRemoveEntry: Reading Directory Content error.\n"));
				_SEH2_LEAVE;
			}

			if (pTarget->d_ino)
			{
				if (pTarget->d_namlen == 1 && pTarget->d_name[0] == '.')
				{
				}
				else if (pTarget->d_namlen == 2 && pTarget->d_name[0] == '.' && 
						pTarget->d_name[1] == '.')
				{
				}
				else
				{
					bRet = FALSE;
					break;
				}
			}
			else
			{
				break;
			}

			dwBytes += pTarget->d_reclen;
		}
	}

	_SEH2_FINALLY
	{
		if (pTarget != NULL)
		{
			ExFreePool(pTarget);
		}
	} _SEH2_END;

	return bRet;
}
Пример #23
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSInvalidateVolumes(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status;
	PIRP                Irp;
	PIO_STACK_LOCATION  IrpSp;

	HANDLE              Handle;

	PLIST_ENTRY         ListEntry;

	PFILE_OBJECT        FileObject;
	PDEVICE_OBJECT      DeviceObject;
	BOOLEAN             GlobalResourceAcquired = FALSE;

	LUID Privilege = {SE_TCB_PRIVILEGE, 0};

	_SEH2_TRY
	{
		Irp   = IrpContext->Irp;
		IrpSp = IoGetCurrentIrpStackLocation(Irp);

		if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode))
		{
			Status = STATUS_PRIVILEGE_NOT_HELD;
			_SEH2_LEAVE;
		}

		if (
#if !defined(_GNU_NTIFS_) || defined(__REACTOS__)
				IrpSp->Parameters.FileSystemControl.InputBufferLength
#else
				((PEXTENDED_IO_STACK_LOCATION)(IrpSp))->
				Parameters.FileSystemControl.InputBufferLength
#endif
				!= sizeof(HANDLE))
		{
			Status = STATUS_INVALID_PARAMETER;

			_SEH2_LEAVE;
		}

		Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;

		Status = ObReferenceObjectByHandle(Handle,
				0,
				*IoFileObjectType,
				KernelMode,
				(void **)&FileObject,
				NULL);

		if (!NT_SUCCESS(Status))
		{
			_SEH2_LEAVE;
		}
		else
		{
			ObDereferenceObject(FileObject);
			DeviceObject = FileObject->DeviceObject;
		}

		FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FileObject=%xh ...\n", FileObject));

		ExAcquireResourceExclusiveLite(
				&FFSGlobal->Resource,
				TRUE);

		GlobalResourceAcquired = TRUE;

		ListEntry = FFSGlobal->VcbList.Flink;

		while (ListEntry != &FFSGlobal->VcbList)
		{
			PFFS_VCB Vcb;

			Vcb = CONTAINING_RECORD(ListEntry, FFS_VCB, Next);

			ListEntry = ListEntry->Flink;

			FFSPrint((DBG_INFO, "FFSInvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh...\n", Vcb, Vcb->Vpb));
			if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject))
			{
				ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
				FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSPurgeVolume...\n"));
				FFSPurgeVolume(Vcb, FALSE);
				ClearFlag(Vcb->Flags, VCB_MOUNTED);
				ExReleaseResourceLite(&Vcb->MainResource);

				//
				// Vcb is still attached on the list ......
				//

				if (ListEntry->Blink == &Vcb->Next)
				{
					FFSPrint((DBG_INFO, "FFSInvalidateVolumes: FFSCheckDismount...\n"));
					FFSCheckDismount(IrpContext, Vcb, FALSE);
				}
			}
		}
	}

	_SEH2_FINALLY
	{
		if (GlobalResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&FFSGlobal->Resource,
					ExGetCurrentResourceThread());
		}

		FFSCompleteIrpContext(IrpContext, Status);
	} _SEH2_END;

	return Status;
}
Пример #24
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSPurgeVolume(
	IN PFFS_VCB Vcb,
	IN BOOLEAN  FlushBeforePurge)
{
	PFFS_FCB        Fcb;
	LIST_ENTRY      FcbList;
	PLIST_ENTRY     ListEntry;
	PFCB_LIST_ENTRY FcbListEntry;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) ||
				IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
		{
			FlushBeforePurge = FALSE;
		}

		FcbListEntry= NULL;
		InitializeListHead(&FcbList);

		for (ListEntry = Vcb->FcbList.Flink;
				ListEntry != &Vcb->FcbList;
				ListEntry = ListEntry->Flink)
		{
			Fcb = CONTAINING_RECORD(ListEntry, FFS_FCB, Next);

			Fcb->ReferenceCount++;

			FFSPrint((DBG_INFO, "FFSPurgeVolume: %s refercount=%xh\n", Fcb->AnsiFileName.Buffer, Fcb->ReferenceCount));

			FcbListEntry = ExAllocatePoolWithTag(PagedPool, sizeof(FCB_LIST_ENTRY), FFS_POOL_TAG);

			if (FcbListEntry)
			{
				FcbListEntry->Fcb = Fcb;

				InsertTailList(&FcbList, &FcbListEntry->Next);
			}
			else
			{
				FFSPrint((DBG_ERROR, "FFSPurgeVolume: Error allocating FcbListEntry ...\n"));
			}
		}

		while (!IsListEmpty(&FcbList))
		{
			ListEntry = RemoveHeadList(&FcbList);

			FcbListEntry = CONTAINING_RECORD(ListEntry, FCB_LIST_ENTRY, Next);

			Fcb = FcbListEntry->Fcb;

			if (ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						TRUE))
			{
				FFSPurgeFile(Fcb, FlushBeforePurge);

				if (!Fcb->OpenHandleCount && Fcb->ReferenceCount == 1)
				{
					RemoveEntryList(&Fcb->Next);
					FFSFreeFcb(Fcb);
				}
				else
				{
					ExReleaseResourceForThreadLite(
						&Fcb->MainResource,
						ExGetCurrentResourceThread());
				}
			}

			ExFreePool(FcbListEntry);
		}

		if (FlushBeforePurge)
		{
			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResourceLite(&Vcb->PagingIoResource);

			CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL);
		}

		if (Vcb->SectionObject.ImageSectionObject)
		{
			MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite);
		}

		if (Vcb->SectionObject.DataSectionObject)
		{
			CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE);
		}

		FFSPrint((DBG_INFO, "FFSPurgeVolume: Volume flushed and purged.\n"));
	}
	_SEH2_FINALLY
	{
		// Nothing
	} _SEH2_END;

	return STATUS_SUCCESS;
}
Пример #25
0
NTSTATUS
FFSWriteFile(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb  = NULL;
	PFFS_FCB            Fcb  = NULL;
	PFFS_CCB            Ccb =  NULL;
	PFILE_OBJECT        FileObject  = NULL;
	PFILE_OBJECT        CacheObject;

	PDEVICE_OBJECT      DeviceObject  = NULL;

	PIRP                Irp  = NULL;
	PIO_STACK_LOCATION  IoStackLocation  = NULL;

	ULONG               Length;
	ULONG               ReturnedLength = 0;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bNeedExtending = FALSE;
	BOOLEAN             bAppendFile = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer = NULL;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb);

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		/*
		if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
		{
			Status = STATUS_FILE_DELETED;
			__leave;
		}

		if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
		{
			Status = STATUS_DELETE_PENDING;
			__leave;
		}
		*/

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		if (Nocache &&
				(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 FALSE
		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))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;
				__leave;
			}
		}

#endif

		if (IsEndOfFile(ByteOffset))
		{
			bAppendFile = TRUE;
			ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
		}

		if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		//
		//  Do flushing for such cases
		//
		if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Fcb->MainResource, 
					IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));

			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcFlushCache(&(Fcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));
			ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);

			if (!NT_SUCCESS(Irp->IoStatus.Status)) 
			{
				Status = Irp->IoStatus.Status;
				__leave;
			}

			ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
			ExReleaseResource(&Fcb->PagingIoResource);

			CcPurgeCacheSection(&(Fcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Fcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);

			FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
			Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/
			if (!ExAcquireResourceSharedLite(
						&Fcb->PagingIoResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			PagingIoResourceAcquired = TRUE;
		}

		if (!PagingIo)
		{
			if (!FsRtlCheckLockForWriteAccess(
						&Fcb->FileLockAnchor,
						Irp))
			{
				Status = STATUS_FILE_LOCK_CONFLICT;
				__leave;
			}
		}

		if (Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Fcb->Header.AllocationSize.QuadPart)
			{
				if (ByteOffset.QuadPart >= 
						Fcb->Header.AllocationSize.QuadPart)
				{
					Status = STATUS_SUCCESS;
					Irp->IoStatus.Information = 0;
					__leave;
				}
				else
				{
					if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart))
					{
						Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart
								- ByteOffset.QuadPart);
					}
				}
			}
		}

		if (!Nocache)
		{
			if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
			{
				__leave;
			}

			if (FileObject->PrivateCacheMap == NULL)
			{
				CcInitializeCacheMap(
						FileObject,
						(PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
						FALSE,
						&FFSGlobal->CacheManagerCallbacks,
						Fcb);

				CcSetReadAheadGranularity(
						FileObject,
						READ_AHEAD_GRANULARITY);

				CcSetFileSizes(
						FileObject, 
						(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
			}

			CacheObject = FileObject;

			//
			//  Need extending the size of inode ?
			//
			if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) >
						(ULONG)(Fcb->Header.FileSize.QuadPart)))
			{

				LARGE_INTEGER   ExtendSize;
				LARGE_INTEGER   FileSize;

				bNeedExtending = TRUE;
				FileSize = Fcb->Header.FileSize;
				ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);

				if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
				{
					if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize))
					{
						Status = STATUS_INSUFFICIENT_RESOURCES;
						__leave;
					}
				}

				{
					Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
					Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart;
				}

				if (FileObject->PrivateCacheMap)
				{
					CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

					if (ByteOffset.QuadPart > FileSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, 
								ByteOffset.QuadPart - FileSize.QuadPart);
					}

					if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart)
					{
						FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, 
								Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
					}
				}

				if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1))
				{
					Status = STATUS_SUCCESS;
				}

				FFSNotifyReportChange(
						IrpContext,
						Vcb,
						Fcb,
						FILE_NOTIFY_CHANGE_SIZE,
						FILE_ACTION_MODIFIED);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{
				CcPrepareMdlWrite(
						CacheObject,
						(&ByteOffset),
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)
				{
					FFSBreakPoint();
					Status = STATUS_INVALID_USER_BUFFER;
					__leave;
				}

				if (!CcCopyWrite(
							CacheObject,
							(PLARGE_INTEGER)&ByteOffset,
							Length,
							IrpContext->IsSynchronous,
							Buffer))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				Status = Irp->IoStatus.Status;
			}

			if (NT_SUCCESS(Status))
			{
				Irp->IoStatus.Information = Length;

				if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
				{
					FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n"));
					FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject);
				}
			}
		}
		else
		{
			ReturnedLength = Length;

			Status = FFSLockUserBuffer(
					IrpContext->Irp,
					Length,
					IoReadAccess);

			if (!NT_SUCCESS(Status))
			{
				__leave;
			}

			Irp->IoStatus.Status = STATUS_SUCCESS;
			Irp->IoStatus.Information = Length;

			Status = 
				FFSv1WriteInode(
						IrpContext,
						Vcb,
						Fcb->dinode1,
						(ULONGLONG)(ByteOffset.QuadPart),
						NULL,
						Length,
						TRUE,
						&ReturnedLength);

			Irp = IrpContext->Irp;

		}
	}

	__finally
	{
		if (PagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (MainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Irp)
			{
				if (Status == STATUS_PENDING)
				{
					if (!bDeferred)
					{
						Status = FFSLockUserBuffer(
									IrpContext->Irp,
									Length,
									IoReadAccess);

						if (NT_SUCCESS(Status))
						{
							Status = FFSQueueRequest(IrpContext);
						}
						else
						{
							FFSCompleteIrpContext(IrpContext, Status);
						}
					}
				}
				else
				{
					if (NT_SUCCESS(Status))
					{
						if (SynchronousIo && !PagingIo)
						{
							FileObject->CurrentByteOffset.QuadPart =
								ByteOffset.QuadPart + Irp->IoStatus.Information;
						}

						if (!PagingIo)
						{
							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
							SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
						}
					}

					FFSCompleteIrpContext(IrpContext, Status);
				}
			}
			else
			{
				FFSFreeIrpContext(IrpContext);
			}
		}
	}

	return Status;

}
Пример #26
0
__drv_mustHoldCriticalRegion
NTSTATUS
FFSClose(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT  DeviceObject;
	NTSTATUS        Status = STATUS_SUCCESS;
	PFFS_VCB        Vcb = 0;
	BOOLEAN         VcbResourceAcquired = FALSE;
	PFILE_OBJECT    FileObject;
	PFFS_FCB        Fcb = 0;
	BOOLEAN         FcbResourceAcquired = FALSE;
	PFFS_CCB        Ccb;
	BOOLEAN         FreeVcb = FALSE;

    PAGED_CODE();

	_SEH2_TRY
	{
		ASSERT(IrpContext != NULL);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		if (DeviceObject == FFSGlobal->DeviceObject)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		Vcb = (PFFS_VCB) DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ASSERT(IsMounted(Vcb));

		if (!ExAcquireResourceExclusiveLite(
					&Vcb->MainResource,
					IrpContext->IsSynchronous))
		{
			FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
						Vcb->OpenFileHandleCount, Vcb->ReferenceCount));

			Status = STATUS_PENDING;
			_SEH2_LEAVE;
		}

		VcbResourceAcquired = TRUE;

		FileObject = IrpContext->FileObject;

		if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
		{
			Fcb = IrpContext->Fcb;
			Ccb = IrpContext->Ccb;
		}
		else
		{
			Fcb = (PFFS_FCB)FileObject->FsContext;

			if (!Fcb)
			{
				Status = STATUS_SUCCESS;
				_SEH2_LEAVE;
			}

			ASSERT(Fcb != NULL);

			Ccb = (PFFS_CCB)FileObject->FsContext2;
		}

		if (Fcb->Identifier.Type == FFSVCB)
		{
			Vcb->ReferenceCount--;

			if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
			{
				FreeVcb = TRUE;
			}

			if (Ccb)
			{
				FFSFreeCcb(Ccb);
				if (FileObject)
				{
					FileObject->FsContext2 = Ccb = NULL;
				}
			}

			Status = STATUS_SUCCESS;

			_SEH2_LEAVE;
		}

		if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB))
		{
#if DBG
			FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
			ExAcquireResourceExclusiveLite(
					&FFSGlobal->CountResource,
					TRUE);

			FFSGlobal->IRPCloseCount++;

			ExReleaseResourceForThreadLite(
					&FFSGlobal->CountResource,
					ExGetCurrentResourceThread());
#endif
			_SEH2_LEAVE;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		/*        
			  if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) && 
			  (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
			  */
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				_SEH2_LEAVE;
			}

			FcbResourceAcquired = TRUE;
		}

		if (!Ccb)
		{
			Status = STATUS_SUCCESS;
			_SEH2_LEAVE;
		}

		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
				(Ccb->Identifier.Size == sizeof(FFS_CCB)));

		Fcb->ReferenceCount--;
		Vcb->ReferenceCount--;

		if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
		{
			FreeVcb = TRUE;
		}

		FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
					Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));

		if (Ccb)
		{
			FFSFreeCcb(Ccb);

			if (FileObject)
			{
				FileObject->FsContext2 = Ccb = NULL;
			}
		}

		if (!Fcb->ReferenceCount)
		{
			//
			// Remove Fcb from Vcb->FcbList ...
			//

			RemoveEntryList(&Fcb->Next);

			FFSFreeFcb(Fcb);

			FcbResourceAcquired = FALSE;
		}

		Status = STATUS_SUCCESS;
	}

	_SEH2_FINALLY
	{
		if (FcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				FFSQueueCloseRequest(IrpContext);
#if 0
/*
				Status = STATUS_SUCCESS;

				if (IrpContext->Irp != NULL)
				{
					IrpContext->Irp->IoStatus.Status = Status;

					FFSCompleteRequest(
							IrpContext->Irp,
							(BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
							(CCHAR)
							(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));

					IrpContext->Irp = NULL;
				}
*/
#endif
			}
			else
			{
				FFSCompleteIrpContext(IrpContext, Status);

				if (FreeVcb)
				{
					ExAcquireResourceExclusiveLite(
							&FFSGlobal->Resource, TRUE);

					FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);

					FFSRemoveVcb(Vcb);

					ExReleaseResourceForThreadLite(
							&FFSGlobal->Resource,
							ExGetCurrentResourceThread());

					FFSFreeVcb(Vcb);
				}
			}
		}
	} _SEH2_END;

	return Status;
}