그냥 드라이버를 좀 하면 되지 않을 까 했는데, 생각보다 많은 부분에서 차이가 나더라..
일단 가볍게 책 두 권을 독파하는 것으로 시작해서 이 분야에 대한 참조 소스를 찾아 나섰다.
어딘가의 웹에서 떠돌아 다니던 File System Filter Driver Tutorial이라는 워드 문서를 발견했지만, 소스는 찾을 수가 없더라...
그러던 것이 구글에서 그대로 조회를 해 봤더니 Code project 사이트에서 해당 소스를 찾을 수 있었다.
- 원본 소스의 이름은 FsFilter 이다.
이걸 이해도 못하고 그냥 쓸 수는 없어서 일단 문서를 기준으로 파일을 만들기 시작했다.
문서를 기준으로 만드는 것은 역시 수두룩한 에러를 뱉어 낸다.
이어서 해당 소스를 뒤져서 없는 부분들을 메워나갔다.
뭐 결국 원래 소스를 그대로 답습한 내용이지만, 이걸 하나의 파일로 만들었다.
여기에 H/W 드라이버를 제작할 때의 필요 함수와 구조체 정의가 몇개 추가되었다.
이 부분에 대해서는 "윈도우 디바이스 드라이버"라는 책에서 샘플로 제공된 소스를 참조했다.
어디까지나 나는 드라이버에 대해서는 초보자나 마찬가지이므로 새로 정의하거나 수정하는 작업은 좀 더 후의 일이 될 듯하다.
파일 시스템 필터 드라이브 제작 시 주의할 부분이 하나
A file system filter driver must have the fast-io dispatch table. If you've forgot to set up the fast-io dispatch table it will lead system to crash. Fast-io is an alternative way to initiate I/O operation (and it's faster than IRP). Fast-io operations are always synchronous. If fast-io handler returns FALSE then fast-io way is imposible and IRP will be created.
출처 :
- File System Filter Driver Tutorial,
- http://www.apriorit.com
- Written by Sergey Podobry
결국 Fast-IO를 처리할 때는 BSOD가 발생할 수 있으니 언제나 IRP 처리를 동반해야 한다는...
뭐 실제 어떻게 동작하는 아직 테스트를 해보지 않아서 모르겠지만 말이지...
어디까지나 아직 테스트를 거치거나 다른 여러가지 것들을 확인하지 못했으니 설혹 보게 되더라도 딴지 걸지 말자.
괜히 이 파일들에 대해 왈가왈부하지 마시길...
아, 정말 싫다.
File_System_Filter_Driver_Tutorial.doc
원본 소스 출처 : http://www.codeproject.com/Articles/43586/File-System-Filter-Driver-Tutorial
#include <ntifs.h>
#define DELAY_ONE_MICROSECOND ( -10 )
#define DELAY_ONE_MILLISECOND ( DELAY_ONE_MICROSECOND * 1000 )
#define DELAY_ONE_SECOND ( DELAY_ONE_MILLISECOND * 1000 )
#define DEVOBJ_LIST_SIZE 64
// Macro to test if FAST_IO_DISPATCH handling routine is valid
#define VALID_FAST_IO_DISPATCH_HANDLER( _FastIoDispatchPtr, _FieldName ) \
( ( ( _FastIoDispatchPtr ) != NULL ) && \
( ( ( _FastIoDispatchPtr )->SizeOfFastIoDispatch ) >= \
( FIELD_OFFSET( FAST_IO_DISPATCH, _FieldName ) + sizeof( void * ) ) ) && \
( ( _FastIoDispatchPtr )->_FieldName != NULL ) )
////////////////////////////////////////////////////////////////////
// Structures
typedef struct _FSFILTER_DEVICE_EXTENSION
{
PDEVICE_OBJECT AttachedToDeviceObject;
} FSFILTER_DEVICE_EXTENSION, *PFSFILTER_DEVICE_EXTENSION;
// For H/W driver
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT NextLayerDeviceObject;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
////////////////////////////////////////////////////////////////////
// Functions - FsFilterFastIo~~~
BOOLEAN FsFilterFastIoCheckIfPossible(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in BOOLEAN bWait,
__in ULONG ulLockKey,
__in BOOLEAN bCheckForReadOperation,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible ) )
{
return ( fastIoDispatch->FastIoCheckIfPossible )(
pFileObject,
pFileOffset,
ulLength,
bWait,
ulLockKey,
bCheckForReadOperation,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoRead(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in BOOLEAN bWait,
__in ULONG ulLockKey,
__out PVOID pBuffer,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead ) )
{
return ( fastIoDispatch->FastIoRead )(
pFileObject,
pFileOffset,
ulLength,
bWait,
ulLockKey,
pBuffer,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoWrite(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in BOOLEAN bWait,
__in ULONG ulLockKey,
__in PVOID pBuffer,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWrite ) )
{
return ( fastIoDispatch->FastIoWrite )(
pFileObject,
pFileOffset,
ulLength,
bWait,
ulLockKey,
pBuffer,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoQueryBasicInfo(
__in PFILE_OBJECT pFileObject,
__in BOOLEAN bWait,
__out PFILE_BASIC_INFORMATION pFileBasicInfo,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryBasicInfo ) )
{
return ( fastIoDispatch->FastIoQueryBasicInfo )(
pFileObject,
bWait,
pFileBasicInfo,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoQueryStandardInfo(
__in PFILE_OBJECT pFileObject,
__in BOOLEAN bWait,
__out PFILE_STANDARD_INFORMATION pFileStandardInfo,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryStandardInfo ) )
{
return ( fastIoDispatch->FastIoQueryStandardInfo )(
pFileObject,
bWait,
pFileStandardInfo,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoLock(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in PLARGE_INTEGER pLength,
__in PEPROCESS pProcessId,
__in ULONG ulKey,
__in BOOLEAN bFailImmediately,
__in BOOLEAN bExclusiveLock,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoLock ) )
{
return ( fastIoDispatch->FastIoLock )(
pFileObject,
pFileOffset,
pLength,
pProcessId,
ulKey,
bFailImmediately,
bExclusiveLock,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoUnlockSingle(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in PLARGE_INTEGER pLength,
__in PEPROCESS pProcessId,
__in ULONG ulKey,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockSingle ) )
{
return ( fastIoDispatch->FastIoUnlockSingle )(
pFileObject,
pFileOffset,
pLength,
pProcessId,
ulKey,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoUnlockAll(
__in PFILE_OBJECT pFileObject,
__in PEPROCESS pProcessId,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAll ) )
{
return ( fastIoDispatch->FastIoUnlockAll )(
pFileObject,
pProcessId,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoUnlockAllByKey(
__in PFILE_OBJECT pFileObject,
__in PVOID pProcessId,
__in ULONG ulKey,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAllByKey ) )
{
return ( fastIoDispatch->FastIoUnlockAllByKey )(
pFileObject,
pProcessId,
ulKey,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoDeviceControl(
__in PFILE_OBJECT pFileObject,
__in BOOLEAN bWait,
__in_opt PVOID pInputBuffer,
__in ULONG ulInputBuffer,
__out_opt PVOID pOutputBuffer,
__in ULONG ulOutputBuffer,
__in ULONG ulIoControlCode,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoDeviceControl ) )
{
return ( fastIoDispatch->FastIoDeviceControl )(
pFileObject,
bWait,
pInputBuffer,
ulInputBuffer,
pOutputBuffer,
ulOutputBuffer,
ulIoControlCode,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
VOID FsFilterFastIoDetachDevice(
__in PDEVICE_OBJECT SourceDevice,
__in PDEVICE_OBJECT TargetDevice
)
{
// Detach from the file system's volume device object.
IoDetachDevice( TargetDevice );
IoDeleteDevice( SourceDevice );
}
BOOLEAN FsFilterFastIoQueryNetworkOpenInfo(
__in PFILE_OBJECT pFileObject,
__in BOOLEAN bWait,
__out PFILE_NETWORK_OPEN_INFORMATION pfNetworkOpenInfo,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryNetworkOpenInfo ) )
{
return ( fastIoDispatch->FastIoQueryNetworkOpenInfo )(
pFileObject,
bWait,
pfNetworkOpenInfo,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoMdlRead(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in ULONG ulLockKey,
__out PMDL * pMdlChain,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlRead ) )
{
return ( fastIoDispatch->MdlRead )(
pFileObject,
pFileOffset,
ulLength,
ulLockKey,
pMdlChain,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoMdlReadComplete(
__in PFILE_OBJECT pFileObject,
__out PMDL pMdlChain,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadComplete ) )
{
return ( fastIoDispatch->MdlReadComplete )(
pFileObject,
pMdlChain,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoPrepareMdlWrite(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in ULONG ulLockKey,
__out PMDL * pMdlChain,
__out PIO_STATUS_BLOCK pIoStatus,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, PrepareMdlWrite ) )
{
return ( fastIoDispatch->PrepareMdlWrite )(
pFileObject,
pFileOffset,
ulLength,
ulLockKey,
pMdlChain,
pIoStatus,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoMdlWriteComplete(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__out PMDL pMdlChain,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteComplete ) )
{
return ( fastIoDispatch->MdlWriteComplete )(
pFileObject,
pFileOffset,
pMdlChain,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoReadCompressed(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in ULONG ulLockKey,
__out PVOID pBuffer,
__out PMDL * pMdlChain,
__out PIO_STATUS_BLOCK pIoStatus,
__out struct _COMPRESSED_DATA_INFO * pCompDataInfo,
__in ULONG ulCompDataInfoLen,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoReadCompressed ) )
{
return ( fastIoDispatch->FastIoReadCompressed )(
pFileObject,
pFileOffset,
ulLength,
ulLockKey,
pBuffer,
pMdlChain,
pIoStatus,
pCompDataInfo,
ulCompDataInfoLen,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoWriteCompressed(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in ULONG ulLength,
__in ULONG ulLockKey,
__out PVOID pBuffer,
__out PMDL * pMdlChain,
__out PIO_STATUS_BLOCK pIoStatus,
__out struct _COMPRESSED_DATA_INFO * pCompDataInfo,
__in ULONG ulCompDataInfoLen,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWriteCompressed ) )
{
return ( fastIoDispatch->FastIoWriteCompressed )(
pFileObject,
pFileOffset,
ulLength,
ulLockKey,
pBuffer,
pMdlChain,
pIoStatus,
pCompDataInfo,
ulCompDataInfoLen,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoMdlReadCompleteCompressed(
__in PFILE_OBJECT pFileObject,
__in PMDL pMdlChain,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadCompleteCompressed ) )
{
return ( fastIoDispatch->MdlReadCompleteCompressed )(
pFileObject,
pMdlChain,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed(
__in PFILE_OBJECT pFileObject,
__in PLARGE_INTEGER pFileOffset,
__in PMDL pMdlChain,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteCompleteCompressed ) )
{
return ( fastIoDispatch->MdlWriteCompleteCompressed )(
pFileObject,
pFileOffset,
pMdlChain,
nextDeviceObject );
}
return FALSE;
}
BOOLEAN FsFilterFastIoQueryOpen(
__in PIRP pIrp,
__out PFILE_NETWORK_OPEN_INFORMATION pfNetOpenInfo,
__in PDEVICE_OBJECT pDeviceObject
)
{
// Pass through logic for this type of Fast I/O
PDEVICE_OBJECT nextDeviceObject = ( ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension )->AttachedToDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if( VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryOpen ) )
{
BOOLEAN bResult;
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation( pIrp );
// Before calling the next filter, we must make sure their device
// object is in the current stack entry for the given IRP
pIoStackLocation->DeviceObject = nextDeviceObject;
bResult = ( fastIoDispatch->FastIoQueryOpen )(
pIrp,
pfNetOpenInfo,
nextDeviceObject );
// Always restore the IRP back to our device object
pIoStackLocation->DeviceObject = pDeviceObject;
return bResult;
}
return FALSE;
}
////////////////////////////////////////////////////////////////////
// Global data
PDRIVER_OBJECT g_fsFilterDriverObject = NULL;
FAST_IO_DISPATCH g_fastIoDispatch =
{
sizeof( FAST_IO_DISPATCH ),
FsFilterFastIoCheckIfPossible,
FsFilterFastIoRead,
FsFilterFastIoWrite,
FsFilterFastIoQueryBasicInfo,
FsFilterFastIoQueryStandardInfo,
FsFilterFastIoLock,
FsFilterFastIoUnlockSingle,
FsFilterFastIoUnlockAll,
FsFilterFastIoUnlockAllByKey,
FsFilterFastIoDeviceControl,
NULL,
NULL,
FsFilterFastIoDetachDevice,
FsFilterFastIoQueryNetworkOpenInfo,
NULL,
FsFilterFastIoMdlRead,
FsFilterFastIoMdlReadComplete,
FsFilterFastIoPrepareMdlWrite,
FsFilterFastIoMdlWriteComplete,
FsFilterFastIoReadCompressed,
FsFilterFastIoWriteCompressed,
FsFilterFastIoMdlReadCompleteCompressed,
FsFilterFastIoMdlWriteCompleteCompressed,
FsFilterFastIoQueryOpen,
NULL,
NULL,
NULL,
};
////////////////////////////////////////////////////////////////////
// Misc
BOOLEAN FsFilterIsMyDeviceObject(
__in PDEVICE_OBJECT DeviceObject
)
{
return DeviceObject->DriverObject == g_fsFilterDriverObject;
}
////////////////////////////////////////////////////////////////////
// This determines whether we are attached to the given device
BOOLEAN FsFilterIsAttachedToDevice(
__in PDEVICE_OBJECT pDeviceObject
)
{
PDEVICE_OBJECT nextDevObj = NULL;
PDEVICE_OBJECT currentDevObj = IoGetAttachedDeviceReference( pDeviceObject );
// Scan down the list to find our device object
do
{
if( FsFilterIsMyDeviceObject( currentDevObj ) )
{
ObDereferenceObject( currentDevObj );
return TRUE;
}
// Get the next attached object.
nextDevObj = IoGetLowerDeviceObject( currentDevObj );
// Dereference our current device object, before moving to the next one.
ObDereferenceObject( currentDevObj );
currentDevObj = nextDevObj;
}
while( NULL != currentDevObj );
return FALSE;
}
/////////////////////////////////////////////////////////////////////
// This will attach to a DeviceObject that represents a mounted volume
NTSTATUS FsFilterAttachToDevice(
__in PDEVICE_OBJECT pDeviceObject,
__out_opt PDEVICE_OBJECT * pFilterDeviceObject
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT filterDeviceObject = NULL;
PFSFILTER_DEVICE_EXTENSION pDevExt = NULL;
ULONG i = 0;
ASSERT( !FsFilterIsAttachedToDevice( pDeviceObject ) );
// Create a new devcie object we can attach with.
ntStatus = IoCreateDevice(
g_fsFilterDriverObject,
sizeof( FSFILTER_DEVICE_EXTENSION ),
NULL,
pDeviceObject->DeviceType,
0,
FALSE,
&filterDeviceObject );
if( !NT_SUCCESS( ntStatus ) )
{
return ntStatus;
}
pDevExt = ( PFSFILTER_DEVICE_EXTENSION )filterDeviceObject->DeviceExtension;
// Propagate flags from the Device Object we are trying to attach to.
if( FlagOn( pDeviceObject->Flags, DO_BUFFERED_IO ) )
{
SetFlag( filterDeviceObject->Flags, DO_BUFFERED_IO );
}
if( FlagOn( pDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN ) )
{
SetFlag( filterDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN );
}
// Do the attachment.
// Is is possible for this attachment request to fail because this device
// object has not finished initializing. This can occur if this filter
// loaded just as this volume was being mounted.
for( i = 0 ; i < 8 ; i ++ )
{
LARGE_INTEGER lnInterval;
ntStatus = IoAttachDeviceToDeviceStackSafe(
filterDeviceObject,
pDeviceObject,
&pDevExt->AttachedToDeviceObject );
if( NT_SUCCESS( ntStatus ) )
{
break;
}
// Delay, giving the device object a chance to finish its
// initialization so we can try again.
lnInterval.QuadPart = ( 500 * DELAY_ONE_MILLISECOND );
KeDelayExecutionThread( KernelMode, FALSE, &lnInterval );
}
if( !NT_SUCCESS( ntStatus ) )
{
// Clean up.
IoDeleteDevice( filterDeviceObject );
filterDeviceObject = NULL;
}
else
{
// Mark we are done initializing.
ClearFlag( filterDeviceObject->Flags, DO_DEVICE_INITIALIZING );
if( NULL != pFilterDeviceObject )
{
* pFilterDeviceObject = filterDeviceObject;
}
}
return ntStatus;
}
void FsFilterDetachFromDevice(
__in PDEVICE_OBJECT pDeviceObject
)
{
PFSFILTER_DEVICE_EXTENSION pDevExt = ( PFSFILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension;
IoDetachDevice( pDevExt->AttachedToDeviceObject );
IoDeleteDevice( pDeviceObject );
}
////////////////////////////////////////////////////////////////////
// Enumerate all the mounted devices that currently exist for
// the given file system and attach to them
NTSTATUS FsFilterEnumerateFileSystemVolumes(
__in PDEVICE_OBJECT pDeviceObject
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG ulNumbDevices = 0;
ULONG i = 0;
PDEVICE_OBJECT lstDevObj[DEVOBJ_LIST_SIZE];
// Now get the list of devices.
ntStatus = IoEnumerateDeviceObjectList(
pDeviceObject->DriverObject,
lstDevObj,
sizeof( lstDevObj ),
&ulNumbDevices );
if( !NT_SUCCESS( ntStatus ) )
{
return ntStatus;
}
ulNumbDevices = min( ulNumbDevices, RTL_NUMBER_OF( lstDevObj ) );
// Walk the given list of devices and attach to them if we should.
for( i = 0 ; i < ulNumbDevices ; ++ i )
{
// Do not attach if:
// - This is the control device object ( the one passed in )
// - The device type does not match
// - We are already attached to it.
if( lstDevObj[i] != pDeviceObject &&
lstDevObj[i]->DeviceType != pDeviceObject->DeviceType &&
!FsFilterIsAttachedToDevice( lstDevObj[i] ) )
{
ntStatus = FsFilterAttachToDevice( lstDevObj[i], NULL );
}
ObDereferenceObject( lstDevObj[i] );
}
return STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
// This will attach to the given file system device object
NTSTATUS FsFilterAttachToFileSystemDevice(
__in PDEVICE_OBJECT pDeviceObject
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT pdoFilterDeviceObject = NULL;
if( !FsFilterIsAttachedToDevice( pDeviceObject ) )
{
ntStatus = FsFilterAttachToDevice( pDeviceObject, &pdoFilterDeviceObject );
if( !NT_SUCCESS( ntStatus ) )
{
return ntStatus;
}
// Enumerated all the mounted devices that currently exist for this file system and attach to them.
ntStatus = FsFilterEnumerateFileSystemVolumes( pDeviceObject );
if( !NT_SUCCESS( ntStatus ) )
{
FsFilterDetachFromDevice( pdoFilterDeviceObject );
return ntStatus;
}
}
return STATUS_SUCCESS;
}
////////////////////////////////////////////////////////////////////
// This will detach us from the chain
VOID FsFilterDetachFromFileSystemDevice(
__in PDEVICE_OBJECT pDeviceObject
)
{
PDEVICE_OBJECT pDevObj = NULL;
for( pDevObj = pDeviceObject->AttachedDevice ; NULL != pDevObj ; pDevObj = pDevObj->AttachedDevice )
{
if( FsFilterIsMyDeviceObject( pDevObj ) )
{
// Detach us from the object just below us. Cleanup and delete the object.
FsFilterDetachFromDevice( pDevObj );
break;
}
}
}
////////////////////////////////////////////////////////////////////
// This routine is invoked whenever a file system has either registered
// or unregistered itself as an active file system.
VOID FsFilterNotificationCallback(
__in PDEVICE_OBJECT DeviceObject,
__in BOOLEAN FsActive
)
{
// Handle attaching/detaching from the given file system.
if( FsActive )
{
FsFilterAttachToFileSystemDevice( DeviceObject );
}
else
{
FsFilterDetachFromFileSystemDevice( DeviceObject );
}
}
////////////////////////////////////////////////////////////////////
// PassThrough IRP Handler
NTSTATUS _DispatchPassThrough(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
PFSFILTER_DEVICE_EXTENSION pDevExt = ( PFSFILTER_DEVICE_EXTENSION )DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( pDevExt->AttachedToDeviceObject, Irp );
}
////////////////////////////////////////////////////////////////////
// IRP_MJ_CREATE IRP Handler
NTSTATUS _DispatchCreate(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation( Irp )->FileObject;
DbgPrint( "%wZ\n", &pFileObject->FileName );
return _DispatchPassThrough( DeviceObject, Irp );
}
////////////////////////////////////////////////////////////////////
// Unload routine
VOID FsFilterUnload(
__in PDRIVER_OBJECT DriverObject
)
{
ULONG ulDevices = 0;
ULONG i = 0;
LARGE_INTEGER ulInterval;
PDEVICE_OBJECT lstDevObj[DEVOBJ_LIST_SIZE];
ulInterval.QuadPart = ( 5 * DELAY_ONE_SECOND );
// Unregistered callback routine for file system changes.
IoUnregisterFsRegistrationChange( DriverObject, FsFilterNotificationCallback );
for( ; ; )
{
IoEnumerateDeviceObjectList(
DriverObject,
lstDevObj,
sizeof( lstDevObj ),
&ulDevices );
if( 0 == ulDevices )
{
break;
}
ulDevices = min( ulDevices, RTL_NUMBER_OF( lstDevObj ) );
for( i = 0 ; i < ulDevices ; ++ i )
{
FsFilterDetachFromDevice( lstDevObj[i] );
ObDereferenceObject( lstDevObj[i] );
}
KeDelayExecutionThread( KernelMode, FALSE, &ulInterval );
}
}
////////////////////////////////////////////////////////////////////
// For H/W driver
NTSTATUS AddDevice(
__in PDRIVER_OBJECT pDriverObject,
__in PDEVICE_OBJECT pPhysicalDeviceObject
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT pDevObj = NULL;
PDEVICE_EXTENSION pDevExtension;
ntStatus = IoCreateDevice(
pDriverObject,
sizeof( DEVICE_EXTENSION ),
NULL,
FILE_DEVICE_UNKNOWN,
0, // FILE_AUTOGENERATED_DEVICE_NAME
FALSE,
&pDevObj );
pDevExtension = ( PDEVICE_EXTENSION )pDevObj->DeviceExtension;
pDevExtension->NextLayerDeviceObject = IoAttachDeviceToDeviceStack( pDevObj, pPhysicalDeviceObject );
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
return ntStatus;
}
NTSTATUS PnpDispatch(
__in PDEVICE_OBJECT pDeviceObject,
__in PIRP pIrp
)
{
PIO_STACK_LOCATION pStack;
PDEVICE_EXTENSION pDeviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT nextLayerDevObj;
pStack = IoGetCurrentIrpStackLocation( pIrp );
pDeviceExtension = ( PDEVICE_EXTENSION )pDeviceObject->DeviceExtension;
nextLayerDevObj = pDeviceExtension->NextLayerDeviceObject;
switch( pStack->MinorFunction )
{
case IRP_MN_REMOVE_DEVICE:
{
IoDetachDevice( nextLayerDevObj );
IoDeleteDevice( pDeviceObject );
}
break;
}
IoSkipCurrentIrpStackLocation( pIrp );
ntStatus = IoCallDriver( nextLayerDevObj, pIrp );
return ntStatus;
}
////////////////////////////////////////////////////////////////////
// DriverEntry - Entry point of the driver
extern "C"
NTSTATUS DriverEntry(
__inout PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG i = 0;
// ASSERT( FALSE ); // This will break to debugger
// Store our driver object
g_fsFilterDriverObject = DriverObject;
// Initialize the driver object dispatch table.
for( i = 0 ; i <= IRP_MJ_MAXIMUM_FUNCTION ; ++ i )
{
DriverObject->MajorFunction[i] = _DispatchPassThrough;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = _DispatchCreate;
// Set fast-io dispatch table.
DriverObject->FastIoDispatch = &g_fastIoDispatch;
// Registered callback routine for file system changes.
status = IoRegisterFsRegistrationChange( DriverObject, FsFilterNotificationCallback );
if( !NT_SUCCESS( status ) )
{
return status;
}
// Set driver unload routine ( debug purpose only ).
DriverObject->DriverUnload = FsFilterUnload;
// for H/W driver
DriverObject->DriverExtension->AddDevice = AddDevice;
// for PnP on H/W driver
DriverObject->MajorFunction[IRP_MJ_PNP] = PnpDispatch;
return STATUS_SUCCESS;
}





최근 덧글