📄 devctl.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: devctl.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ntifs.h"
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL gExt2Global;
/* DEFINITIONS *************************************************************/
NTSTATUS
Ext2DeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context);
#ifdef ALLOC_PRAGMA
//#pragma alloc_text(PAGE, Ext2DeviceControlCompletion)
#pragma alloc_text(PAGE, Ext2DeviceControl)
#pragma alloc_text(PAGE, Ext2DeviceControlNormal)
#pragma alloc_text(PAGE, Ext2DeviceControl)
#endif
NTSTATUS
Ext2DeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
#if DBG
Ext2DbgPrint(D_DEVCTL, DRIVER_NAME ": %-16.16s %-31s *** Status: %s (%#x) ***\n",
PsGetCurrentProcess()->ImageFileName,
"IRP_MJ_DEVICE_CONTROL",
Ext2DbgNtStatusToString(Irp->IoStatus.Status),
Irp->IoStatus.Status );
#endif
return STATUS_SUCCESS;
}
NTSTATUS
Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
BOOLEAN CompleteRequest = TRUE;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb;
PEXT2_CCB Ccb;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PIO_STACK_LOCATION NextIrpSp;
PDEVICE_OBJECT TargetDeviceObject;
__try
{
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
CompleteRequest = TRUE;
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == gExt2Global->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext;
Ccb = (PEXT2_CCB) IrpSp->FileObject->FsContext2;
if (!(Vcb &&
( (Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))) &&
Ccb) )
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
TargetDeviceObject = Vcb->TargetDeviceObject;
//
// Pass on the IOCTL to the driver below
//
CompleteRequest = FALSE;
NextIrpSp = IoGetNextIrpStackLocation( Irp );
*NextIrpSp = *IrpSp;
IoSetCompletionRoutine(
Irp,
Ext2DeviceControlCompletion,
NULL,
FALSE,
TRUE,
TRUE );
Status = IoCallDriver(TargetDeviceObject, Irp);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = FALSE;
}
}
__finally
{
if (!IrpContext->ExceptionInProgress)
{
if (CompleteRequest)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
}
if (IrpContext)
{
Ext2FreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
Ext2GetSuperBlock (IN PEXT2_IRP_CONTEXT IrpContext)
{
PIRP Irp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL;
PDEVICE_OBJECT DeviceObject = NULL;
PEXT2_VCB Vcb = NULL;
PCHAR pOutputBuffer = NULL;
ULONG dwDataWritten = 0;
ULONG dwDataSize = sizeof(EXT2_SUPER_BLOCK);
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ENTER (D_DEVCTL, "Ext2GetSuperBlock");
__try
{
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Irp = IrpContext->Irp;
DeviceObject = IrpContext->DeviceObject;
ASSERT (Irp != NULL);
ASSERT (DeviceObject != NULL);
//
// This request is not allowed on the main device object
//
if (DeviceObject == gExt2Global->DeviceObject)
{
Ext2DbgPrint(D_DEVCTL, "Cannot allow on the main device object, returning.");
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
//
// It should be a VCB.
//
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
//
// Get the User mode memmory where we need to dump the super block.
//
pOutputBuffer = (PCHAR) Irp->UserBuffer;
if(pOutputBuffer == NULL)
{
Ext2DbgPrint(D_DEVCTL, "Output buffer NULL, returning.");
Status = STATUS_INVALID_PARAMETER;
__leave;
}
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
ProbeForWrite(
pOutputBuffer,
IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength,
1
);
if(IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
Ext2DbgPrint(D_DEVCTL, "Copying data.");
RtlCopyMemory(pOutputBuffer, Vcb->ext2_super_block, dwDataSize);
dwDataWritten = dwDataSize;
Status = STATUS_SUCCESS;
}
else
{
Ext2DbgPrint(D_DEVCTL, "Output buffer too small (need %d bytes, got %d bytes), returning.",
dwDataSize,
IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength);
dwDataWritten = dwDataSize;
Status = STATUS_BUFFER_TOO_SMALL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status = FALSE;
}
}
__finally
{
if (!IrpContext->ExceptionInProgress)
{
IrpContext->Irp->IoStatus.Status = Status;
IrpContext->Irp->IoStatus.Information = dwDataWritten;
Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
Ext2FreeIrpContext(IrpContext);
}
}
LEAVE3 (D_DEVCTL, "Ext2GetSuperBlock");
return Status;
}
NTSTATUS
Ext2GetInodeForFile (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN OUT ULONG* dwDataWritten
)
{
PIRP Irp = NULL;
PIO_STACK_LOCATION IoStackLocation = NULL;
PEXT2_FCB Fcb = NULL;
PCHAR pOutputBuffer = NULL;
ULONG dwDataSize = sizeof(EXT2_INODE);
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ENTER (D_DEVCTL, "Ext2GetInodeForFile");
__try
{
ASSERT (IrpContext != NULL);
ASSERT (FileObject != NULL);
// It should be a FCB.
Fcb = (PEXT2_FCB) FileObject->FsContext;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
// Get the User mode memmory where we need to dump the super block.
Irp = IrpContext->Irp;
ASSERT (Irp != NULL);
pOutputBuffer = (PCHAR) Irp->UserBuffer;
if(pOutputBuffer == NULL)
{
Ext2DbgPrint(D_DEVCTL, "Output buffer NULL, returning.");
Status = STATUS_INVALID_PARAMETER;
__leave;
}
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
ProbeForWrite(
pOutputBuffer,
IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength,
1
);
if(IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength >= dwDataSize)
{
Ext2DbgPrint(D_DEVCTL, "Copying data.");
// Over loading the reserved field with the inode number.
Fcb->ext2_inode->osd1.linux1.l_i_reserved1 = Fcb->Ext2Mcb->Inode ;
RtlCopyMemory(pOutputBuffer, Fcb->ext2_inode, dwDataSize);
if (dwDataWritten != NULL)
{
(*dwDataWritten) = dwDataSize;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -