⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext2fs.c

📁 ext2 file system driver for win nt
💻 C
📖 第 1 页 / 共 5 页
字号:
		
		if (Fcb->Identifier.Type == VCB)
		{
			if (Vcb->Flags & VCB_VOLUME_LOCKED)
			{
				Vcb->Flags &= ~VCB_VOLUME_LOCKED;
				
				Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
			}
			
			Vcb->ReferenceCount--;
			
			if (!Vcb->ReferenceCount && Vcb->Flags & VCB_DISMOUNT_PENDING)
			{
				FreeVcb = TRUE;
			}
			
			Status = STATUS_SUCCESS;
			
			__leave;
		}
		
		ASSERT((Fcb->Identifier.Type == FCB) &&
			(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
		
#ifndef EXT2_RO
		if (!Fcb->IsPageFile)
#endif
		{
			if (!ExAcquireResourceExclusiveLite(
				&Fcb->MainResource,
				IrpContext->IsSynchronous ))
			{
				Status = STATUS_PENDING;
				__leave;
			}
			
			FcbResourceAcquired = TRUE;
		}
		
		Ccb = (PEXT2_CCB) FileObject->FsContext2;
		
		ASSERT(Ccb != NULL);
		
		ASSERT((Ccb->Identifier.Type == CCB) &&
			(Ccb->Identifier.Size == sizeof(EXT2_CCB)));
		
		Fcb->ReferenceCount--;
		
		Vcb->ReferenceCount--;

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

		Ext2FreeCcb(Ccb);
		
		if (!Fcb->ReferenceCount)
		{
			ExReleaseResourceForThreadLite(
				&Fcb->MainResource,
				ExGetCurrentResourceThread() );
			
			FcbResourceAcquired = FALSE;
			
			Ext2FreeFcb(Fcb);
		}
		
		Status = STATUS_SUCCESS;
    }
    __finally
    {
	    if (VcbResourceAcquired)
	    {
		    ExReleaseResourceForThreadLite(
			    &Vcb->MainResource,
			    ExGetCurrentResourceThread()  );
	    }
	    
	    if (FcbResourceAcquired)
	    {
		    ExReleaseResourceForThreadLite(
			    &Fcb->MainResource,
			    ExGetCurrentResourceThread() );
	    }
	    
	    if (!IrpContext->ExceptionInProgress)
	    {
		    if (Status == STATUS_PENDING)
		    {
		    
			    Status = STATUS_SUCCESS;
			    
			    if (IrpContext->Irp != NULL)
			    {
				    IrpContext->Irp->IoStatus.Status = Status;
				    
				    Ext2CompleteRequest(
					    IrpContext->Irp,
					    (CCHAR)
					    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
					    );
				    
				    IrpContext->Irp = NULL;
			    }
			    
			    Ext2QueueCloseRequest(IrpContext);
		    }
		    else
		    {
			    if (IrpContext->Irp != NULL)
			    {
				    IrpContext->Irp->IoStatus.Status = Status;
				    
				    Ext2CompleteRequest(
					    IrpContext->Irp,
					    (CCHAR)
					    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
					    );
			    }
			    
			    Ext2FreeIrpContext(IrpContext);
			    
			    if (FreeVcb)
			    {
				    Ext2FreeVcb(Vcb);
			    }
		    }
	    }
    }
    
    return Status;
}

VOID
Ext2QueueCloseRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{
	ASSERT(IrpContext);
	
	ASSERT((IrpContext->Identifier.Type == ICX) &&
		(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
	
	// IsSynchronous means we can block (so we don't requeue it)
	IrpContext->IsSynchronous = TRUE;
	
	ExInitializeWorkItem(
		&IrpContext->WorkQueueItem,
		Ext2DeQueueCloseRequest,
		IrpContext);
	
	ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
}

VOID
Ext2DeQueueCloseRequest (IN PVOID Context)
{
	PEXT2_IRP_CONTEXT IrpContext;
	
	IrpContext = (PEXT2_IRP_CONTEXT) Context;
	
	ASSERT(IrpContext);
	
	ASSERT((IrpContext->Identifier.Type == ICX) &&
		(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
	
	__try
	{
		__try
		{
			FsRtlEnterFileSystem();
			Ext2Close(IrpContext);
		}
		__except (Ext2ExceptionFilter(IrpContext, GetExceptionCode()))
		{
			Ext2ExceptionHandler(IrpContext);
		}
	}
	__finally
	{
		FsRtlExitFileSystem();
	}
}


NTSTATUS
Ext2LookupFileName (IN PEXT2_VCB        Vcb,
		    IN PUNICODE_STRING  FullFileName,
		    IN OUT PULONG       Offset,
		    IN OUT PULONG	Inode,
		    IN OUT PULONG	DirInode,
		    IN OUT PEXT2_INODE  ext2_inode)
{
	ULONG           RootInode = 2;
	UNICODE_STRING  FileName;
	NTSTATUS        Status = STATUS_OBJECT_NAME_NOT_FOUND;
	EXT2_DIR_ENTRY  ext2_dir;
	USHORT		i = 0;
	BOOLEAN		bRun = TRUE;
	BOOLEAN		bCurrent = FALSE;
	EXT2_INODE	in;
	ULONG		off = 0;

	*Offset = 0;
	*Inode = 0;

	if (*DirInode != 0 && FullFileName->Buffer[0] != L'\\')
	{
		bCurrent = TRUE;
		RootInode = *DirInode;
	}
	else
	{
		RootInode = 2;
		*DirInode = 2;
	}
	
	RtlZeroMemory(&ext2_dir, sizeof(EXT2_DIR_ENTRY));

	if (FullFileName->Length == 0)
	{
		return Status;
	}
	
	if (FullFileName->Length == 2 && FullFileName->Buffer[0] == L'\\')
	{
		if (!Ext2LoadInode(Vcb, RootInode, ext2_inode))
		{
			return Status;
		}
		*Inode = 2;
		*DirInode = 2;
		return STATUS_SUCCESS;
	}
	
	while (bRun && i < FullFileName->Length/2)
	{
		ULONG Length;

		if (bCurrent)
		{
			bCurrent = FALSE;
		}
		else
		{
			if(FullFileName->Buffer[i++] != L'\\')
				break;
		}

		Length = i;

		while(i < FullFileName->Length/2 && (FullFileName->Buffer[i] != L'\\'))
			i++;
		if (i - Length >0)
		{
			if (NT_SUCCESS(Status))
				RootInode = ext2_dir.inode;

			FileName = *FullFileName;
			FileName.Buffer += Length;
			FileName.Length = (USHORT)((i - Length) * 2);

			if (!Ext2LoadInode(Vcb, RootInode, &in))
			{
				return STATUS_OBJECT_NAME_NOT_FOUND;
			}

			if (!S_ISDIR(in.i_mode))
				break;

			Status = Ext2ScanDir (
				Vcb,
				RootInode,
				&FileName,
				&off,
				&in,
				&ext2_dir);

			if (!NT_SUCCESS(Status))
				bRun = FALSE;

		}
	}

	if (NT_SUCCESS(Status))
	{
		if (Inode)
			*Inode = ext2_dir.inode;
		if (DirInode)
			*DirInode = RootInode;
		
		if (Offset)
			*Offset = 0;
		if (ext2_inode)
			Ext2LoadInode(Vcb, ext2_dir.inode, ext2_inode);
	}

	return Status;
}

NTSTATUS
Ext2ScanDir (IN PEXT2_VCB        Vcb,
	     IN ULONG            inode,
	     IN PUNICODE_STRING  FileName,
	     IN OUT PULONG       Index,
	     IN PEXT2_INODE	 ext2_inode,
	     IN OUT PEXT2_DIR_ENTRY  ext2_dir)
{
	NTSTATUS                Status = STATUS_UNSUCCESSFUL;
	USHORT                  InodeFileNameLength;
	UNICODE_STRING          InodeFileName;

	PVOID			DirectoryContent = NULL;
	struct			ext2_dir_entry* pDir = NULL;
	ULONG			dwBytes;
	BOOLEAN			bFound = FALSE;
	

	InodeFileName.Buffer = NULL;
	
	__try
	{

		DirectoryContent = ExAllocatePool(NonPagedPool,
			ext2_inode->i_size);
		if (!DirectoryContent)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		Ext2ReadInode(Vcb, ext2_inode, 0, DirectoryContent, ext2_inode->i_size);
		dwBytes = 0;

		pDir = (struct ext2_dir_entry *) ((PUCHAR)DirectoryContent + dwBytes);

		while (!bFound && dwBytes < ext2_inode->i_size && pDir->inode)
		{
			InodeFileNameLength = pDir->name_len & 0xff;
			
			InodeFileName.Length = InodeFileName.MaximumLength =
				InodeFileNameLength * 2;
			
			InodeFileName.Buffer = ExAllocatePool(
				NonPagedPool,
				InodeFileNameLength * 2 + 2);

			RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
			
			Ext2CharToWchar(
				InodeFileName.Buffer,
				pDir->name,
				InodeFileNameLength );

			KdPrint(("Ext2ScanDir: file:%S to comp.\n", InodeFileName.Buffer));

			if (!RtlCompareUnicodeString(
				FileName,
				&InodeFileName,
				TRUE ))
			{
				bFound = TRUE;
				*Index = dwBytes;
				RtlCopyMemory(ext2_dir, pDir, pDir->rec_len > sizeof(EXT2_DIR_ENTRY)
					? sizeof(EXT2_DIR_ENTRY) : pDir->rec_len);
				Status = STATUS_SUCCESS;
				KdPrint(("Ext2ScanDir: Found: inode=%xh\n", pDir->inode));
			}
			
			if (InodeFileName.Buffer != NULL)
			{
				ExFreePool(InodeFileName.Buffer);
				InodeFileName.Buffer = NULL;
			}
			
			dwBytes +=pDir->rec_len;
			pDir = (struct ext2_dir_entry *) ((PUCHAR)DirectoryContent + dwBytes);

		}

		if (!bFound)
			Status = STATUS_NO_SUCH_FILE;
	}

	__finally
	{
		if (InodeFileName.Buffer != NULL)
		{
			ExFreePool(InodeFileName.Buffer);
		}

		if (DirectoryContent)
			ExFreePool(DirectoryContent);
	}
	
	return Status;
}

NTSTATUS
Ext2OpenFile(PEXT2_VCB Vcb, PIRP Irp)
{
	NTSTATUS			Status = STATUS_OBJECT_NAME_NOT_FOUND;
	PIO_STACK_LOCATION  io_stack;
	PEXT2_FCB           Fcb = NULL;
	PEXT2_FCB			pParentFcb = NULL;
	PEXT2_CCB           Ccb = NULL;
	ULONG               found_index = 0;
	struct ext2_inode*  ext2_inode;
	PLIST_ENTRY         Link;
	PEXT2_FCB           TmpFcb;
	BOOLEAN             VcbResourceAcquired = FALSE;
	BOOLEAN				bFound = FALSE;
	BOOLEAN				bDir = FALSE;
	ULONG				inode, dir_inode;
	UNICODE_STRING	    FileName;

	FileName.Buffer = NULL;
	io_stack = IoGetCurrentIrpStackLocation(Irp);

	__try
	{
		ExAcquireResourceExclusiveLite(
			&Vcb->MainResource,
			TRUE );
		
		VcbResourceAcquired = TRUE;
		
		ext2_inode = ExAllocatePool(
			NonPagedPool,
			sizeof(struct ext2_inode) );
		if (!ext2_inode)
			__leave;

		FileName.MaximumLength = 0x400;

		if (io_stack->FileObject->RelatedFileObject)
		{
			pParentFcb = (PEXT2_FCB)(io_stack->FileObject->RelatedFileObject->FsContext);
		}

		FileName =	io_stack->FileObject->FileName;


		if (pParentFcb)
		{
			dir_inode = pParentFcb->inode;
		}
		else
		{
			dir_inode = 2;
		}

		KdPrint(("Ext2OpenFile: %S Opt: %xh.\n",
			FileName.Buffer,
			io_stack->Parameters.Create.Options));


		Status = Ext2LookupFileName(
			Vcb,
			&FileName,
			&found_index,
			&inode,
			&dir_inode,
			ext2_inode );

		if (!NT_SUCCESS(Status))
		{
			__leave;
		}
/*
		else
		{
			bDir = (io_stack->FileObject->Flags & 0x02) ? TRUE : FALSE;

			if (io_stack->FileObject->FileName.Buffer[0] == L'\\' &&
			    io_stack->FileObject->FileName.Length == 2 && 
			    Vcb->inode != 0 )
			    bDir = FALSE;

			if (S_ISDIR(ext2_inode->i_mode) && (Vcb->inode != inode) && bDir)
			{
				Vcb->inode = inode;
				if (Vcb->Name.Buffer)
					ExFreePool(Vcb->Name.Buffer);
				Vcb->Name.Buffer = ExAllocatePool(NonPagedPool, Length + 2);
				RtlZeroMemory(Vcb->Name.Buffer, Length + 2);
				Vcb->Name.MaximumLength = 0x400;
				Vcb->Name.Length = 0;
				RtlAppendUnicodeStringToString(
					&(Vcb->Name), &FileName);
				if (Vcb->Name.Buffer[(Length - 2)/2] != L'\\')
				{
					Vcb->Name.Buffer[Length/2] =  L'\\';
					Vcb->Name.Length +=2;
				}
			}
			else
			{
//				Vcb->inode = dir_inode;
			}

		}
*/

		Link = Vcb->FcbList.Flink;
		
		while (!bFound && Link != &Vcb->FcbList)
		{
			TmpFcb = CONTAINING_RECORD(Link, EXT2_FCB, Next);
			
			if (TmpFcb && TmpFcb->Identifier.Type == FCB)
			{
#if DBG
				KdPrint(("Ext2OpenFile: [%s,%xh]\n", TmpFcb->DbgFileName, TmpFcb->inode));
#endif				
				if (TmpFcb->inode == inode)
				{
					KdPrint(("Ext2OpenFile: Found FCB for %xh.\n", inode));
					Fcb = TmpFcb;
					bFound = TRUE;
				}
			}
			Link = Link->Flink;
		}

		
		if (!Fcb)
		{
			Fcb = Ext2AllocateFcb (
				Vcb, &FileName, found_index, inode,
				dir_inode, ext2_inode );
		}
		
		if (Fcb)
		{
			Ccb = Ext2AllocateCcb();
			
			Fcb->OpenHandleCount++;
			Vcb->OpenFileHandleCount++;
			Fcb->ReferenceCount++;
			Vcb->ReferenceCount++;
#if DBG
			KdPrint(("Ext2OpenFile: %s refercount=%xh\n", Fcb->DbgFileName, Fcb->ReferenceCount));
#endif			
			io_stack->FileObject->FsContext = (void*)Fcb;
			io_stack->FileObject->FsContext2 = (void*) Ccb;
			io_stack->FileObject->PrivateCacheMap = NULL;
			io_stack->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
			io_stack->FileObject->Vpb = Vcb->Vpb;
			
			Irp->IoStatus.Information = FILE_OPENED;
			Status = STATUS_SUCCESS;
#if DBG			
			KdPrint(("Ext2OpenFile: %s OpenCount: %u ReferCount: %u\n",
				Fcb->DbgFileName, Fcb->OpenHandleCount,	Fcb->ReferenceCount));
#endif
		}
		else
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_OBJECT_NAME_NOT_FOUND;
			KdPrint(("Ext2OpenFile: Create denied (CCB allocate error.)\n"));
		}
	
	}

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

		if (bFound)
		{
			if (ext2_inode)
				ExFreePool(ext2_inode);
		}
		else
		{
			if (!Fcb && ext2_inode)
				ExFreePool(ext2_inode);
		}
/*
		if (FileName.Buffer)
			ExFreePool(FileName.Buffer);
*/
	}
	
	return Status;
}


NTSTATUS
Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT      DeviceObject;
	PIRP                Irp;
	PIO_STACK_LOCATION  io_stack;
	PEXT2_VCB           Vcb = 0;
	NTSTATUS	    Status = STATUS_OBJECT_NAME_NOT_FOUND;


	DeviceObjec

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -