├── NTFsrc ├── filesys │ ├── WS_FTP.LOG │ ├── event │ │ ├── MAKE-MC.BAT │ │ ├── MAKEFILE │ │ ├── README.TXT │ │ ├── SOURCES │ │ ├── dummy.c │ │ ├── errmsg.msg │ │ ├── errmsg.rc │ │ ├── obj │ │ │ ├── _objects.mac │ │ │ └── i386 │ │ │ │ ├── checked │ │ │ │ ├── sfsdevnt.dll │ │ │ │ ├── sfsdevnt.exp │ │ │ │ └── sfsdevnt.lib │ │ │ │ ├── dummy.obj │ │ │ │ ├── errmsg.res │ │ │ │ └── free │ │ │ │ ├── sfsdevnt.dll │ │ │ │ ├── sfsdevnt.exp │ │ │ │ └── sfsdevnt.lib │ │ └── sfsdevnt.def │ ├── inc │ │ ├── errmsg.h │ │ ├── protos.h │ │ ├── sfsd.h │ │ └── struct.h │ ├── readme1.txt │ └── src │ │ ├── cleanup.c │ │ ├── close.c │ │ ├── create.c │ │ ├── devcntrl.c │ │ ├── dircntrl.c │ │ ├── fastio.c │ │ ├── fileinfo.c │ │ ├── flush.c │ │ ├── makefile │ │ ├── misc.c │ │ ├── obj │ │ ├── _objects.mac │ │ └── i386 │ │ │ ├── checked │ │ │ └── sfsd.sys │ │ │ ├── cleanup.obj │ │ │ ├── close.obj │ │ │ ├── create.obj │ │ │ ├── devcntrl.obj │ │ │ ├── dircntrl.obj │ │ │ ├── fastio.obj │ │ │ ├── fileinfo.obj │ │ │ ├── flush.obj │ │ │ ├── free │ │ │ └── sfsd.sys │ │ │ ├── misc.obj │ │ │ ├── read.obj │ │ │ ├── sfsdinit.obj │ │ │ ├── shutdown.obj │ │ │ └── write.obj │ │ ├── read.c │ │ ├── sfsdinit.c │ │ ├── shutdown.c │ │ ├── sources │ │ └── write.c ├── filter-high │ ├── WS_FTP.LOG │ ├── inc │ │ ├── protos.h │ │ ├── sfilter.h │ │ └── struct.h │ ├── readme2.txt │ ├── sfilter.ini │ └── src │ │ ├── attach.c │ │ ├── close.c │ │ ├── create.c │ │ ├── dispatch.c │ │ ├── fastio.c │ │ ├── fsctrl.c │ │ ├── makefile │ │ ├── misc.c │ │ ├── obj │ │ ├── _objects.mac │ │ └── i386 │ │ │ ├── checked │ │ │ └── sfilter.sys │ │ │ └── free │ │ │ ├── sfilter.dbg │ │ │ └── sfilter.sys │ │ ├── sfilinit.c │ │ ├── sfilter.rc │ │ └── sources └── fsrec │ ├── WS_FTP.LOG │ ├── inc │ └── sfsrec.h │ ├── readme3.txt │ └── src │ ├── makefile │ ├── obj │ ├── _objects.mac │ └── i386 │ │ ├── checked │ │ └── sfsrec.sys │ │ ├── free │ │ └── sfsrec.sys │ │ └── sfsrec.obj │ ├── sfsrec.c │ └── sources └── README.txt /NTFsrc/filesys/WS_FTP.LOG: -------------------------------------------------------------------------------- 1 | 97.08.05 15:11 B C:\Users\Erik\NTFdisk\filesys\readme1.txt --> geode /home/eray readme1.txt 2 | 97.08.06 14:20 B C:\Users\erik\NTFdisk\filesys\readme1.txt <-- geode /work/nt/file.internals/disk readme1.txt 3 | -------------------------------------------------------------------------------- /NTFsrc/filesys/event/MAKE-MC.BAT: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM The following explain the options used : 3 | REM v = verbose 4 | REM c = set Customer bit in all message ids. 5 | REM s = insert symbolic name as first line of each message. 6 | REM h = pathname where (created) header file should be stored. 7 | REM U = output file should be in Unicode. 8 | 9 | \mstools-351\bin\mc -vcs -h ..\inc -U errmsg.msg 10 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/event/MAKEFILE: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # 3 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 4 | # file to this component. This file merely indirects to the real make file 5 | # that is shared by all the components of NT. 6 | # 7 | ########################################################################## 8 | !INCLUDE $(NTMAKEENV)\makefile.def 9 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/event/README.TXT: -------------------------------------------------------------------------------- 1 | Use the MAKE-MC.BAT file to compile the errmsg.msg file using mc.exe, 2 | which is the Microsoft message compiler. Then use build to create the 3 | required dll. 4 | 5 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/event/SOURCES: -------------------------------------------------------------------------------- 1 | # - Execute the "build" command to make the Sample FSD Event-related dll. 2 | 3 | # 4 | # The TARGETNAME variable is defined by the developer. It is the name of 5 | # the target (component) that is being built by this makefile. It 6 | # should NOT include any path or file extension information. 7 | # 8 | 9 | TARGETNAME=sfsdevnt 10 | 11 | TARGETPATH=obj 12 | 13 | TARGETTYPE=DYNLINK 14 | 15 | INCLUDES=..\inc 16 | 17 | # Source files common to multiple platforms 18 | 19 | SOURCES=dummy.c \ 20 | errmsg.rc 21 | 22 | UNICODE=1 23 | 24 | # 25 | # Next specify any additional options for the compiler. 26 | # 27 | 28 | C_DEFINES=-DUNICODE 29 | 30 | # 31 | # Next specify options for the linker. 32 | # 33 | 34 | DLLBASE=0x62900000 35 | 36 | UMRES=obj\*\sfsdevnt.res 37 | 38 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/event/dummy.c: -------------------------------------------------------------------------------- 1 | void 2 | DummyEntryPoint(void) 3 | { 4 | } 5 | -------------------------------------------------------------------------------- /NTFsrc/filesys/event/errmsg.msg: -------------------------------------------------------------------------------- 1 | ;/************************************************************************* 2 | ;* 3 | ;* File: errmsg.msg 4 | ;* 5 | ;* Product: Sample FSD 6 | ;* 7 | ;* Module: Sample FSD Event Log Messages 8 | ;* 9 | ;* Description: 10 | ;* Contains error strings in a format understandable to the message compiler. 11 | ;* Please compile (using mc) with the -c option which will set the 12 | ;* "Customer" bit in all errors. 13 | ;* Use values beginning at 0xA000 (e.g. 0xA001) for the Sample FSD 14 | ;* errors. 15 | ;* Do NOT use %1 for insertion strings. The I/O manager assumes that 16 | ;* the first insertion string is the name of the driver/device. 17 | ;* 18 | ;* (c) 1996-97 Rajeev Nagar, All Rights Reserved 19 | ;* 20 | ;*************************************************************************/ 21 | MessageIdTypedef=ULONG 22 | 23 | SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS 24 | Informational=0x1:STATUS_SEVERITY_INFORMATIONAL 25 | Warning=0x2:STATUS_SEVERITY_WARNING 26 | Error=0x3:STATUS_SEVERITY_ERROR 27 | ) 28 | 29 | FacilityNames=(IO=0x004) 30 | 31 | MessageId=0xA001 Facility=IO Severity=Error 32 | SymbolicName=SFSD_ERROR_INTERNAL_ERROR 33 | Language=English 34 | The Sample FSD encountered an internal error. Please check log data information. 35 | . 36 | 37 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/event/errmsg.rc: -------------------------------------------------------------------------------- 1 | LANGUAGE 0x9,0x1 2 | 1 11 MSG00001.bin 3 | -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/_objects.mac: -------------------------------------------------------------------------------- 1 | ALPHA_OBJECTS= \ 2 | $(_OBJ_DIR)\alpha\errmsg.res \ 3 | $(_OBJ_DIR)\alpha\dummy.obj 4 | 5 | PASS0_ALPHA_OBJECTS= 6 | 7 | MIPS_OBJECTS= \ 8 | $(_OBJ_DIR)\mips\errmsg.res \ 9 | $(_OBJ_DIR)\mips\dummy.obj 10 | 11 | PASS0_MIPS_OBJECTS= 12 | 13 | 386_OBJECTS= \ 14 | $(_OBJ_DIR)\i386\errmsg.res \ 15 | $(_OBJ_DIR)\i386\dummy.obj 16 | 17 | PASS0_386_OBJECTS= 18 | 19 | PPC_OBJECTS= \ 20 | $(_OBJ_DIR)\ppc\errmsg.res \ 21 | $(_OBJ_DIR)\ppc\dummy.obj 22 | 23 | PASS0_PPC_OBJECTS= 24 | 25 | -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.dll -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.exp -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/checked/sfsdevnt.lib -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/dummy.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/dummy.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/errmsg.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/errmsg.res -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/free/sfsdevnt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/free/sfsdevnt.dll -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/free/sfsdevnt.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/free/sfsdevnt.exp -------------------------------------------------------------------------------- /NTFsrc/filesys/event/obj/i386/free/sfsdevnt.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/event/obj/i386/free/sfsdevnt.lib -------------------------------------------------------------------------------- /NTFsrc/filesys/event/sfsdevnt.def: -------------------------------------------------------------------------------- 1 | LIBRARY SFSDEVENT 2 | 3 | DESCRIPTION 'Sample FSD Event Log Messages' 4 | 5 | EXPORTS 6 | 7 | DummyEntryPoint 8 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/inc/errmsg.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: errmsg.msg 4 | * 5 | * Product: Sample FSD 6 | * 7 | * Module: Sample FSD Event Log Messages 8 | * 9 | * Description: 10 | * Contains error strings in a format understandable to the message compiler. 11 | * Please compile (using mc) with the -c option which will set the 12 | * "Customer" bit in all errors. 13 | * Use values beginning at 0xA000 (e.g. 0xA001) for the Sample FSD 14 | * errors. 15 | * Do NOT use %1 for insertion strings. The I/O manager assumes that 16 | * the first insertion string is the name of the driver/device. 17 | * 18 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 19 | * 20 | *************************************************************************/ 21 | // 22 | // Values are 32 bit values layed out as follows: 23 | // 24 | // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 25 | // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 26 | // +---+-+-+-----------------------+-------------------------------+ 27 | // |Sev|C|R| Facility | Code | 28 | // +---+-+-+-----------------------+-------------------------------+ 29 | // 30 | // where 31 | // 32 | // Sev - is the severity code 33 | // 34 | // 00 - Success 35 | // 01 - Informational 36 | // 10 - Warning 37 | // 11 - Error 38 | // 39 | // C - is the Customer code flag 40 | // 41 | // R - is a reserved bit 42 | // 43 | // Facility - is the facility code 44 | // 45 | // Code - is the facility's status code 46 | // 47 | // 48 | // Define the facility codes 49 | // 50 | 51 | 52 | // 53 | // Define the severity codes 54 | // 55 | #define STATUS_SEVERITY_WARNING 0x2 56 | #define STATUS_SEVERITY_SUCCESS 0x0 57 | #define STATUS_SEVERITY_INFORMATIONAL 0x1 58 | #define STATUS_SEVERITY_ERROR 0x3 59 | 60 | 61 | // 62 | // MessageId: SFSD_ERROR_INTERNAL_ERROR 63 | // 64 | // MessageText: 65 | // 66 | // The Sample FSD encountered an internal error. Please check log data information. 67 | // 68 | #define SFSD_ERROR_INTERNAL_ERROR ((ULONG)0xE004A001L) 69 | 70 | -------------------------------------------------------------------------------- /NTFsrc/filesys/inc/protos.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: protos.h 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains the prototypes for functions in this sample FSD. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #ifndef _SFSD_PROTOS_H_ 17 | #define _SFSD_PROTOS_H_ 18 | 19 | /************************************************************************* 20 | * Prototypes for the file sfsdinit.c 21 | *************************************************************************/ 22 | extern NTSTATUS DriverEntry( 23 | PDRIVER_OBJECT DriverObject, // created by the I/O sub-system 24 | PUNICODE_STRING RegistryPath); // path to the registry key 25 | 26 | extern void SFsdInitializeFunctionPointers( 27 | PDRIVER_OBJECT DriverObject); // created by the I/O sub-system 28 | 29 | /************************************************************************* 30 | * Prototypes for the file create.c 31 | *************************************************************************/ 32 | extern NTSTATUS SFsdCreate( 33 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 34 | PIRP Irp); // I/O Request Packet 35 | 36 | extern NTSTATUS SFsdCommonCreate( 37 | PtrSFsdIrpContext PtrIrpContext, 38 | PIRP PtrIrp); 39 | 40 | extern NTSTATUS SFsdOpenVolume( 41 | PtrSFsdVCB PtrVCB, // volume to be opened 42 | PtrSFsdIrpContext PtrIrpContext, // IRP context 43 | PIRP PtrIrp, // original/user IRP 44 | unsigned short ShareAccess, // share access 45 | PIO_SECURITY_CONTEXT PtrSecurityContext, // caller's context (incl access) 46 | PFILE_OBJECT PtrNewFileObject); // I/O Mgr. created file object 47 | 48 | extern void SFsdInitializeFCB( 49 | PtrSFsdFCB PtrNewFCB, // FCB structure to be initialized 50 | PtrSFsdVCB PtrVCB, // logical volume (VCB) pointer 51 | PtrSFsdObjectName PtrObjectName, // name of the object 52 | uint32 Flags, // is this a file/directory, etc. 53 | PFILE_OBJECT PtrFileObject);// optional file object to be initialized 54 | 55 | /************************************************************************* 56 | * Prototypes for the file misc.c 57 | *************************************************************************/ 58 | extern NTSTATUS SFsdInitializeZones( 59 | void); 60 | 61 | extern void SFsdDestroyZones( 62 | void); 63 | 64 | extern BOOLEAN SFsdIsIrpTopLevel( 65 | PIRP Irp); // the IRP sent to our dispatch routine 66 | 67 | extern long SFsdExceptionFilter( 68 | PtrSFsdIrpContext PtrIrpContext, 69 | PEXCEPTION_POINTERS PtrExceptionPointers); 70 | 71 | extern NTSTATUS SFsdExceptionHandler( 72 | PtrSFsdIrpContext PtrIrpContext, 73 | PIRP Irp); 74 | 75 | extern void SFsdLogEvent( 76 | NTSTATUS SFsdEventLogId, // the SFsd private message id 77 | NTSTATUS RC); // any NT error code we wish to log ... 78 | 79 | extern PtrSFsdObjectName SFsdAllocateObjectName( 80 | void); 81 | 82 | extern void SFsdReleaseObjectName( 83 | PtrSFsdObjectName PtrObjectName); 84 | 85 | extern PtrSFsdCCB SFsdAllocateCCB( 86 | void); 87 | 88 | extern void SFsdReleaseCCB( 89 | PtrSFsdCCB PtrCCB); 90 | 91 | extern PtrSFsdFCB SFsdAllocateFCB( 92 | void); 93 | 94 | extern NTSTATUS SFsdCreateNewFCB( 95 | PtrSFsdFCB *ReturnedFCB, 96 | PLARGE_INTEGER AllocationSize, 97 | PLARGE_INTEGER EndOfFile, 98 | PFILE_OBJECT PtrFileObject, 99 | PtrSFsdVCB PtrVCB); 100 | 101 | extern void SFsdReleaseFCB( 102 | PtrSFsdFCB PtrFCB); 103 | 104 | extern PtrSFsdFileLockInfo SFsdAllocateByteLocks( 105 | void); 106 | 107 | extern void SFsdReleaseByteLocks( 108 | PtrSFsdFileLockInfo PtrByteLocks); 109 | 110 | extern PtrSFsdIrpContext SFsdAllocateIrpContext( 111 | PIRP Irp, 112 | PDEVICE_OBJECT PtrTargetDeviceObject); 113 | 114 | extern void SFsdReleaseIrpContext( 115 | PtrSFsdIrpContext PtrIrpContext); 116 | 117 | extern NTSTATUS SFsdPostRequest( 118 | PtrSFsdIrpContext PtrIrpContext, 119 | PIRP PtrIrp); 120 | 121 | extern void SFsdCommonDispatch( 122 | void *Context); // actually an IRPContext structure 123 | 124 | extern void SFsdInitializeVCB( 125 | PDEVICE_OBJECT PtrVolumeDeviceObject, 126 | PDEVICE_OBJECT PtrTargetDeviceObject, 127 | PVPB PtrVPB); 128 | 129 | /************************************************************************* 130 | * Prototypes for the file cleanup.c 131 | *************************************************************************/ 132 | extern NTSTATUS SFsdCleanup( 133 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 134 | PIRP Irp); // I/O Request Packet 135 | 136 | extern NTSTATUS SFsdCommonCleanup( 137 | PtrSFsdIrpContext PtrIrpContext, 138 | PIRP PtrIrp); 139 | 140 | /************************************************************************* 141 | * Prototypes for the file close.c 142 | *************************************************************************/ 143 | extern NTSTATUS SFsdClose( 144 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 145 | PIRP Irp); // I/O Request Packet 146 | 147 | extern NTSTATUS SFsdCommonClose( 148 | PtrSFsdIrpContext PtrIrpContext, 149 | PIRP PtrIrp); 150 | 151 | /************************************************************************* 152 | * Prototypes for the file read.c 153 | *************************************************************************/ 154 | extern NTSTATUS SFsdRead( 155 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 156 | PIRP Irp); // I/O Request Packet 157 | 158 | extern NTSTATUS SFsdCommonRead( 159 | PtrSFsdIrpContext PtrIrpContext, 160 | PIRP PtrIrp); 161 | 162 | extern void *SFsdGetCallersBuffer( 163 | PIRP PtrIrp); 164 | 165 | extern NTSTATUS SFsdLockCallersBuffer( 166 | PIRP PtrIrp, 167 | BOOLEAN IsReadOperation, 168 | uint32 Length); 169 | 170 | extern void SFsdMdlComplete( 171 | PtrSFsdIrpContext PtrIrpContext, 172 | PIRP PtrIrp, 173 | PIO_STACK_LOCATION PtrIoStackLocation, 174 | BOOLEAN ReadCompletion); 175 | 176 | /************************************************************************* 177 | * Prototypes for the file write.c 178 | *************************************************************************/ 179 | extern NTSTATUS SFsdWrite( 180 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 181 | PIRP Irp); // I/O Request Packet 182 | 183 | extern NTSTATUS SFsdCommonWrite( 184 | PtrSFsdIrpContext PtrIrpContext, 185 | PIRP PtrIrp); 186 | 187 | extern void SFsdDeferredWriteCallBack ( 188 | void *Context1, // Should be PtrIrpContext 189 | void *Context2); // Should be PtrIrp 190 | 191 | /************************************************************************* 192 | * Prototypes for the file fileinfo.c 193 | *************************************************************************/ 194 | extern NTSTATUS SFsdFileInfo( 195 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 196 | PIRP Irp); // I/O Request Packet 197 | 198 | extern NTSTATUS SFsdCommonFileInfo( 199 | PtrSFsdIrpContext PtrIrpContext, 200 | PIRP PtrIrp); 201 | 202 | extern NTSTATUS SFsdGetBasicInformation( 203 | PtrSFsdFCB PtrFCB, 204 | PFILE_BASIC_INFORMATION PtrBuffer, 205 | long *PtrReturnedLength); 206 | 207 | extern NTSTATUS SFsdSetBasicInformation( 208 | PtrSFsdFCB PtrFCB, 209 | PtrSFsdCCB PtrCCB, 210 | PFILE_OBJECT PtrFileObject, 211 | PFILE_BASIC_INFORMATION PtrBuffer); 212 | 213 | extern NTSTATUS SFsdSetDispositionInformation( 214 | PtrSFsdFCB PtrFCB, 215 | PtrSFsdCCB PtrCCB, 216 | PtrSFsdVCB PtrVCB, 217 | PFILE_OBJECT PtrFileObject, 218 | PtrSFsdIrpContext PtrIrpContext, 219 | PIRP PtrIrp, 220 | PFILE_DISPOSITION_INFORMATION PtrBuffer); 221 | 222 | extern NTSTATUS SFsdSetAllocationInformation( 223 | PtrSFsdFCB PtrFCB, 224 | PtrSFsdCCB PtrCCB, 225 | PtrSFsdVCB PtrVCB, 226 | PFILE_OBJECT PtrFileObject, 227 | PtrSFsdIrpContext PtrIrpContext, 228 | PIRP PtrIrp, 229 | PFILE_ALLOCATION_INFORMATION PtrBuffer); 230 | 231 | /************************************************************************* 232 | * Prototypes for the file flush.c 233 | *************************************************************************/ 234 | extern NTSTATUS SFsdFlush( 235 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 236 | PIRP Irp); // I/O Request Packet 237 | 238 | extern NTSTATUS SFsdCommonFlush( 239 | PtrSFsdIrpContext PtrIrpContext, 240 | PIRP PtrIrp); 241 | 242 | extern void SFsdFlushAFile( 243 | PtrSFsdNTRequiredFCB PtrReqdFCB, 244 | PIO_STATUS_BLOCK PtrIoStatus); 245 | 246 | extern void SFsdFlushLogicalVolume( 247 | PtrSFsdIrpContext PtrIrpContext, 248 | PIRP PtrIrp, 249 | PtrSFsdVCB PtrVCB); 250 | 251 | extern NTSTATUS SFsdFlushCompletion( 252 | PDEVICE_OBJECT PtrDeviceObject, 253 | PIRP PtrIrp, 254 | PVOID Context); 255 | 256 | /************************************************************************* 257 | * Prototypes for the file dircntrl.c 258 | *************************************************************************/ 259 | extern NTSTATUS SFsdDirControl( 260 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 261 | PIRP Irp); // I/O Request Packet 262 | 263 | extern NTSTATUS SFsdCommonDirControl( 264 | PtrSFsdIrpContext PtrIrpContext, 265 | PIRP PtrIrp); 266 | 267 | extern NTSTATUS SFsdQueryDirectory( 268 | PtrSFsdIrpContext PtrIrpContext, 269 | PIRP PtrIrp, 270 | PIO_STACK_LOCATION PtrIoStackLocation, 271 | PFILE_OBJECT PtrFileObject, 272 | PtrSFsdFCB PtrFCB, 273 | PtrSFsdCCB PtrCCB); 274 | 275 | extern NTSTATUS SFsdNotifyChangeDirectory( 276 | PtrSFsdIrpContext PtrIrpContext, 277 | PIRP PtrIrp, 278 | PIO_STACK_LOCATION PtrIoStackLocation, 279 | PFILE_OBJECT PtrFileObject, 280 | PtrSFsdFCB PtrFCB, 281 | PtrSFsdCCB PtrCCB); 282 | 283 | /************************************************************************* 284 | * Prototypes for the file devcntrl.c 285 | *************************************************************************/ 286 | extern NTSTATUS SFsdDeviceControl( 287 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 288 | PIRP Irp); // I/O Request Packet 289 | 290 | extern NTSTATUS SFsdCommonDeviceControl( 291 | PtrSFsdIrpContext PtrIrpContext, 292 | PIRP PtrIrp); 293 | 294 | extern NTSTATUS SFsdDevIoctlCompletion( 295 | PDEVICE_OBJECT PtrDeviceObject, 296 | PIRP PtrIrp, 297 | void *Context); 298 | 299 | extern NTSTATUS SFsdHandleQueryPath( 300 | void *BufferPointer); 301 | 302 | /************************************************************************* 303 | * Prototypes for the file shutdown.c 304 | *************************************************************************/ 305 | extern NTSTATUS SFsdShutdown( 306 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 307 | PIRP Irp); // I/O Request Packet 308 | 309 | extern NTSTATUS SFsdCommonShutdown( 310 | PtrSFsdIrpContext PtrIrpContext, 311 | PIRP PtrIrp); 312 | 313 | /************************************************************************* 314 | * Prototypes for the file fastio.c 315 | *************************************************************************/ 316 | extern BOOLEAN SFsdFastIoCheckIfPossible( 317 | IN PFILE_OBJECT FileObject, 318 | IN PLARGE_INTEGER FileOffset, 319 | IN ULONG Length, 320 | IN BOOLEAN Wait, 321 | IN ULONG LockKey, 322 | IN BOOLEAN CheckForReadOperation, 323 | OUT PIO_STATUS_BLOCK IoStatus, 324 | IN PDEVICE_OBJECT DeviceObject); 325 | 326 | extern BOOLEAN SFsdFastIoRead( 327 | IN PFILE_OBJECT FileObject, 328 | IN PLARGE_INTEGER FileOffset, 329 | IN ULONG Length, 330 | IN BOOLEAN Wait, 331 | IN ULONG LockKey, 332 | OUT PVOID Buffer, 333 | OUT PIO_STATUS_BLOCK IoStatus, 334 | IN PDEVICE_OBJECT DeviceObject); 335 | 336 | extern BOOLEAN SFsdFastIoWrite( 337 | IN PFILE_OBJECT FileObject, 338 | IN PLARGE_INTEGER FileOffset, 339 | IN ULONG Length, 340 | IN BOOLEAN Wait, 341 | IN ULONG LockKey, 342 | OUT PVOID Buffer, 343 | OUT PIO_STATUS_BLOCK IoStatus, 344 | IN PDEVICE_OBJECT DeviceObject); 345 | 346 | extern BOOLEAN SFsdFastIoQueryBasicInfo( 347 | IN PFILE_OBJECT FileObject, 348 | IN BOOLEAN Wait, 349 | OUT PFILE_BASIC_INFORMATION Buffer, 350 | OUT PIO_STATUS_BLOCK IoStatus, 351 | IN PDEVICE_OBJECT DeviceObject); 352 | 353 | extern BOOLEAN SFsdFastIoQueryStdInfo( 354 | IN PFILE_OBJECT FileObject, 355 | IN BOOLEAN Wait, 356 | OUT PFILE_STANDARD_INFORMATION Buffer, 357 | OUT PIO_STATUS_BLOCK IoStatus, 358 | IN PDEVICE_OBJECT DeviceObject); 359 | 360 | extern BOOLEAN SFsdFastIoLock( 361 | IN PFILE_OBJECT FileObject, 362 | IN PLARGE_INTEGER FileOffset, 363 | IN PLARGE_INTEGER Length, 364 | PEPROCESS ProcessId, 365 | ULONG Key, 366 | BOOLEAN FailImmediately, 367 | BOOLEAN ExclusiveLock, 368 | OUT PIO_STATUS_BLOCK IoStatus, 369 | IN PDEVICE_OBJECT DeviceObject); 370 | 371 | extern BOOLEAN SFsdFastIoUnlockSingle( 372 | IN PFILE_OBJECT FileObject, 373 | IN PLARGE_INTEGER FileOffset, 374 | IN PLARGE_INTEGER Length, 375 | PEPROCESS ProcessId, 376 | ULONG Key, 377 | OUT PIO_STATUS_BLOCK IoStatus, 378 | IN PDEVICE_OBJECT DeviceObject); 379 | 380 | extern BOOLEAN SFsdFastIoUnlockAll( 381 | IN PFILE_OBJECT FileObject, 382 | PEPROCESS ProcessId, 383 | OUT PIO_STATUS_BLOCK IoStatus, 384 | IN PDEVICE_OBJECT DeviceObject); 385 | 386 | extern BOOLEAN SFsdFastIoUnlockAllByKey( 387 | IN PFILE_OBJECT FileObject, 388 | PEPROCESS ProcessId, 389 | ULONG Key, 390 | OUT PIO_STATUS_BLOCK IoStatus, 391 | IN PDEVICE_OBJECT DeviceObject); 392 | 393 | extern void SFsdFastIoAcqCreateSec( 394 | IN PFILE_OBJECT FileObject); 395 | 396 | extern void SFsdFastIoRelCreateSec( 397 | IN PFILE_OBJECT FileObject); 398 | 399 | extern BOOLEAN SFsdAcqLazyWrite( 400 | IN PVOID Context, 401 | IN BOOLEAN Wait); 402 | 403 | extern void SFsdRelLazyWrite( 404 | IN PVOID Context); 405 | 406 | extern BOOLEAN SFsdAcqReadAhead( 407 | IN PVOID Context, 408 | IN BOOLEAN Wait); 409 | 410 | extern void SFsdRelReadAhead( 411 | IN PVOID Context); 412 | 413 | // the remaining are only valid under NT Version 4.0 and later 414 | #if(_WIN32_WINNT >= 0x0400) 415 | 416 | extern BOOLEAN SFsdFastIoQueryNetInfo( 417 | IN PFILE_OBJECT FileObject, 418 | IN BOOLEAN Wait, 419 | OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, 420 | OUT PIO_STATUS_BLOCK IoStatus, 421 | IN PDEVICE_OBJECT DeviceObject); 422 | 423 | extern BOOLEAN SFsdFastIoMdlRead( 424 | IN PFILE_OBJECT FileObject, 425 | IN PLARGE_INTEGER FileOffset, 426 | IN ULONG Length, 427 | IN ULONG LockKey, 428 | OUT PMDL *MdlChain, 429 | OUT PIO_STATUS_BLOCK IoStatus, 430 | IN PDEVICE_OBJECT DeviceObject); 431 | 432 | extern BOOLEAN SFsdFastIoMdlReadComplete( 433 | IN PFILE_OBJECT FileObject, 434 | OUT PMDL MdlChain, 435 | IN PDEVICE_OBJECT DeviceObject); 436 | 437 | extern BOOLEAN SFsdFastIoPrepareMdlWrite( 438 | IN PFILE_OBJECT FileObject, 439 | IN PLARGE_INTEGER FileOffset, 440 | IN ULONG Length, 441 | IN ULONG LockKey, 442 | OUT PMDL *MdlChain, 443 | OUT PIO_STATUS_BLOCK IoStatus, 444 | IN PDEVICE_OBJECT DeviceObject); 445 | 446 | extern BOOLEAN SFsdFastIoMdlWriteComplete( 447 | IN PFILE_OBJECT FileObject, 448 | IN PLARGE_INTEGER FileOffset, 449 | OUT PMDL MdlChain, 450 | IN PDEVICE_OBJECT DeviceObject); 451 | 452 | extern NTSTATUS SFsdFastIoAcqModWrite( 453 | IN PFILE_OBJECT FileObject, 454 | IN PLARGE_INTEGER EndingOffset, 455 | OUT PERESOURCE *ResourceToRelease, 456 | IN PDEVICE_OBJECT DeviceObject); 457 | 458 | extern NTSTATUS SFsdFastIoRelModWrite( 459 | IN PFILE_OBJECT FileObject, 460 | IN PERESOURCE ResourceToRelease, 461 | IN PDEVICE_OBJECT DeviceObject); 462 | 463 | extern NTSTATUS SFsdFastIoAcqCcFlush( 464 | IN PFILE_OBJECT FileObject, 465 | IN PDEVICE_OBJECT DeviceObject); 466 | 467 | extern NTSTATUS SFsdFastIoRelCcFlush( 468 | IN PFILE_OBJECT FileObject, 469 | IN PDEVICE_OBJECT DeviceObject); 470 | 471 | #endif // (_WIN32_WINNT >= 0x0400) 472 | 473 | #endif // _SFSD_PROTOS_H_ 474 | 475 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/inc/sfsd.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfsd.h 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * The main include file for the sample file system driver. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #ifndef _SFSD_SFSD_H_ 17 | #define _SFSD_SFSD_H_ 18 | 19 | // some constant definitions 20 | #define SFSD_PANIC_IDENTIFIER (0x86427531) 21 | 22 | // any directory information SFSD obtains from the local file system 23 | // will use a buffer of the following size ... (in KB) 24 | #define SFSD_READ_DIR_BUFFER_LENGTH (512) 25 | 26 | // Common include files - should be in the include dir of the MS supplied IFS Kit 27 | #include 28 | 29 | // the following include files should be in the inc sub-dir associated with this driver 30 | #include "struct.h" 31 | #include "protos.h" 32 | #include "errmsg.h" 33 | 34 | // global variables - minimize these 35 | extern SFsdData SFsdGlobalData; 36 | 37 | // try-finally simulation 38 | #define try_return(S) { S; goto try_exit; } 39 | #define try_return1(S) { S; goto try_exit1; } 40 | #define try_return2(S) { S; goto try_exit2; } 41 | 42 | // some global (helpful) macros 43 | #define SFsdSetFlag(Flag, Value) ((Flag) |= (Value)) 44 | #define SFsdClearFlag(Flag, Value) ((Flag) &= ~(Value)) 45 | 46 | #define SFsdQuadAlign(Value) ((((uint32)(Value)) + 7) & 0xfffffff8) 47 | 48 | // to perform a bug-check (panic), the following macro is used 49 | #define SFsdPanic(arg1, arg2, arg3) \ 50 | (KeBugCheckEx(SFSD_PANIC_IDENTIFIER, SFSD_BUG_CHECK_ID | __LINE__, (uint32)(arg1), (uint32)(arg2), (uint32)(arg3))) 51 | 52 | // a convenient macro (must be invoked in the context of the thread that acquired the resource) 53 | #define SFsdReleaseResource(Resource) \ 54 | (ExReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread())) 55 | 56 | // each file has a unique bug-check identifier associated with it. 57 | // Here is a list of constant definitions for these identifiers 58 | #define SFSD_FILE_INIT (0x00000001) 59 | #define SFSD_FILE_REGISTRY (0x00000002) 60 | #define SFSD_FILE_CREATE (0x00000003) 61 | #define SFSD_FILE_CLEANUP (0x00000004) 62 | #define SFSD_FILE_CLOSE (0x00000005) 63 | #define SFSD_FILE_READ (0x00000006) 64 | #define SFSD_FILE_WRITE (0x00000007) 65 | #define SFSD_FILE_INFORMATION (0x00000008) 66 | #define SFSD_FILE_FLUSH (0x00000009) 67 | #define SFSD_FILE_VOL_INFORMATION (0x0000000A) 68 | #define SFSD_FILE_DIR_CONTROL (0x0000000B) 69 | #define SFSD_FILE_FILE_CONTROL (0x0000000C) 70 | #define SFSD_FILE_DEVICE_CONTROL (0x0000000D) 71 | #define SFSD_FILE_SHUTDOWN (0x0000000E) 72 | #define SFSD_FILE_LOCK_CONTROL (0x0000000F) 73 | #define SFSD_FILE_SECURITY (0x00000010) 74 | #define SFSD_FILE_EXT_ATTR (0x00000011) 75 | #define SFSD_FILE_MISC (0x00000012) 76 | #define SFSD_FILE_FAST_IO (0x00000013) 77 | 78 | #if DBG 79 | #define SFsdBreakPoint() DbgBreakPoint() 80 | #else 81 | #define SFsdBreakPoint() 82 | #endif 83 | 84 | #endif // _SFSD_SFSD_H_ 85 | 86 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/readme1.txt: -------------------------------------------------------------------------------- 1 | Sample File System Driver 2 | ------------------------ 3 | 4 | The sample file system driver code provided here can be used to 5 | design and implement your own file system driver product. 6 | 7 | !!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 8 | 9 | The code provided here is for illustration purposes only. It is not 10 | to be used as-is. Substantial modifications, enhancements, and testing 11 | are required before installing any portion of the code on any machine. 12 | 13 | DO NOT EXPECT THIS CODE TO WORK. IT IS ONLY TO BE USED AS A GUIDE 14 | IN CONJUNCTION WITH THE TEXT CONTAINED IN THE BOOK IN DESIGNING YOUR 15 | OWN FSD. IT IS SEVERELY LACKING IN FUNCTIONALITY AND HAS NEVER BEEN 16 | INSTALLED OR TESTED AS IS COMMONLY REQUIRED. 17 | 18 | TO COMPILE THE SOURCES PROVIDED HERE, YOU MUST HAVE A COPY OF THE 19 | "ntifs.h" HEADER FILE PROVIDED BY MICROSOFT AS PART OF THE WINDOWS NT 20 | IFS KIT. 21 | 22 | !!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 23 | 24 | Files provided: 25 | -------------- 26 | 27 | src\sfsdinit.c - File system driver initialization functions 28 | src\create.c - Routines to support create/open requests 29 | src\cleanup.c - Stub functions for the cleanup dispatch entry point 30 | src\close.c - Stub functions for the close dispatch entry point 31 | src\dircntrl.c - Routines to support directory control requests 32 | src\read.c - Support for the read dispatch routine 33 | src\write.c - Support for the write dispatch routine 34 | src\fastio.c - The fast I/O entry points (and Cache Manager callbacks) 35 | src\flush.c - Support for the flush entry point 36 | src\devcntrl.c - Device IOCTL support 37 | src\fileinfo.c - Query/modify file attributes 38 | src\shutdown.c - Support for the shutdown notification call 39 | src\misc.c - Everything that didn't fit into the above, but was required 40 | for compilation purposes 41 | inc\protos.h - Prototypes for all functions in files listed above 42 | inc\sfsd.h - The "main" include file; also contains useful macros 43 | inc\struct.h - Structure type definitions 44 | inc\errmsg.h - Automatically generated include file 45 | (by the message compiler) that allows reporting of 46 | FSD-specific error/warning/informational 47 | messages in the event log (see the event subdirectory) 48 | src\makefile - makefile! 49 | src\sources - Contains list of files to be built; used by build.exe 50 | README.TXT - What you are reading 51 | 52 |  53 | -------------------------------------------------------------------------------- /NTFsrc/filesys/src/cleanup.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: cleanup.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Should contain code to handle the "Cleanup" dispatch entry point. 9 | * This file serves as a placeholder. Please update this file as part 10 | * of designing and implementing your FSD. 11 | * 12 | * Author: R. Nagar 13 | * 14 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 15 | * 16 | *************************************************************************/ 17 | 18 | #include "sfsd.h" 19 | 20 | // define the file specific bug-check id 21 | #define SFSD_BUG_CHECK_ID SFSD_FILE_CLEANUP 22 | 23 | 24 | 25 | /************************************************************************* 26 | * 27 | * Function: SFsdCleanup() 28 | * 29 | * Description: 30 | * The I/O Manager will invoke this routine to handle a cleanup 31 | * request 32 | * 33 | * Expected Interrupt Level (for execution) : 34 | * 35 | * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 36 | * to be deferred to a worker thread context) 37 | * 38 | * Return Value: Does not matter! 39 | * 40 | *************************************************************************/ 41 | NTSTATUS SFsdCleanup( 42 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 43 | PIRP Irp) // I/O Request Packet 44 | { 45 | NTSTATUS RC = STATUS_SUCCESS; 46 | PtrSFsdIrpContext PtrIrpContext = NULL; 47 | BOOLEAN AreWeTopLevel = FALSE; 48 | 49 | FsRtlEnterFileSystem(); 50 | ASSERT(DeviceObject); 51 | ASSERT(Irp); 52 | 53 | // set the top level context 54 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 55 | 56 | try { 57 | 58 | // get an IRP context structure and issue the request 59 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 60 | ASSERT(PtrIrpContext); 61 | 62 | RC = SFsdCommonCleanup(PtrIrpContext, Irp); 63 | 64 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 65 | 66 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 67 | 68 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 69 | } 70 | 71 | if (AreWeTopLevel) { 72 | IoSetTopLevelIrp(NULL); 73 | } 74 | 75 | FsRtlExitFileSystem(); 76 | 77 | return(RC); 78 | } 79 | 80 | 81 | 82 | /************************************************************************* 83 | * 84 | * Function: SFsdCommonCleanup() 85 | * 86 | * Description: 87 | * The actual work is performed here. This routine may be invoked in one' 88 | * of the two possible contexts: 89 | * (a) in the context of a system worker thread 90 | * (b) in the context of the original caller 91 | * 92 | * Expected Interrupt Level (for execution) : 93 | * 94 | * IRQL_PASSIVE_LEVEL 95 | * 96 | * Return Value: Does not matter! 97 | * 98 | *************************************************************************/ 99 | NTSTATUS SFsdCommonCleanup( 100 | PtrSFsdIrpContext PtrIrpContext, 101 | PIRP PtrIrp) 102 | { 103 | NTSTATUS RC = STATUS_SUCCESS; 104 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 105 | PFILE_OBJECT PtrFileObject = NULL; 106 | PtrSFsdFCB PtrFCB = NULL; 107 | PtrSFsdCCB PtrCCB = NULL; 108 | PtrSFsdVCB PtrVCB = NULL; 109 | PtrSFsdNTRequiredFCB PtrReqdFCB = NULL; 110 | PERESOURCE PtrResourceAcquired = NULL; 111 | IO_STATUS_BLOCK LocalIoStatus; 112 | 113 | BOOLEAN CompleteIrp = TRUE; 114 | BOOLEAN PostRequest = FALSE; 115 | 116 | BOOLEAN CanWait = FALSE; 117 | 118 | try { 119 | // First, get a pointer to the current I/O stack location 120 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 121 | ASSERT(PtrIoStackLocation); 122 | 123 | PtrFileObject = PtrIoStackLocation->FileObject; 124 | ASSERT(PtrFileObject); 125 | 126 | // Get the FCB and CCB pointers 127 | PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 128 | ASSERT(PtrCCB); 129 | PtrFCB = PtrCCB->PtrFCB; 130 | ASSERT(PtrFCB); 131 | 132 | PtrVCB = (PtrSFsdVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension); 133 | ASSERT(PtrVCB); 134 | ASSERT(PtrVCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB); 135 | 136 | // Steps you will probably take at this point are: 137 | // (a) Acquire the VCB exclusively 138 | // (b) Acquire the file (FCB) exclusively 139 | // (c) Flush file data to disk 140 | // (d) Talk to the FSRTL package (if you use it) about pending oplocks. 141 | // (e) Notify the FSRTL package (if you use it) for use with pending 142 | // notification IRPs 143 | // (f) Unlock byte-range locks (if any were acquired by process) 144 | // (g) Update time stamp values (e.g. fast-IO had been performed) 145 | // (h) Inform the Cache Manager to uninitialize Cache Maps ... 146 | // and other similar stuff. Chapter 10 in the book describes in further 147 | // detail the list of functionality expected from a typical cleanup routine. 148 | 149 | try_exit: NOTHING; 150 | 151 | } finally { 152 | 153 | // See the read/write examples for how to fill in this portion 154 | 155 | } // end of "finally" processing 156 | 157 | return(RC); 158 | } 159 | 160 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/close.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: close.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Should contain code to handle the "Close" dispatch entry point. 9 | * This file serves as a placeholder. Please update this file as part 10 | * of designing and implementing your FSD. 11 | * 12 | * Author: R. Nagar 13 | * 14 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 15 | * 16 | *************************************************************************/ 17 | 18 | #include "sfsd.h" 19 | 20 | // define the file specific bug-check id 21 | #define SFSD_BUG_CHECK_ID SFSD_FILE_CLOSE 22 | 23 | 24 | 25 | /************************************************************************* 26 | * 27 | * Function: SFsdClose() 28 | * 29 | * Description: 30 | * The I/O Manager will invoke this routine to handle a close 31 | * request 32 | * 33 | * Expected Interrupt Level (for execution) : 34 | * 35 | * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 36 | * to be deferred to a worker thread context) 37 | * 38 | * Return Value: Does not matter! 39 | * 40 | *************************************************************************/ 41 | NTSTATUS SFsdClose( 42 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 43 | PIRP Irp) // I/O Request Packet 44 | { 45 | NTSTATUS RC = STATUS_SUCCESS; 46 | PtrSFsdIrpContext PtrIrpContext = NULL; 47 | BOOLEAN AreWeTopLevel = FALSE; 48 | 49 | FsRtlEnterFileSystem(); 50 | ASSERT(DeviceObject); 51 | ASSERT(Irp); 52 | 53 | // set the top level context 54 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 55 | 56 | try { 57 | 58 | // get an IRP context structure and issue the request 59 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 60 | ASSERT(PtrIrpContext); 61 | 62 | RC = SFsdCommonClose(PtrIrpContext, Irp); 63 | 64 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 65 | 66 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 67 | 68 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 69 | } 70 | 71 | if (AreWeTopLevel) { 72 | IoSetTopLevelIrp(NULL); 73 | } 74 | 75 | FsRtlExitFileSystem(); 76 | 77 | return(RC); 78 | } 79 | 80 | 81 | 82 | 83 | /************************************************************************* 84 | * 85 | * Function: SFsdCommonClose() 86 | * 87 | * Description: 88 | * The actual work is performed here. This routine may be invoked in one' 89 | * of the two possible contexts: 90 | * (a) in the context of a system worker thread 91 | * (b) in the context of the original caller 92 | * 93 | * Expected Interrupt Level (for execution) : 94 | * 95 | * IRQL_PASSIVE_LEVEL 96 | * 97 | * Return Value: Does not matter! 98 | * 99 | *************************************************************************/ 100 | NTSTATUS SFsdCommonClose( 101 | PtrSFsdIrpContext PtrIrpContext, 102 | PIRP PtrIrp) 103 | { 104 | NTSTATUS RC = STATUS_SUCCESS; 105 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 106 | PFILE_OBJECT PtrFileObject = NULL; 107 | PtrSFsdFCB PtrFCB = NULL; 108 | PtrSFsdCCB PtrCCB = NULL; 109 | PtrSFsdVCB PtrVCB = NULL; 110 | PtrSFsdNTRequiredFCB PtrReqdFCB = NULL; 111 | PERESOURCE PtrResourceAcquired = NULL; 112 | IO_STATUS_BLOCK LocalIoStatus; 113 | 114 | BOOLEAN CompleteIrp = TRUE; 115 | BOOLEAN PostRequest = FALSE; 116 | 117 | BOOLEAN CanWait = FALSE; 118 | 119 | try { 120 | // First, get a pointer to the current I/O stack location 121 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 122 | ASSERT(PtrIoStackLocation); 123 | 124 | PtrFileObject = PtrIoStackLocation->FileObject; 125 | ASSERT(PtrFileObject); 126 | 127 | // Get the FCB and CCB pointers 128 | PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 129 | ASSERT(PtrCCB); 130 | PtrFCB = PtrCCB->PtrFCB; 131 | ASSERT(PtrFCB); 132 | 133 | PtrVCB = (PtrSFsdVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension); 134 | ASSERT(PtrVCB); 135 | ASSERT(PtrVCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB); 136 | 137 | // Steps you will probably take at this point are: 138 | // (a) Acquire the VCB exclusively 139 | // (b) Acquire the file (FCB) exclusively 140 | // (c) Delete the CCB structure (free memory) 141 | // (d) If this is the last close, release the FCB structure (unless you keep these 142 | // around for "delayed close" functionality. 143 | // Note that it is often the case that the close dispatch entry point is invoked 144 | // in the most inconvenient of situations (when it is not possible, for example, 145 | // to safely acquire certain required resources without deadlocking or waiting). 146 | // Therefore, be extremely careful in implementing this close dispatch entry point. 147 | // Also note that you do not have the option of returning a failure code from the 148 | // close dispatch entry point; the system expects that the close will always succeed. 149 | 150 | try_exit: NOTHING; 151 | 152 | } finally { 153 | 154 | // See the read/write examples for how to fill in this portion 155 | 156 | } // end of "finally" processing 157 | 158 | return(RC); 159 | } 160 | 161 | 162 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/devcntrl.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: devcntrl.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains code to handle the "Device IOCTL" dispatch entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfsd.h" 17 | 18 | // define the file specific bug-check id 19 | #define SFSD_BUG_CHECK_ID SFSD_FILE_DEVICE_CONTROL 20 | 21 | #if(_WIN32_WINNT < 0x0400) 22 | #define IOCTL_REDIR_QUERY_PATH CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS) 23 | 24 | typedef struct _QUERY_PATH_REQUEST { 25 | ULONG PathNameLength; 26 | PIO_SECURITY_CONTEXT SecurityContext; 27 | WCHAR FilePathName[1]; 28 | } QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST; 29 | 30 | typedef struct _QUERY_PATH_RESPONSE { 31 | ULONG LengthAccepted; 32 | } QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE; 33 | #endif 34 | 35 | 36 | /************************************************************************* 37 | * 38 | * Function: SFsdDeviceControl() 39 | * 40 | * Description: 41 | * The I/O Manager will invoke this routine to handle a Device IOCTL 42 | * request 43 | * 44 | * Expected Interrupt Level (for execution) : 45 | * 46 | * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 47 | * to be deferred to a worker thread context) 48 | * 49 | * Return Value: STATUS_SUCCESS/Error 50 | * 51 | *************************************************************************/ 52 | NTSTATUS SFsdDeviceControl( 53 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 54 | PIRP Irp) // I/O Request Packet 55 | { 56 | NTSTATUS RC = STATUS_SUCCESS; 57 | PtrSFsdIrpContext PtrIrpContext = NULL; 58 | BOOLEAN AreWeTopLevel = FALSE; 59 | 60 | FsRtlEnterFileSystem(); 61 | ASSERT(DeviceObject); 62 | ASSERT(Irp); 63 | 64 | // set the top level context 65 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 66 | 67 | try { 68 | 69 | // get an IRP context structure and issue the request 70 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 71 | ASSERT(PtrIrpContext); 72 | 73 | RC = SFsdCommonDeviceControl(PtrIrpContext, Irp); 74 | 75 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 76 | 77 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 78 | 79 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 80 | } 81 | 82 | if (AreWeTopLevel) { 83 | IoSetTopLevelIrp(NULL); 84 | } 85 | 86 | FsRtlExitFileSystem(); 87 | 88 | return(RC); 89 | } 90 | 91 | 92 | 93 | /************************************************************************* 94 | * 95 | * Function: SFsdCommonDeviceControl() 96 | * 97 | * Description: 98 | * The actual work is performed here. This routine may be invoked in one' 99 | * of the two possible contexts: 100 | * (a) in the context of a system worker thread 101 | * (b) in the context of the original caller 102 | * 103 | * Expected Interrupt Level (for execution) : 104 | * 105 | * IRQL_PASSIVE_LEVEL 106 | * 107 | * Return Value: STATUS_SUCCESS/Error 108 | * 109 | *************************************************************************/ 110 | NTSTATUS SFsdCommonDeviceControl( 111 | PtrSFsdIrpContext PtrIrpContext, 112 | PIRP PtrIrp) 113 | { 114 | NTSTATUS RC = STATUS_SUCCESS; 115 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 116 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 117 | PFILE_OBJECT PtrFileObject = NULL; 118 | PtrSFsdFCB PtrFCB = NULL; 119 | PtrSFsdCCB PtrCCB = NULL; 120 | PtrSFsdVCB PtrVCB = NULL; 121 | BOOLEAN CompleteIrp = FALSE; 122 | ULONG IoControlCode = 0; 123 | void *BufferPointer = NULL; 124 | 125 | try { 126 | // First, get a pointer to the current I/O stack location 127 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 128 | ASSERT(PtrIoStackLocation); 129 | 130 | PtrFileObject = PtrIoStackLocation->FileObject; 131 | ASSERT(PtrFileObject); 132 | 133 | PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 134 | ASSERT(PtrCCB); 135 | PtrFCB = PtrCCB->PtrFCB; 136 | ASSERT(PtrFCB); 137 | 138 | if (PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) { 139 | PtrVCB = (PtrSFsdVCB)(PtrFCB); 140 | } else { 141 | PtrVCB = PtrFCB->PtrVCB; 142 | } 143 | 144 | // Get the IoControlCode value 145 | IoControlCode = PtrIoStackLocation->Parameters.DeviceIoControl.IoControlCode; 146 | 147 | // You may wish to allow only volume open operations. 148 | 149 | switch (IoControlCode) { 150 | #ifdef __THIS_IS_A_NETWORK_REDIR_ 151 | case IOCTL_REDIR_QUERY_PATH: 152 | // Only for network redirectors. 153 | BufferPointer = (void *)(PtrIoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer); 154 | // Invoke the handler for this IOCTL. 155 | RC = SFsdHandleQueryPath(BufferPointer); 156 | CompleteIrp = TRUE; 157 | try_return(RC); 158 | break; 159 | #endif // _THIS_IS_A_NETWORK_REDIR_ 160 | default: 161 | // Invoke the lower level driver in the chain. 162 | PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp); 163 | *PtrNextIoStackLocation = *PtrIoStackLocation; 164 | // Set a completion routine. 165 | IoSetCompletionRoutine(PtrIrp, SFsdDevIoctlCompletion, NULL, TRUE, TRUE, TRUE); 166 | // Send the request. 167 | RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); 168 | break; 169 | } 170 | 171 | try_exit: NOTHING; 172 | 173 | } finally { 174 | 175 | // Release the IRP context 176 | if (!(PtrIrpContext->IrpContextFlags & SFSD_IRP_CONTEXT_EXCEPTION)) { 177 | // Free up the Irp Context 178 | SFsdReleaseIrpContext(PtrIrpContext); 179 | 180 | if (CompleteIrp) { 181 | PtrIrp->IoStatus.Status = RC; 182 | PtrIrp->IoStatus.Information = 0; 183 | 184 | // complete the IRP 185 | IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 186 | } 187 | } 188 | } 189 | 190 | return(RC); 191 | } 192 | 193 | 194 | /************************************************************************* 195 | * 196 | * Function: SFsdDevIoctlCompletion() 197 | * 198 | * Description: 199 | * Completion routine. 200 | * 201 | * Expected Interrupt Level (for execution) : 202 | * 203 | * IRQL_PASSIVE_LEVEL 204 | * 205 | * Return Value: STATUS_SUCCESS 206 | * 207 | *************************************************************************/ 208 | NTSTATUS SFsdDevIoctlCompletion( 209 | PDEVICE_OBJECT PtrDeviceObject, 210 | PIRP PtrIrp, 211 | void *Context) 212 | { 213 | if (PtrIrp->PendingReturned) { 214 | IoMarkIrpPending(PtrIrp); 215 | } 216 | 217 | return(STATUS_SUCCESS); 218 | } 219 | 220 | 221 | /************************************************************************* 222 | * 223 | * Function: SFsdHandleQueryPath() 224 | * 225 | * Description: 226 | * Handle the MUP request. 227 | * 228 | * Expected Interrupt Level (for execution) : 229 | * 230 | * IRQL_PASSIVE_LEVEL 231 | * 232 | * Return Value: STATUS_SUCCESS 233 | * 234 | *************************************************************************/ 235 | NTSTATUS SFsdHandleQueryPath( 236 | void *BufferPointer) 237 | { 238 | NTSTATUS RC = STATUS_SUCCESS; 239 | PQUERY_PATH_REQUEST RequestBuffer = (PQUERY_PATH_REQUEST)BufferPointer; 240 | PQUERY_PATH_RESPONSE ReplyBuffer = (PQUERY_PATH_RESPONSE)BufferPointer; 241 | ULONG LengthOfNameToBeMatched = RequestBuffer->PathNameLength; 242 | ULONG LengthOfMatchedName = 0; 243 | WCHAR *NameToBeMatched = RequestBuffer->FilePathName; 244 | 245 | // So here we are. Simply check the name supplied. 246 | // You can use whatever algorithm you like to determine whether the 247 | // sent in name is acceptable. 248 | // The first character in the name is always a "\" 249 | // If you like the name sent in (probably, you will like a subset 250 | // of the name), set the matching length value in LengthOfMatchedName. 251 | 252 | // if (FoundMatch) { 253 | // ReplyBuffer->LengthAccepted = LengthOfMatchedName; 254 | // } else { 255 | // RC = STATUS_OBJECT_NAME_NOT_FOUND; 256 | // } 257 | 258 | return(RC); 259 | } 260 | 261 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/dircntrl.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: dircntrl.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains code to handle the "directory control" dispatch entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfsd.h" 17 | 18 | // define the file specific bug-check id 19 | #define SFSD_BUG_CHECK_ID SFSD_FILE_DIR_CONTROL 20 | 21 | 22 | 23 | /************************************************************************* 24 | * 25 | * Function: SFsdDirControl() 26 | * 27 | * Description: 28 | * The I/O Manager will invoke this routine to handle a directory control 29 | * request 30 | * 31 | * Expected Interrupt Level (for execution) : 32 | * 33 | * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 34 | * to be deferred to a worker thread context) 35 | * 36 | * Return Value: STATUS_SUCCESS/Error 37 | * 38 | *************************************************************************/ 39 | NTSTATUS SFsdDirControl( 40 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 41 | PIRP Irp) // I/O Request Packet 42 | { 43 | NTSTATUS RC = STATUS_SUCCESS; 44 | PtrSFsdIrpContext PtrIrpContext = NULL; 45 | BOOLEAN AreWeTopLevel = FALSE; 46 | 47 | FsRtlEnterFileSystem(); 48 | ASSERT(DeviceObject); 49 | ASSERT(Irp); 50 | 51 | // set the top level context 52 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 53 | 54 | try { 55 | 56 | // get an IRP context structure and issue the request 57 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 58 | ASSERT(PtrIrpContext); 59 | 60 | RC = SFsdCommonDirControl(PtrIrpContext, Irp); 61 | 62 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 63 | 64 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 65 | 66 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 67 | } 68 | 69 | if (AreWeTopLevel) { 70 | IoSetTopLevelIrp(NULL); 71 | } 72 | 73 | FsRtlExitFileSystem(); 74 | 75 | return(RC); 76 | } 77 | 78 | 79 | 80 | /************************************************************************* 81 | * 82 | * Function: SFsdCommonDirControl() 83 | * 84 | * Description: 85 | * The actual work is performed here. This routine may be invoked in one' 86 | * of the two possible contexts: 87 | * (a) in the context of a system worker thread 88 | * (b) in the context of the original caller 89 | * 90 | * Expected Interrupt Level (for execution) : 91 | * 92 | * IRQL_PASSIVE_LEVEL 93 | * 94 | * Return Value: STATUS_SUCCESS/Error 95 | * 96 | *************************************************************************/ 97 | NTSTATUS SFsdCommonDirControl( 98 | PtrSFsdIrpContext PtrIrpContext, 99 | PIRP PtrIrp) 100 | { 101 | NTSTATUS RC = STATUS_SUCCESS; 102 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 103 | PFILE_OBJECT PtrFileObject = NULL; 104 | PtrSFsdFCB PtrFCB = NULL; 105 | PtrSFsdCCB PtrCCB = NULL; 106 | PtrSFsdVCB PtrVCB = NULL; 107 | 108 | // First, get a pointer to the current I/O stack location 109 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 110 | ASSERT(PtrIoStackLocation); 111 | 112 | PtrFileObject = PtrIoStackLocation->FileObject; 113 | ASSERT(PtrFileObject); 114 | 115 | // Get the FCB and CCB pointers 116 | PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 117 | ASSERT(PtrCCB); 118 | PtrFCB = PtrCCB->PtrFCB; 119 | ASSERT(PtrFCB); 120 | 121 | // Get some of the parameters supplied to us 122 | switch (PtrIoStackLocation->MinorFunction) { 123 | case IRP_MN_QUERY_DIRECTORY: 124 | RC = SFsdQueryDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB); 125 | break; 126 | case IRP_MN_NOTIFY_CHANGE_DIRECTORY: 127 | RC = SFsdNotifyChangeDirectory(PtrIrpContext, PtrIrp, PtrIoStackLocation, PtrFileObject, PtrFCB, PtrCCB); 128 | break; 129 | default: 130 | // This should not happen. 131 | RC = STATUS_INVALID_DEVICE_REQUEST; 132 | PtrIrp->IoStatus.Status = RC; 133 | PtrIrp->IoStatus.Information = 0; 134 | 135 | // Free up the Irp Context 136 | SFsdReleaseIrpContext(PtrIrpContext); 137 | 138 | // complete the IRP 139 | IoCompleteRequest(PtrIrp, IO_NO_INCREMENT); 140 | break; 141 | } 142 | 143 | return(RC); 144 | } 145 | 146 | 147 | /************************************************************************* 148 | * 149 | * Function: SFsdQueryDirectory() 150 | * 151 | * Description: 152 | * Query directory request. 153 | * 154 | * Expected Interrupt Level (for execution) : 155 | * 156 | * IRQL_PASSIVE_LEVEL 157 | * 158 | * Return Value: STATUS_SUCCESS/Error 159 | * 160 | *************************************************************************/ 161 | NTSTATUS SFsdQueryDirectory( 162 | PtrSFsdIrpContext PtrIrpContext, 163 | PIRP PtrIrp, 164 | PIO_STACK_LOCATION PtrIoStackLocation, 165 | PFILE_OBJECT PtrFileObject, 166 | PtrSFsdFCB PtrFCB, 167 | PtrSFsdCCB PtrCCB) 168 | { 169 | NTSTATUS RC = STATUS_SUCCESS; 170 | BOOLEAN CompleteRequest = TRUE; 171 | BOOLEAN PostRequest = FALSE; 172 | PtrSFsdNTRequiredFCB PtrReqdFCB = NULL; 173 | BOOLEAN CanWait = FALSE; 174 | PtrSFsdVCB PtrVCB = NULL; 175 | BOOLEAN AcquiredFCB = FALSE; 176 | unsigned long BufferLength = 0; 177 | PSTRING PtrSearchPattern = NULL; 178 | FILE_INFORMATION_CLASS FileInformationClass; 179 | unsigned long FileIndex = 0; 180 | BOOLEAN RestartScan = FALSE; 181 | BOOLEAN ReturnSingleEntry = FALSE; 182 | BOOLEAN IndexSpecified = FALSE; 183 | unsigned char *Buffer = NULL; 184 | BOOLEAN FirstTimeQuery = FALSE; 185 | unsigned long StartingIndexForSearch = 0; 186 | unsigned int BytesReturned = 0; 187 | 188 | try { 189 | 190 | // Validate the sent-in FCB 191 | if ((PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & SFSD_FCB_DIRECTORY)) { 192 | // We will only allow notify requests on directories. 193 | RC = STATUS_INVALID_PARAMETER; 194 | } 195 | 196 | PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 197 | CanWait = ((PtrIrpContext->IrpContextFlags & SFSD_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 198 | PtrVCB = PtrFCB->PtrVCB; 199 | 200 | // If the caller does not wish to block, it would be easier to 201 | // simply post the request now. 202 | if (!CanWait) { 203 | PostRequest = TRUE; 204 | try_return(RC = STATUS_PENDING); 205 | } 206 | 207 | // Obtain the callers parameters 208 | BufferLength = PtrIoStackLocation->Parameters.QueryDirectory.Length; 209 | PtrSearchPattern = PtrIoStackLocation->Parameters.QueryDirectory.FileName; 210 | FileInformationClass = PtrIoStackLocation->Parameters.QueryDirectory.FileInformationClass; 211 | FileIndex = PtrIoStackLocation->Parameters.QueryDirectory.FileIndex; 212 | 213 | // Some additional arguments that affect the FSD behavior 214 | RestartScan = (PtrIoStackLocation->Flags & SL_RESTART_SCAN); 215 | ReturnSingleEntry = (PtrIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY); 216 | IndexSpecified = (PtrIoStackLocation->Flags & SL_INDEX_SPECIFIED); 217 | 218 | // I will acquire exclusive access to the FCB. 219 | // This is not mandatory, however, and your FSD could choose to acquire 220 | // the resource shared for increased parallelism. 221 | ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); 222 | AcquiredFCB = TRUE; 223 | 224 | // We must determine the buffer pointer to be used. Since this 225 | // routine could either be invoked directly in the context of the 226 | // calling thread, or in the context of a worker thread, here is 227 | // a general way of determining what we should use. 228 | if (PtrIrp->MdlAddress) { 229 | Buffer = MmGetSystemAddressForMdl(PtrIrp->MdlAddress); 230 | } else { 231 | Buffer = PtrIrp->UserBuffer; 232 | } 233 | 234 | // The method of determining where to look from and what to look for is 235 | // unfortunately extremely confusing. However, here is a methodology you 236 | // you can broadly adopt: 237 | // (a) You have to maintain a search buffer per CCB structure. 238 | // (b) This search buffer is initialized the very first time 239 | // a query directory operation is performed using the file object. 240 | // (For the sample FSD, the search buffer is stored in the 241 | // DirectorySearchPattern field) 242 | // However, the caller still has the option of "overriding" this stored 243 | // search pattern by supplying a new one in a query directory operation. 244 | // 245 | if (PtrSearchPattern == NULL) { 246 | // User has supplied a search pattern 247 | // Now validate that the search pattern is legitimate; this is 248 | // dependent upon the character set acceptable to your FSD. 249 | 250 | // Once you have validated the search pattern, you must 251 | // check whether you need to store this search pattern in 252 | // the CCB. 253 | if (PtrCCB->DirectorySearchPattern == NULL) { 254 | // This must be the very first query request. 255 | FirstTimeQuery = TRUE; 256 | 257 | // Now, allocate enough memory to contain the caller 258 | // supplied search pattern and fill in the DirectorySearchPattern 259 | // field in the CCB 260 | // PtrCCB->DirectorySearchPattern = ExAllocatePool(...); 261 | } else { 262 | // We should ignore the search pattern in the CCB and instead, 263 | // use the user-supplied pattern for this particular query 264 | // directory request. 265 | } 266 | 267 | } else if (PtrCCB->DirectorySearchPattern == NULL) { 268 | // This MUST be the first directory query operation (else the 269 | // DirectorySearchPattern field would never be NULL. Also, the caller 270 | // has neglected to provide a pattern so we MUST invent one. 271 | // Use "*" (following NT conventions) as your search pattern 272 | // and store it in the PtrCCB->DirectorySearchPattern field. 273 | 274 | PtrCCB->DirectorySearchPattern = ExAllocatePool(PagedPool, sizeof(L"*")); 275 | ASSERT(PtrCCB->DirectorySearchPattern); 276 | 277 | FirstTimeQuery = TRUE; 278 | } else { 279 | // The caller has not supplied any search pattern that we are 280 | // forced to use. However, the caller had previously supplied 281 | // a pattern (or we must have invented one) and we will use it. 282 | // This is definitely not the first query operation on this 283 | // directory using this particular file object. 284 | 285 | PtrSearchPattern = PtrCCB->DirectorySearchPattern; 286 | } 287 | 288 | // There is one other piece of information that your FSD must store 289 | // in the CCB structure for query directory support. This is the index 290 | // value (i.e. the offset in your on-disk directory structure) from 291 | // which you should start searching. 292 | // However, the flags supplied with the IRP can make us override this 293 | // as well. 294 | 295 | if (FileIndex) { 296 | // Caller has told us wherefrom to begin. 297 | // You may need to round this to an appropriate directory entry 298 | // entry alignment value. 299 | StartingIndexForSearch = FileIndex; 300 | } else if (RestartScan) { 301 | StartingIndexForSearch = 0; 302 | } else { 303 | // Get the starting offset from the CCB. 304 | // Remember to update this value on your way out from this function. 305 | // But, do not update the CCB CurrentByteOffset field if you reach 306 | // the end of the directory (or get an error reading the directory) 307 | // while performing the search. 308 | StartingIndexForSearch = PtrCCB->CurrentByteOffset.LowPart; 309 | } 310 | 311 | // Now, your FSD must determine the best way to read the directory 312 | // contents from disk and search through them. 313 | 314 | // If ReturnSingleEntry is TRUE, please return information on only 315 | // one matching entry. 316 | 317 | // One final note though: 318 | // If you do not find a directory entry OR while searching you reach the 319 | // end of the directory, then the return code should be set as follows: 320 | 321 | // (a) If any files have been returned (i.e. ReturnSingleEntry was FALSE 322 | // and you did find at least one match), then return STATUS_SUCCESS 323 | // (b) If no entry is being returned then: 324 | // (i) If this is the first query i.e. FirstTimeQuery is TRUE 325 | // then return STATUS_NO_SUCH_FILE 326 | // (ii) Otherwise, return STATUS_NO_MORE_FILES 327 | 328 | try_exit: NOTHING; 329 | 330 | // Remember to update the CurrentByteOffset field in the CCB if required. 331 | 332 | // You should also set a flag in the FCB indicating that the directory 333 | // contents were accessed. 334 | 335 | } finally { 336 | if (PostRequest) { 337 | if (AcquiredFCB) { 338 | SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 339 | } 340 | 341 | // Map the users buffer and then post the request. 342 | RC = SFsdLockCallersBuffer(PtrIrp, TRUE, BufferLength); 343 | ASSERT(NT_SUCCESS(RC)); 344 | 345 | RC = SFsdPostRequest(PtrIrpContext, PtrIrp); 346 | 347 | } else if (!(PtrIrpContext->IrpContextFlags & 348 | SFSD_IRP_CONTEXT_EXCEPTION)) { 349 | if (AcquiredFCB) { 350 | SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 351 | } 352 | 353 | // Complete the request. 354 | PtrIrp->IoStatus.Status = RC; 355 | PtrIrp->IoStatus.Information = BytesReturned; 356 | 357 | // Free up the Irp Context 358 | SFsdReleaseIrpContext(PtrIrpContext); 359 | 360 | // complete the IRP 361 | IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 362 | } 363 | } 364 | 365 | return(RC); 366 | } 367 | 368 | 369 | 370 | /************************************************************************* 371 | * 372 | * Function: SFsdNotifyChangeDirectory() 373 | * 374 | * Description: 375 | * Handle the notify request. 376 | * 377 | * Expected Interrupt Level (for execution) : 378 | * 379 | * IRQL_PASSIVE_LEVEL 380 | * 381 | * Return Value: STATUS_SUCCESS/Error 382 | * 383 | *************************************************************************/ 384 | NTSTATUS SFsdNotifyChangeDirectory( 385 | PtrSFsdIrpContext PtrIrpContext, 386 | PIRP PtrIrp, 387 | PIO_STACK_LOCATION PtrIoStackLocation, 388 | PFILE_OBJECT PtrFileObject, 389 | PtrSFsdFCB PtrFCB, 390 | PtrSFsdCCB PtrCCB) 391 | { 392 | NTSTATUS RC = STATUS_SUCCESS; 393 | BOOLEAN CompleteRequest = FALSE; 394 | BOOLEAN PostRequest = FALSE; 395 | PtrSFsdNTRequiredFCB PtrReqdFCB = NULL; 396 | BOOLEAN CanWait = FALSE; 397 | ULONG CompletionFilter = 0; 398 | BOOLEAN WatchTree = FALSE; 399 | PtrSFsdVCB PtrVCB = NULL; 400 | BOOLEAN AcquiredFCB = FALSE; 401 | 402 | try { 403 | 404 | // Validate the sent-in FCB 405 | if ((PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) || !(PtrFCB->FCBFlags & SFSD_FCB_DIRECTORY)) { 406 | // We will only allow notify requests on directories. 407 | RC = STATUS_INVALID_PARAMETER; 408 | CompleteRequest = TRUE; 409 | } 410 | 411 | PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 412 | CanWait = ((PtrIrpContext->IrpContextFlags & SFSD_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 413 | PtrVCB = PtrFCB->PtrVCB; 414 | 415 | // Acquire the FCB resource shared 416 | if (!ExAcquireResourceSharedLite(&(PtrReqdFCB->MainResource), CanWait)) { 417 | PostRequest = TRUE; 418 | try_return(RC = STATUS_PENDING); 419 | } 420 | AcquiredFCB = TRUE; 421 | 422 | // Obtain some parameters sent by the caller 423 | CompletionFilter = PtrIoStackLocation->Parameters.NotifyDirectory.CompletionFilter; 424 | WatchTree = (PtrIoStackLocation->Flags & SL_WATCH_TREE ? TRUE : FALSE); 425 | 426 | // If you wish to capture the subject context, you can do so as 427 | // follows: 428 | // { 429 | // PSECURITY_SUBJECT_CONTEXT SubjectContext; 430 | // SubjectContext = ExAllocatePool(PagedPool, 431 | // sizeof(SECURITY_SUBJECT_CONTEXT)); 432 | // SeCaptureSubjectContext(SubjectContext); 433 | // } 434 | 435 | FsRtlNotifyFullChangeDirectory(&(PtrVCB->NotifyIRPMutex), &(PtrVCB->NextNotifyIRP), (void *)PtrCCB, 436 | (PSTRING)(PtrFCB->FCBName->ObjectName.Buffer), WatchTree, FALSE, CompletionFilter, PtrIrp, 437 | NULL, // SFsdTraverseAccessCheck(...) ? 438 | NULL); // SubjectContext ? 439 | 440 | RC = STATUS_PENDING; 441 | 442 | try_exit: NOTHING; 443 | 444 | } finally { 445 | 446 | if (PostRequest) { 447 | // Perform appropriate post related processing here 448 | if (AcquiredFCB) { 449 | SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 450 | AcquiredFCB = FALSE; 451 | } 452 | RC = SFsdPostRequest(PtrIrpContext, PtrIrp); 453 | } else if (CompleteRequest) { 454 | PtrIrp->IoStatus.Status = RC; 455 | PtrIrp->IoStatus.Information = 0; 456 | 457 | // Free up the Irp Context 458 | SFsdReleaseIrpContext(PtrIrpContext); 459 | 460 | // complete the IRP 461 | IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 462 | } else { 463 | // Simply free up the IrpContext since the IRP has been queued 464 | SFsdReleaseIrpContext(PtrIrpContext); 465 | } 466 | 467 | // Release the FCB resources if acquired. 468 | if (AcquiredFCB) { 469 | SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 470 | AcquiredFCB = FALSE; 471 | } 472 | 473 | } 474 | 475 | return(RC); 476 | } 477 | 478 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/flush.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: flush.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains code to handle the "Flush Buffers" dispatch entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfsd.h" 17 | 18 | // define the file specific bug-check id 19 | #define SFSD_BUG_CHECK_ID SFSD_FILE_FLUSH 20 | 21 | 22 | 23 | /************************************************************************* 24 | * 25 | * Function: SFsdFlush() 26 | * 27 | * Description: 28 | * The I/O Manager will invoke this routine to handle a flush buffers 29 | * request 30 | * 31 | * Expected Interrupt Level (for execution) : 32 | * 33 | * IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 34 | * to be deferred to a worker thread context) 35 | * 36 | * Return Value: STATUS_SUCCESS/Error 37 | * 38 | *************************************************************************/ 39 | NTSTATUS SFsdFlush( 40 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 41 | PIRP Irp) // I/O Request Packet 42 | { 43 | NTSTATUS RC = STATUS_SUCCESS; 44 | PtrSFsdIrpContext PtrIrpContext = NULL; 45 | BOOLEAN AreWeTopLevel = FALSE; 46 | 47 | FsRtlEnterFileSystem(); 48 | ASSERT(DeviceObject); 49 | ASSERT(Irp); 50 | 51 | // set the top level context 52 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 53 | 54 | try { 55 | 56 | // get an IRP context structure and issue the request 57 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 58 | ASSERT(PtrIrpContext); 59 | 60 | RC = SFsdCommonFlush(PtrIrpContext, Irp); 61 | 62 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 63 | 64 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 65 | 66 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 67 | } 68 | 69 | if (AreWeTopLevel) { 70 | IoSetTopLevelIrp(NULL); 71 | } 72 | 73 | FsRtlExitFileSystem(); 74 | 75 | return(RC); 76 | } 77 | 78 | 79 | 80 | /************************************************************************* 81 | * 82 | * Function: SFsdCommonFlush() 83 | * 84 | * Description: 85 | * The actual work is performed here. This routine may be invoked in one' 86 | * of the two possible contexts: 87 | * (a) in the context of a system worker thread 88 | * (b) in the context of the original caller 89 | * 90 | * Expected Interrupt Level (for execution) : 91 | * 92 | * IRQL_PASSIVE_LEVEL 93 | * 94 | * Return Value: STATUS_SUCCESS/Error 95 | * 96 | *************************************************************************/ 97 | NTSTATUS SFsdCommonFlush( 98 | PtrSFsdIrpContext PtrIrpContext, 99 | PIRP PtrIrp) 100 | { 101 | NTSTATUS RC = STATUS_SUCCESS; 102 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 103 | PFILE_OBJECT PtrFileObject = NULL; 104 | PtrSFsdFCB PtrFCB = NULL; 105 | PtrSFsdCCB PtrCCB = NULL; 106 | PtrSFsdVCB PtrVCB = NULL; 107 | PtrSFsdNTRequiredFCB PtrReqdFCB = NULL; 108 | BOOLEAN AcquiredFCB = FALSE; 109 | BOOLEAN PostRequest = FALSE; 110 | BOOLEAN CanWait = TRUE; 111 | 112 | try { 113 | // First, get a pointer to the current I/O stack location 114 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 115 | ASSERT(PtrIoStackLocation); 116 | 117 | PtrFileObject = PtrIoStackLocation->FileObject; 118 | ASSERT(PtrFileObject); 119 | 120 | // Get the FCB and CCB pointers 121 | PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 122 | ASSERT(PtrCCB); 123 | PtrFCB = PtrCCB->PtrFCB; 124 | ASSERT(PtrFCB); 125 | PtrReqdFCB = &(PtrFCB->NTRequiredFCB); 126 | 127 | // Get some of the parameters supplied to us 128 | CanWait = ((PtrIrpContext->IrpContextFlags & SFSD_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE); 129 | 130 | // If we cannot wait, post the request immediately since a flush is inherently blocking/synchronous. 131 | if (!CanWait) { 132 | PostRequest = TRUE; 133 | try_return(RC); 134 | } 135 | 136 | // Check the type of object passed-in. That will determine the course of 137 | // action we take. 138 | if ((PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) || (PtrFCB->FCBFlags & SFSD_FCB_ROOT_DIRECTORY)) { 139 | 140 | if (PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) { 141 | PtrVCB = (PtrSFsdVCB)(PtrFCB); 142 | } else { 143 | PtrVCB = PtrFCB->PtrVCB; 144 | } 145 | 146 | // The caller wishes to flush all files for the mounted 147 | // logical volume. The flush volume routine below should simply 148 | // walk through all of the open file streams, acquire the 149 | // FCB resource, and request the flush operation from the Cache 150 | // Manager. Basically, the sequence of operations listed below 151 | // for a single file should be executed on all open files. 152 | 153 | SFsdFlushLogicalVolume(PtrIrpContext, PtrIrp, PtrVCB); 154 | 155 | try_return(RC); 156 | } 157 | 158 | if (!(PtrFCB->FCBFlags & SFSD_FCB_DIRECTORY)) { 159 | // This is a regular file. 160 | ExAcquireResourceExclusiveLite(&(PtrReqdFCB->MainResource), TRUE); 161 | AcquiredFCB = TRUE; 162 | 163 | // Request the Cache Manager to perform a flush operation. 164 | // Further, instruct the Cache Manager that we wish to flush the 165 | // entire file stream. 166 | SFsdFlushAFile(PtrReqdFCB, &(PtrIrp->IoStatus)); 167 | RC = PtrIrp->IoStatus.Status; 168 | // All done. You may want to also flush the directory entry for the 169 | // file stream at this time. 170 | 171 | // Some log-based FSD implementations may wish to flush their 172 | // log files at this time. Finally, you should update the time-stamp 173 | // values for the file stream appropriately. This would involve 174 | // obtaining the current time and modifying the appropriate directory 175 | // entry fields. 176 | } 177 | 178 | try_exit: 179 | 180 | if (AcquiredFCB) { 181 | SFsdReleaseResource(&(PtrReqdFCB->MainResource)); 182 | AcquiredFCB = FALSE; 183 | } 184 | 185 | if (!PostRequest) { 186 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 187 | NTSTATUS RC1 = STATUS_SUCCESS; 188 | 189 | // Send the request down at this point. 190 | // To do this, you must set the next IRP stack location, and 191 | // maybe set a completion routine. 192 | // Be careful about marking the IRP pending if the lower level 193 | // driver returned pending and you do have a completion routine! 194 | PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp); 195 | *PtrNextIoStackLocation = *PtrIoStackLocation; 196 | 197 | // Set the completion routine to "eat-up" any 198 | // STATUS_INVALID_DEVICE_REQUEST error code returned by the lower 199 | // level driver. 200 | IoSetCompletionRoutine(PtrIrp, SFsdFlushCompletion, NULL, TRUE, TRUE, TRUE); 201 | 202 | RC1 = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); 203 | 204 | RC = ((RC1 == STATUS_INVALID_DEVICE_REQUEST) ? RC : RC1); 205 | } 206 | 207 | } finally { 208 | if (PostRequest) { 209 | // Nothing to lock now. 210 | RC = SFsdPostRequest(PtrIrpContext, PtrIrp); 211 | } else { 212 | // Release the IRP context at this time. 213 | SFsdReleaseIrpContext(PtrIrpContext); 214 | } 215 | } 216 | 217 | return(RC); 218 | } 219 | 220 | 221 | /************************************************************************* 222 | * 223 | * Function: SFsdFlushAFile() 224 | * 225 | * Description: 226 | * Tell the Cache Manager to perform a flush. 227 | * 228 | * Expected Interrupt Level (for execution) : 229 | * 230 | * IRQL_PASSIVE_LEVEL 231 | * 232 | * Return Value: None 233 | * 234 | *************************************************************************/ 235 | void SFsdFlushAFile( 236 | PtrSFsdNTRequiredFCB PtrReqdFCB, 237 | PIO_STATUS_BLOCK PtrIoStatus) 238 | { 239 | CcFlushCache(&(PtrReqdFCB->SectionObject), NULL, 0, PtrIoStatus); 240 | return; 241 | } 242 | 243 | 244 | /************************************************************************* 245 | * 246 | * Function: SFsdFlushLogicalVolume() 247 | * 248 | * Description: 249 | * Flush everything beginning at root directory. 250 | * 251 | * Expected Interrupt Level (for execution) : 252 | * 253 | * IRQL_PASSIVE_LEVEL 254 | * 255 | * Return Value: None 256 | * 257 | *************************************************************************/ 258 | void SFsdFlushLogicalVolume( 259 | PtrSFsdIrpContext PtrIrpContext, 260 | PIRP PtrIrp, 261 | PtrSFsdVCB PtrVCB) 262 | { 263 | BOOLEAN AcquiredVCB = FALSE; 264 | PtrSFsdFCB PtrFCB = NULL; 265 | PLIST_ENTRY PtrNextFCB = NULL; 266 | 267 | try { 268 | ExAcquireResourceExclusiveLite(&(PtrVCB->VCBResource), TRUE); 269 | AcquiredVCB = TRUE; 270 | 271 | // Go through the list of FCB's. You would probably 272 | // flush all of the files. Then, you could flush the 273 | // directories that you may have have pinned into memory. 274 | 275 | // NOTE: This function may also be invoked internally as part of 276 | // processing a shutdown request. 277 | 278 | } finally { 279 | 280 | if (AcquiredVCB) { 281 | SFsdReleaseResource(&(PtrVCB->VCBResource)); 282 | } 283 | } 284 | 285 | return; 286 | } 287 | 288 | 289 | /************************************************************************* 290 | * 291 | * Function: SFsdFlushCompletion() 292 | * 293 | * Description: 294 | * Eat up any bad errors. 295 | * 296 | * Expected Interrupt Level (for execution) : 297 | * 298 | * IRQL_PASSIVE_LEVEL 299 | * 300 | * Return Value: None 301 | * 302 | *************************************************************************/ 303 | NTSTATUS SFsdFlushCompletion( 304 | PDEVICE_OBJECT PtrDeviceObject, 305 | PIRP PtrIrp, 306 | PVOID Context) 307 | { 308 | NTSTATUS RC = STATUS_SUCCESS; 309 | 310 | if (PtrIrp->PendingReturned) { 311 | IoMarkIrpPending(PtrIrp); 312 | } 313 | 314 | if (PtrIrp->IoStatus.Status == STATUS_INVALID_DEVICE_REQUEST) { 315 | // cannot do much here, can we? 316 | PtrIrp->IoStatus.Status = STATUS_SUCCESS; 317 | } 318 | 319 | return(STATUS_SUCCESS); 320 | } 321 | 322 | 323 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/_objects.mac: -------------------------------------------------------------------------------- 1 | ALPHA_OBJECTS= \ 2 | $(_OBJ_DIR)\alpha\sfsdinit.obj \ 3 | $(_OBJ_DIR)\alpha\create.obj \ 4 | $(_OBJ_DIR)\alpha\misc.obj \ 5 | $(_OBJ_DIR)\alpha\cleanup.obj \ 6 | $(_OBJ_DIR)\alpha\close.obj \ 7 | $(_OBJ_DIR)\alpha\read.obj \ 8 | $(_OBJ_DIR)\alpha\write.obj \ 9 | $(_OBJ_DIR)\alpha\fileinfo.obj \ 10 | $(_OBJ_DIR)\alpha\flush.obj \ 11 | $(_OBJ_DIR)\alpha\dircntrl.obj \ 12 | $(_OBJ_DIR)\alpha\devcntrl.obj \ 13 | $(_OBJ_DIR)\alpha\shutdown.obj \ 14 | $(_OBJ_DIR)\alpha\fastio.obj 15 | 16 | PASS0_ALPHA_OBJECTS= 17 | 18 | MIPS_OBJECTS= \ 19 | $(_OBJ_DIR)\mips\sfsdinit.obj \ 20 | $(_OBJ_DIR)\mips\create.obj \ 21 | $(_OBJ_DIR)\mips\misc.obj \ 22 | $(_OBJ_DIR)\mips\cleanup.obj \ 23 | $(_OBJ_DIR)\mips\close.obj \ 24 | $(_OBJ_DIR)\mips\read.obj \ 25 | $(_OBJ_DIR)\mips\write.obj \ 26 | $(_OBJ_DIR)\mips\fileinfo.obj \ 27 | $(_OBJ_DIR)\mips\flush.obj \ 28 | $(_OBJ_DIR)\mips\dircntrl.obj \ 29 | $(_OBJ_DIR)\mips\devcntrl.obj \ 30 | $(_OBJ_DIR)\mips\shutdown.obj \ 31 | $(_OBJ_DIR)\mips\fastio.obj 32 | 33 | PASS0_MIPS_OBJECTS= 34 | 35 | 386_OBJECTS= \ 36 | $(_OBJ_DIR)\i386\sfsdinit.obj \ 37 | $(_OBJ_DIR)\i386\create.obj \ 38 | $(_OBJ_DIR)\i386\misc.obj \ 39 | $(_OBJ_DIR)\i386\cleanup.obj \ 40 | $(_OBJ_DIR)\i386\close.obj \ 41 | $(_OBJ_DIR)\i386\read.obj \ 42 | $(_OBJ_DIR)\i386\write.obj \ 43 | $(_OBJ_DIR)\i386\fileinfo.obj \ 44 | $(_OBJ_DIR)\i386\flush.obj \ 45 | $(_OBJ_DIR)\i386\dircntrl.obj \ 46 | $(_OBJ_DIR)\i386\devcntrl.obj \ 47 | $(_OBJ_DIR)\i386\shutdown.obj \ 48 | $(_OBJ_DIR)\i386\fastio.obj 49 | 50 | PASS0_386_OBJECTS= 51 | 52 | PPC_OBJECTS= \ 53 | $(_OBJ_DIR)\ppc\sfsdinit.obj \ 54 | $(_OBJ_DIR)\ppc\create.obj \ 55 | $(_OBJ_DIR)\ppc\misc.obj \ 56 | $(_OBJ_DIR)\ppc\cleanup.obj \ 57 | $(_OBJ_DIR)\ppc\close.obj \ 58 | $(_OBJ_DIR)\ppc\read.obj \ 59 | $(_OBJ_DIR)\ppc\write.obj \ 60 | $(_OBJ_DIR)\ppc\fileinfo.obj \ 61 | $(_OBJ_DIR)\ppc\flush.obj \ 62 | $(_OBJ_DIR)\ppc\dircntrl.obj \ 63 | $(_OBJ_DIR)\ppc\devcntrl.obj \ 64 | $(_OBJ_DIR)\ppc\shutdown.obj \ 65 | $(_OBJ_DIR)\ppc\fastio.obj 66 | 67 | PASS0_PPC_OBJECTS= 68 | 69 | -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/checked/sfsd.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/checked/sfsd.sys -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/cleanup.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/cleanup.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/close.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/close.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/create.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/create.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/devcntrl.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/devcntrl.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/dircntrl.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/dircntrl.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/fastio.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/fastio.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/fileinfo.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/fileinfo.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/flush.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/flush.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/free/sfsd.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/free/sfsd.sys -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/misc.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/misc.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/read.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/read.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/sfsdinit.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/sfsdinit.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/shutdown.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/shutdown.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/obj/i386/write.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filesys/src/obj/i386/write.obj -------------------------------------------------------------------------------- /NTFsrc/filesys/src/sfsdinit.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfsdinit.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * This file contains the initialization code for the kernel mode 9 | * Sample FSD module. The DriverEntry() routine is called by the I/O 10 | * sub-system to initialize the FSD. 11 | * 12 | * Author: R. Nagar 13 | * 14 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 15 | * 16 | *************************************************************************/ 17 | 18 | #include "sfsd.h" 19 | 20 | // define the file specific bug-check id 21 | #define SFSD_BUG_CHECK_ID SFSD_FILE_INIT 22 | 23 | #define SFSD_FS_NAME L"\\SampleFSD" 24 | 25 | // global variables are declared here 26 | SFsdData SFsdGlobalData; 27 | 28 | 29 | /************************************************************************* 30 | * 31 | * Function: DriverEntry() 32 | * 33 | * Description: 34 | * This routine is the standard entry point for all kernel mode drivers. 35 | * The routine is invoked at IRQL PASSIVE_LEVEL in the context of a 36 | * system worker thread. 37 | * All FSD specific data structures etc. are initialized here. 38 | * 39 | * Expected Interrupt Level (for execution) : 40 | * 41 | * IRQL_PASSIVE_LEVEL 42 | * 43 | * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded). 44 | * 45 | *************************************************************************/ 46 | NTSTATUS DriverEntry( 47 | PDRIVER_OBJECT DriverObject, // created by the I/O sub-system 48 | PUNICODE_STRING RegistryPath) // path to the registry key 49 | { 50 | NTSTATUS RC = STATUS_SUCCESS; 51 | UNICODE_STRING DriverDeviceName; 52 | BOOLEAN RegisteredShutdown = FALSE; 53 | 54 | SFsdBreakPoint(); 55 | 56 | try { 57 | try { 58 | // initialize the global data structure 59 | RtlZeroMemory(&SFsdGlobalData, sizeof(SFsdGlobalData)); 60 | 61 | // initialize some required fields 62 | SFsdGlobalData.NodeIdentifier.NodeType = SFSD_NODE_TYPE_GLOBAL_DATA; 63 | SFsdGlobalData.NodeIdentifier.NodeSize = sizeof(SFsdGlobalData); 64 | 65 | // initialize the global data resource and remember the fact that 66 | // the resource has been initialized 67 | RC = ExInitializeResourceLite(&(SFsdGlobalData.GlobalDataResource)); 68 | ASSERT(NT_SUCCESS(RC)); 69 | SFsdSetFlag(SFsdGlobalData.SFsdFlags, SFSD_DATA_FLAGS_RESOURCE_INITIALIZED); 70 | 71 | // keep a ptr to the driver object sent to us by the I/O Mgr 72 | SFsdGlobalData.SFsdDriverObject = DriverObject; 73 | 74 | // initialize the mounted logical volume list head 75 | InitializeListHead(&(SFsdGlobalData.NextVCB)); 76 | 77 | // before we proceed with any more initialization, read in 78 | // user supplied configurable values ... 79 | // if (!NT_SUCCESS(RC = SFsdObtainRegistryValues(RegistryPath))) { 80 | // in your commercial driver implementation, it would be 81 | // advisable for your driver to print an appropriate error 82 | // message to the system error log before leaving 83 | // try_return(RC); 84 | // } 85 | 86 | // we should have the registry data (if any), allocate zone memory ... 87 | // This is an example of when FSD implementations try to pre-allocate 88 | // some fixed amount of memory to avoid internal fragmentation and/or waiting 89 | // later during run-time ... 90 | if (!NT_SUCCESS(RC = SFsdInitializeZones())) { 91 | // we failed, print a message and leave ... 92 | try_return(RC); 93 | } 94 | 95 | // initialize the IRP major function table, and the fast I/O table 96 | SFsdInitializeFunctionPointers(DriverObject); 97 | 98 | // create a device object representing the driver itself 99 | // so that requests can be targeted to the driver ... 100 | // e.g. for a disk-based FSD, "mount" requests will be sent to 101 | // this device object by the I/O Manager.\ 102 | // For a redirector/server, you may have applications 103 | // send "special" IOCTL's using this device object ... 104 | RtlInitUnicodeString(&DriverDeviceName, SFSD_FS_NAME); 105 | if (!NT_SUCCESS(RC = IoCreateDevice( 106 | DriverObject, // our driver object 107 | 0, // don't need an extension for this object 108 | &DriverDeviceName,// name - can be used to "open" the driver 109 | // see the book for alternate choices 110 | FILE_DEVICE_DISK_FILE_SYSTEM, 111 | 0, // no special characteristics 112 | // do not want this as an exclusive device, though you might 113 | FALSE, 114 | &(SFsdGlobalData.SFsdDeviceObject)))) { 115 | // failed to create a device object, leave ... 116 | try_return(RC); 117 | } 118 | 119 | #ifdef _THIS_IS_A_NETWORK_REDIR_OR_SERVER_ 120 | 121 | // since network redirectors/servers do not register themselves as 122 | // "file systems", the I/O Manager does not ordinarily request the 123 | // FSD to flush logical volumes at shutdown. To get some notification 124 | // at shutdown, use the IoRegisterShutdownNotification() instead ... 125 | if (!NT_SUCCESS(RC = IoRegisterShutdownNotification(SFsdGlobalData.SFsdDeviceObject))) { 126 | // failed to register shutdown notification ... 127 | try_return(RC); 128 | } 129 | RegisteredShutdown = TRUE; 130 | 131 | // Register the network FSD with the MUP component. 132 | if (!NT_SUCCESS(RC = FsRtlRegisterUncProvider(&(SFsdGlobalData.MupHandle), &DriverDeviceName, FALSE))) { 133 | try_return(RC); 134 | } 135 | 136 | #else // This is a disk based FSD 137 | 138 | // register the driver with the I/O Manager, pretend as if this is 139 | // a physical disk based FSD (or in order words, this FSD manages 140 | // logical volumes residing on physical disk drives) 141 | IoRegisterFileSystem(SFsdGlobalData.SFsdDeviceObject); 142 | 143 | #endif // _THIS_IS_A_NETWORK_REDIR_OR_SERVER_ 144 | 145 | } except (EXCEPTION_EXECUTE_HANDLER) { 146 | // we encountered an exception somewhere, eat it up 147 | RC = GetExceptionCode(); 148 | } 149 | 150 | try_exit: NOTHING; 151 | } finally { 152 | // start unwinding if we were unsuccessful 153 | if (!NT_SUCCESS(RC)) { 154 | #ifdef _THIS_IS_A_NETWORK_REDIR_OR_SERVER_ 155 | if (RegisteredShutdown) { 156 | IoUnregisterShutdownNotification(SFsdGlobalData.SFsdDeviceObject); 157 | } 158 | #endif // _THIS_IS_A_NETWORK_REDIR_OR_SERVER_ 159 | 160 | // Now, delete any device objects, etc. we may have created 161 | if (SFsdGlobalData.SFsdDeviceObject) { 162 | IoDeleteDevice(SFsdGlobalData.SFsdDeviceObject); 163 | SFsdGlobalData.SFsdDeviceObject = NULL; 164 | } 165 | 166 | // free up any memory we might have reserved for zones/lookaside 167 | // lists 168 | if (SFsdGlobalData.SFsdFlags & SFSD_DATA_FLAGS_ZONES_INITIALIZED) { 169 | SFsdDestroyZones(); 170 | } 171 | 172 | // delete the resource we may have initialized 173 | if (SFsdGlobalData.SFsdFlags & SFSD_DATA_FLAGS_RESOURCE_INITIALIZED) { 174 | // un-initialize this resource 175 | ExDeleteResourceLite(&(SFsdGlobalData.GlobalDataResource)); 176 | SFsdClearFlag(SFsdGlobalData.SFsdFlags, SFSD_DATA_FLAGS_RESOURCE_INITIALIZED); 177 | } 178 | } 179 | } 180 | 181 | return(RC); 182 | } 183 | 184 | 185 | 186 | /************************************************************************* 187 | * 188 | * Function: SFsdInitializeFunctionPointers() 189 | * 190 | * Description: 191 | * Initialize the IRP... function pointer array in the driver object 192 | * structure. Also initialize the fast-io function ptr array ... 193 | * 194 | * Expected Interrupt Level (for execution) : 195 | * 196 | * IRQL_PASSIVE_LEVEL 197 | * 198 | * Return Value: None 199 | * 200 | *************************************************************************/ 201 | void SFsdInitializeFunctionPointers( 202 | PDRIVER_OBJECT DriverObject) // created by the I/O sub-system 203 | { 204 | PFAST_IO_DISPATCH PtrFastIoDispatch = NULL; 205 | 206 | // initialize the function pointers for the IRP major 207 | // functions that this FSD is prepared to handle ... 208 | // NT Version 4.0 has 28 possible functions that a 209 | // kernel mode driver can handle. 210 | // NT Version 3.51 and before has only 22 such functions, 211 | // of which 18 are typically interesting to most FSD's. 212 | 213 | // The only interesting new functions that a FSD might 214 | // want to respond to beginning with Version 4.0 are the 215 | // IRP_MJ_QUERY_QUOTA and the IRP_MJ_SET_QUOTA requests. 216 | 217 | // The code below does not handle quota manipulation, neither 218 | // does the NT Version 4.0 operating system (or I/O Manager). 219 | // However, you should be on the lookout for any such new 220 | // functionality that your FSD might have to implement in 221 | // the near future. 222 | 223 | DriverObject->MajorFunction[IRP_MJ_CREATE] = SFsdCreate; 224 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = SFsdClose; 225 | DriverObject->MajorFunction[IRP_MJ_READ] = SFsdRead; 226 | DriverObject->MajorFunction[IRP_MJ_WRITE] = SFsdWrite; 227 | 228 | DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SFsdFileInfo; 229 | DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = SFsdFileInfo; 230 | 231 | DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = SFsdFlush; 232 | // To implement support for querying and modifying volume attributes 233 | // (volume information query/set operations), enable initialization 234 | // of the following two function pointers and then implement the supporting 235 | // functions. Use Chapter 11 in the text to assist you in your efforts. 236 | // DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = SFsdVolInfo; 237 | // DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = SFsdVolInfo; 238 | DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = SFsdDirControl; 239 | // To implement support for file system IOCTL calls, enable initialization 240 | // of the following function pointer and implement appropriate support. Use 241 | // Chapter 11 in the text to assist you in your efforts. 242 | // DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SFsdFSControl; 243 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SFsdDeviceControl; 244 | DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = SFsdShutdown; 245 | // For byte-range lock support, enable initialization of the following 246 | // function pointer and implement appropriate support. Use Chapter 10 247 | // in the text to assist you in your efforts. 248 | // DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = SFsdLockControl; 249 | DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SFsdCleanup; 250 | // If your FSD supports security attributes, you should provide appropriate 251 | // dispatch entry points and initialize the function pointers as given below. 252 | // DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = SFsdSecurity; 253 | // DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = SFsdSecurity; 254 | // If you support extended attributes, you should provide appropriate 255 | // dispatch entry points and initialize the function pointers as given below. 256 | // DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = SFsdExtendedAttr; 257 | // DriverObject->MajorFunction[IRP_MJ_SET_EA] = SFsdExtendedAttr; 258 | 259 | // Now, it is time to initialize the fast-io stuff ... 260 | PtrFastIoDispatch = DriverObject->FastIoDispatch = &(SFsdGlobalData.SFsdFastIoDispatch); 261 | 262 | // initialize the global fast-io structure 263 | // NOTE: The fast-io structure has undergone a substantial revision 264 | // in Windows NT Version 4.0. The structure has been extensively expanded. 265 | // Therefore, if your driver needs to work on both V3.51 and V4.0+, 266 | // you will have to be able to distinguish between the two versions at compile time. 267 | PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); 268 | PtrFastIoDispatch->FastIoCheckIfPossible = SFsdFastIoCheckIfPossible; 269 | PtrFastIoDispatch->FastIoRead = SFsdFastIoRead; 270 | PtrFastIoDispatch->FastIoWrite = SFsdFastIoWrite; 271 | PtrFastIoDispatch->FastIoQueryBasicInfo = SFsdFastIoQueryBasicInfo; 272 | PtrFastIoDispatch->FastIoQueryStandardInfo = SFsdFastIoQueryStdInfo; 273 | PtrFastIoDispatch->FastIoLock = SFsdFastIoLock; 274 | PtrFastIoDispatch->FastIoUnlockSingle = SFsdFastIoUnlockSingle; 275 | PtrFastIoDispatch->FastIoUnlockAll = SFsdFastIoUnlockAll; 276 | PtrFastIoDispatch->FastIoUnlockAllByKey = SFsdFastIoUnlockAllByKey; 277 | PtrFastIoDispatch->AcquireFileForNtCreateSection = SFsdFastIoAcqCreateSec; 278 | PtrFastIoDispatch->ReleaseFileForNtCreateSection = SFsdFastIoRelCreateSec; 279 | 280 | // the remaining are only valid under NT Version 4.0 and later 281 | #if(_WIN32_WINNT >= 0x0400) 282 | PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = SFsdFastIoQueryNetInfo; 283 | PtrFastIoDispatch->AcquireForModWrite = SFsdFastIoAcqModWrite; 284 | PtrFastIoDispatch->ReleaseForModWrite = SFsdFastIoRelModWrite; 285 | PtrFastIoDispatch->AcquireForCcFlush = SFsdFastIoAcqCcFlush; 286 | PtrFastIoDispatch->ReleaseForCcFlush = SFsdFastIoRelCcFlush; 287 | 288 | // MDL functionality 289 | PtrFastIoDispatch->MdlRead = SFsdFastIoMdlRead; 290 | PtrFastIoDispatch->MdlReadComplete = SFsdFastIoMdlReadComplete; 291 | PtrFastIoDispatch->PrepareMdlWrite = SFsdFastIoPrepareMdlWrite; 292 | PtrFastIoDispatch->MdlWriteComplete = SFsdFastIoMdlWriteComplete; 293 | 294 | // although this FSD does not support compressed read/write functionality, 295 | // NTFS does, and if you design a FSD that can provide such functionality, 296 | // you should consider initializing the fast io entry points for reading 297 | // and/or writing compressed data ... 298 | #endif // (_WIN32_WINNT >= 0x0400) 299 | 300 | // last but not least, initialize the Cache Manager callback functions 301 | // which are used in CcInitializeCacheMap() 302 | SFsdGlobalData.CacheMgrCallBacks.AcquireForLazyWrite = SFsdAcqLazyWrite; 303 | SFsdGlobalData.CacheMgrCallBacks.ReleaseFromLazyWrite = SFsdRelLazyWrite; 304 | SFsdGlobalData.CacheMgrCallBacks.AcquireForReadAhead = SFsdAcqReadAhead; 305 | SFsdGlobalData.CacheMgrCallBacks.ReleaseFromReadAhead = SFsdRelReadAhead; 306 | 307 | return; 308 | } 309 | 310 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/shutdown.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: shutdown.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains code to handle the "shutdown notification" dispatch entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfsd.h" 17 | 18 | // define the file specific bug-check id 19 | #define SFSD_BUG_CHECK_ID SFSD_FILE_SHUTDOWN 20 | 21 | 22 | 23 | /************************************************************************* 24 | * 25 | * Function: SFsdShutdown() 26 | * 27 | * Description: 28 | * All disk-based FSDs can expect to receive this shutdown notification 29 | * request whenever the system is about to be halted gracefully. If you 30 | * design and implement a network redirector, you must register explicitly 31 | * for shutdown notification by invoking the IoRegisterShutdownNotification() 32 | * routine from your driver entry. 33 | * 34 | * Note that drivers that register to receive shutdown notification get 35 | * invoked BEFORE disk-based FSDs are told about the shutdown notification. 36 | * 37 | * Expected Interrupt Level (for execution) : 38 | * 39 | * IRQL_PASSIVE_LEVEL 40 | * 41 | * Return Value: Irrelevant. 42 | * 43 | *************************************************************************/ 44 | NTSTATUS SFsdShutdown( 45 | PDEVICE_OBJECT DeviceObject, // the logical volume device object 46 | PIRP Irp) // I/O Request Packet 47 | { 48 | NTSTATUS RC = STATUS_SUCCESS; 49 | PtrSFsdIrpContext PtrIrpContext = NULL; 50 | BOOLEAN AreWeTopLevel = FALSE; 51 | 52 | FsRtlEnterFileSystem(); 53 | ASSERT(DeviceObject); 54 | ASSERT(Irp); 55 | 56 | // set the top level context 57 | AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 58 | 59 | try { 60 | 61 | // get an IRP context structure and issue the request 62 | PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 63 | ASSERT(PtrIrpContext); 64 | 65 | RC = SFsdCommonShutdown(PtrIrpContext, Irp); 66 | 67 | } except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 68 | 69 | RC = SFsdExceptionHandler(PtrIrpContext, Irp); 70 | 71 | SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 72 | } 73 | 74 | if (AreWeTopLevel) { 75 | IoSetTopLevelIrp(NULL); 76 | } 77 | 78 | FsRtlExitFileSystem(); 79 | 80 | return(RC); 81 | } 82 | 83 | 84 | 85 | /************************************************************************* 86 | * 87 | * Function: SFsdCommonShutdown() 88 | * 89 | * Description: 90 | * The actual work is performed here. Basically, all we do here is 91 | * internally invoke a flush on all mounted logical volumes. This, in 92 | * tuen, will result in all open file streams being flushed to disk. 93 | * 94 | * Expected Interrupt Level (for execution) : 95 | * 96 | * IRQL_PASSIVE_LEVEL 97 | * 98 | * Return Value: Irrelevant 99 | * 100 | *************************************************************************/ 101 | NTSTATUS SFsdCommonShutdown( 102 | PtrSFsdIrpContext PtrIrpContext, 103 | PIRP PtrIrp) 104 | { 105 | NTSTATUS RC = STATUS_SUCCESS; 106 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 107 | IO_STATUS_BLOCK LocalIoStatus; 108 | 109 | try { 110 | // First, get a pointer to the current I/O stack location 111 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 112 | ASSERT(PtrIoStackLocation); 113 | 114 | // Here is the algorithm you can follow in implementing your shutdown 115 | // functionality. Note, of course, that it is quite possible that you 116 | // may wish to do much more specialized processing in your specific 117 | // (commercial) FSD at shutdown time; the steps listed below, however, 118 | // are those that you should implement at a minimum: 119 | // (a) Block all new "mount volume" requests by acquiring an appropriate 120 | // global resource/lock. 121 | // (b) Go through your linked list of mounted logical volumes and for 122 | // each such volume, do the following: 123 | // (i) acquire the volume resource exclusively 124 | // (ii) invoke SFsdFlushLogicalVolume() (internally) to flush the 125 | // open data streams belonging to the volume from the system 126 | // cache 127 | // (iii) Invoke the physical/virtual/logical target device object 128 | // on which the volume is mounted and inform this device 129 | // about the shutdown request (Use IoBuildSynchronousFsdRequest() 130 | // to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you 131 | // will then issue to the target device object). 132 | // (iv) Wait for the completion of the shutdown processing by the target 133 | // device object 134 | // (v) Release the VCB resource you will have acquired in (i) above. 135 | 136 | // Once you have processed all the mounted logical volumes, you can release 137 | // all acquired global resources and leave (in peace :-) 138 | 139 | try_exit: NOTHING; 140 | 141 | } finally { 142 | 143 | // See the read/write examples for how to fill in this portion 144 | 145 | } // end of "finally" processing 146 | 147 | return(RC); 148 | } 149 | 150 |  -------------------------------------------------------------------------------- /NTFsrc/filesys/src/sources: -------------------------------------------------------------------------------- 1 | # - Execute the "build" command to make the sample FSD driver 2 | 3 | # The TARGETNAME variable is defined by the developer. It is the name of 4 | # the target (component) that is being built by this makefile. It 5 | # should NOT include any path or file extension information. 6 | 7 | TARGETNAME=sfsd 8 | 9 | # The TARGETPATH and TARGETTYPE variables are defined by the developer. 10 | # The first specifies where the target is to be build. The second specifies 11 | # the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or 12 | # BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode 13 | # apps and don't need to build a library. 14 | 15 | TARGETPATH=obj 16 | 17 | TARGETTYPE=DRIVER 18 | 19 | # The INCLUDES variable specifies any include paths that are specific to 20 | # this source directory. Separate multiple directory paths with single 21 | # semicolons. Relative path specifications are okay. The INCLUDES 22 | # variable is not required. Specifying an empty INCLUDES variable 23 | # (i.e. INCLUDES= ) indicates no include paths are to be searched. 24 | # 25 | # NOTE: The "fsdk\inc" refers to the Microsoft supplied Installable File Systems 26 | # Developers Kit. 27 | INCLUDES=..\inc;\ddk-40\inc;\fsdk\inc-40; 28 | 29 | # The SOURCES variable is defined by the developer. It is a list of all the 30 | # source files for this component. Each source file should be on a separate 31 | # line using the line continuation character. This will minimize merge 32 | # conflicts if two developers adding source files to the same component. 33 | # The SOURCES variable is required. If there are no platform common source 34 | # files, an empty SOURCES variable should be used. (i.e. SOURCES= ) 35 | 36 | # Source files common to multiple platforms 37 | 38 | SOURCES=sfsdinit.c \ 39 | create.c \ 40 | misc.c \ 41 | cleanup.c \ 42 | close.c \ 43 | read.c \ 44 | write.c \ 45 | fileinfo.c \ 46 | flush.c \ 47 | dircntrl.c \ 48 | devcntrl.c \ 49 | shutdown.c \ 50 | fastio.c 51 | 52 | # Next specify any additional options for the compiler. 53 | # Define the appropriate CPU type (and insert defines 54 | # in the appropriate header file) to get the right 55 | # values for "uint8", "uint16" etc. typedefs. 56 | 57 | C_DEFINES= -DUNICODE -D_CPU_X86_ 58 | 59 | # The type of product being built - NT = kernel mode 60 | 61 | UMTYPE=nt 62 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/WS_FTP.LOG: -------------------------------------------------------------------------------- 1 | 97.08.05 15:11 B C:\Users\Erik\NTFdisk\filter-high\readme2.txt --> geode /home/eray readme2.txt 2 | 97.08.06 14:20 B C:\Users\erik\NTFdisk\filter-high\readme2.txt <-- geode /work/nt/file.internals/disk readme2.txt 3 | -------------------------------------------------------------------------------- /NTFsrc/filter-high/inc/protos.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: protos.h 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains the prototypes for functions in this sample filter driver. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #ifndef _SFILTER_PROTOS_H_ 17 | #define _SFILTER_PROTOS_H_ 18 | 19 | /************************************************************************ 20 | * prototypes for the file sfilinit.c 21 | ************************************************************************/ 22 | extern NTSTATUS DriverEntry( 23 | PDRIVER_OBJECT DriverObject, // created by the I/O sub-system 24 | PUNICODE_STRING RegistryPath); // path to the registry key 25 | 26 | extern void SFilterInitializeFunctionPointers( 27 | PDRIVER_OBJECT DriverObject); // created by the I/O sub-system 28 | 29 | /************************************************************************ 30 | * prototypes for the file fastio.c 31 | ************************************************************************/ 32 | extern BOOLEAN SFilterFastIoCheckIfPossible( 33 | IN PFILE_OBJECT FileObject, 34 | IN PLARGE_INTEGER FileOffset, 35 | IN ULONG Length, 36 | IN BOOLEAN Wait, 37 | IN ULONG LockKey, 38 | IN BOOLEAN CheckForReadOperation, 39 | OUT PIO_STATUS_BLOCK IoStatus, 40 | IN PDEVICE_OBJECT DeviceObject); 41 | 42 | extern BOOLEAN SFilterFastIoRead( 43 | IN PFILE_OBJECT FileObject, 44 | IN PLARGE_INTEGER FileOffset, 45 | IN ULONG Length, 46 | IN BOOLEAN Wait, 47 | IN ULONG LockKey, 48 | OUT PVOID Buffer, 49 | OUT PIO_STATUS_BLOCK IoStatus, 50 | IN PDEVICE_OBJECT DeviceObject); 51 | 52 | extern BOOLEAN SFilterFastIoWrite( 53 | IN PFILE_OBJECT FileObject, 54 | IN PLARGE_INTEGER FileOffset, 55 | IN ULONG Length, 56 | IN BOOLEAN Wait, 57 | IN ULONG LockKey, 58 | OUT PVOID Buffer, 59 | OUT PIO_STATUS_BLOCK IoStatus, 60 | IN PDEVICE_OBJECT DeviceObject); 61 | 62 | extern BOOLEAN SFilterFastIoQueryBasicInfo( 63 | IN PFILE_OBJECT FileObject, 64 | IN BOOLEAN Wait, 65 | OUT PFILE_BASIC_INFORMATION Buffer, 66 | OUT PIO_STATUS_BLOCK IoStatus, 67 | IN PDEVICE_OBJECT DeviceObject); 68 | 69 | extern BOOLEAN SFilterFastIoQueryStdInfo( 70 | IN PFILE_OBJECT FileObject, 71 | IN BOOLEAN Wait, 72 | OUT PFILE_STANDARD_INFORMATION Buffer, 73 | OUT PIO_STATUS_BLOCK IoStatus, 74 | IN PDEVICE_OBJECT DeviceObject); 75 | 76 | extern BOOLEAN SFilterFastIoLock( 77 | IN PFILE_OBJECT FileObject, 78 | IN PLARGE_INTEGER FileOffset, 79 | IN PLARGE_INTEGER Length, 80 | PEPROCESS ProcessId, 81 | ULONG Key, 82 | BOOLEAN FailImmediately, 83 | BOOLEAN ExclusiveLock, 84 | OUT PIO_STATUS_BLOCK IoStatus, 85 | IN PDEVICE_OBJECT DeviceObject); 86 | 87 | extern BOOLEAN SFilterFastIoUnlockSingle( 88 | IN PFILE_OBJECT FileObject, 89 | IN PLARGE_INTEGER FileOffset, 90 | IN PLARGE_INTEGER Length, 91 | PEPROCESS ProcessId, 92 | ULONG Key, 93 | OUT PIO_STATUS_BLOCK IoStatus, 94 | IN PDEVICE_OBJECT DeviceObject); 95 | 96 | extern BOOLEAN SFilterFastIoUnlockAll( 97 | IN PFILE_OBJECT FileObject, 98 | PEPROCESS ProcessId, 99 | OUT PIO_STATUS_BLOCK IoStatus, 100 | IN PDEVICE_OBJECT DeviceObject); 101 | 102 | extern BOOLEAN SFilterFastIoUnlockAllByKey( 103 | IN PFILE_OBJECT FileObject, 104 | PEPROCESS ProcessId, 105 | ULONG Key, 106 | OUT PIO_STATUS_BLOCK IoStatus, 107 | IN PDEVICE_OBJECT DeviceObject); 108 | 109 | extern BOOLEAN SFilterFastIoDeviceControl( 110 | IN PFILE_OBJECT FileObject, 111 | IN BOOLEAN Wait, 112 | IN PVOID InputBuffer, 113 | IN ULONG InputBufferLength, 114 | OUT PVOID OutputBuffer, 115 | IN ULONG OutputBufferLength, 116 | IN ULONG IoControlCode, 117 | OUT PIO_STATUS_BLOCK IoStatus, 118 | IN PDEVICE_OBJECT DeviceObject); 119 | 120 | extern void SFilterFastIoAcqCreateSec( 121 | IN PFILE_OBJECT FileObject); 122 | 123 | extern void SFilterFastIoRelCreateSec( 124 | IN PFILE_OBJECT FileObject); 125 | 126 | #if(_WIN32_WINNT >= 0x0400) 127 | 128 | extern void SFilterFastIoDetachDevice( 129 | PDEVICE_OBJECT SourceDeviceObject, // our device object 130 | PDEVICE_OBJECT TargetDeviceObject); 131 | 132 | extern BOOLEAN SFilterFastIoQueryNetInfo( 133 | IN PFILE_OBJECT FileObject, 134 | IN BOOLEAN Wait, 135 | OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, 136 | OUT PIO_STATUS_BLOCK IoStatus, 137 | IN PDEVICE_OBJECT DeviceObject); 138 | 139 | extern BOOLEAN SFilterFastIoMdlRead( 140 | IN PFILE_OBJECT FileObject, 141 | IN PLARGE_INTEGER FileOffset, 142 | IN ULONG Length, 143 | IN ULONG LockKey, 144 | OUT PMDL *MdlChain, 145 | OUT PIO_STATUS_BLOCK IoStatus, 146 | IN PDEVICE_OBJECT DeviceObject); 147 | 148 | extern BOOLEAN SFilterFastIoMdlReadComplete( 149 | IN PFILE_OBJECT FileObject, 150 | OUT PMDL MdlChain, 151 | IN PDEVICE_OBJECT DeviceObject); 152 | 153 | extern BOOLEAN SFilterFastIoPrepareMdlWrite( 154 | IN PFILE_OBJECT FileObject, 155 | IN PLARGE_INTEGER FileOffset, 156 | IN ULONG Length, 157 | IN ULONG LockKey, 158 | OUT PMDL *MdlChain, 159 | OUT PIO_STATUS_BLOCK IoStatus, 160 | IN PDEVICE_OBJECT DeviceObject); 161 | 162 | extern BOOLEAN SFilterFastIoMdlWriteComplete( 163 | IN PFILE_OBJECT FileObject, 164 | IN PLARGE_INTEGER FileOffset, 165 | OUT PMDL MdlChain, 166 | IN PDEVICE_OBJECT DeviceObject); 167 | 168 | extern BOOLEAN SFilterFastIoReadCompressed( 169 | IN PFILE_OBJECT FileObject, 170 | IN PLARGE_INTEGER FileOffset, 171 | IN ULONG Length, 172 | IN ULONG LockKey, 173 | OUT PVOID Buffer, 174 | OUT PMDL *MdlChain, 175 | OUT PIO_STATUS_BLOCK IoStatus, 176 | OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, 177 | IN ULONG CompressedDataInfoLength, 178 | IN PDEVICE_OBJECT DeviceObject); 179 | 180 | extern BOOLEAN SFilterFastIoWriteCompressed( 181 | IN PFILE_OBJECT FileObject, 182 | IN PLARGE_INTEGER FileOffset, 183 | IN ULONG Length, 184 | IN ULONG LockKey, 185 | OUT PVOID Buffer, 186 | OUT PMDL *MdlChain, 187 | OUT PIO_STATUS_BLOCK IoStatus, 188 | OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, 189 | IN ULONG CompressedDataInfoLength, 190 | IN PDEVICE_OBJECT DeviceObject); 191 | 192 | extern BOOLEAN SFilterFastIoMdlReadCompleteCompressed( 193 | IN PFILE_OBJECT FileObject, 194 | OUT PMDL MdlChain, 195 | IN PDEVICE_OBJECT DeviceObject); 196 | 197 | extern BOOLEAN SFilterFastIoMdlWriteCompleteCompressed( 198 | IN PFILE_OBJECT FileObject, 199 | IN PLARGE_INTEGER FileOffset, 200 | OUT PMDL MdlChain, 201 | IN PDEVICE_OBJECT DeviceObject); 202 | 203 | extern NTSTATUS SFilterFastIoAcqModWrite( 204 | IN PFILE_OBJECT FileObject, 205 | IN PLARGE_INTEGER EndingOffset, 206 | OUT PERESOURCE *ResourceToRelease, 207 | IN PDEVICE_OBJECT DeviceObject); 208 | 209 | extern NTSTATUS SFilterFastIoRelModWrite( 210 | IN PFILE_OBJECT FileObject, 211 | IN PERESOURCE ResourceToRelease, 212 | IN PDEVICE_OBJECT DeviceObject); 213 | 214 | extern NTSTATUS SFilterFastIoAcqCcFlush( 215 | IN PFILE_OBJECT FileObject, 216 | IN PDEVICE_OBJECT DeviceObject); 217 | 218 | extern NTSTATUS SFilterFastIoRelCcFlush( 219 | IN PFILE_OBJECT FileObject, 220 | IN PDEVICE_OBJECT DeviceObject); 221 | 222 | extern BOOLEAN SFilterFastIoQueryOpen( 223 | IN PIRP Irp, 224 | OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, 225 | IN PDEVICE_OBJECT DeviceObject); 226 | 227 | #endif //_WIN32_WINNT >= 0x0400 228 | 229 | /************************************************************************ 230 | * prototypes for the file attach.c 231 | ************************************************************************/ 232 | extern NTSTATUS SFilterAttachTarget( 233 | PDEVICE_OBJECT PtrTargetDeviceObject, 234 | PDEVICE_OBJECT *PtrNewDeviceObject); 235 | 236 | extern void SFilterDetachTarget( 237 | PDEVICE_OBJECT SourceDeviceObject, 238 | PDEVICE_OBJECT TargetDeviceObject, 239 | PtrSFilterDeviceExtension PtrDeviceExtension); 240 | 241 | /************************************************************************ 242 | * prototypes for the file dispatch.c 243 | ************************************************************************/ 244 | extern NTSTATUS SFilterDefaultDispatch ( 245 | PDEVICE_OBJECT DeviceObject, // Our device object 246 | PIRP Irp); // I/O Request Packet 247 | 248 | extern NTSTATUS SFilterDefaultCompletion( 249 | PDEVICE_OBJECT PtrDeviceObject, 250 | PIRP PtrIrp, 251 | void *Context); 252 | 253 | /************************************************************************ 254 | * prototypes for the file misc.c 255 | ************************************************************************/ 256 | extern void SFilterInitDevExtension( 257 | PtrSFilterDeviceExtension PtrDeviceExtension, 258 | PDEVICE_OBJECT PtrAssociatedDeviceObject, 259 | uint32 NodeType); 260 | 261 | extern void SFilterDeleteDevExtension( 262 | PtrSFilterDeviceExtension PtrDeviceExtension, 263 | BOOLEAN ResourceAcquired); 264 | 265 | extern NTSTATUS SFilterCreateDirectory( 266 | PWCHAR DirectoryNameStr, 267 | PHANDLE PtrReturnedHandle, 268 | BOOLEAN MakeTemporaryObject); 269 | 270 | extern void SFilterReinitialize( 271 | PDRIVER_OBJECT DriverObject, // representing the filter driver 272 | void *Context, // this filter driver supplies registry path 273 | ULONG Count); // # times this function invoked 274 | 275 | extern void SFilterFSDNotification( 276 | PDEVICE_OBJECT PtrTargetFileSystemDeviceObject, 277 | BOOLEAN DriverActive); 278 | 279 | /************************************************************************ 280 | * prototypes for the file create.c 281 | ************************************************************************/ 282 | 283 | extern NTSTATUS SFilterCreate( 284 | PDEVICE_OBJECT DeviceObject, // Our device object 285 | PIRP Irp); // I/O Request Packet 286 | 287 | /************************************************************************ 288 | * prototypes for the file close.c 289 | ************************************************************************/ 290 | 291 | extern NTSTATUS SFilterCleanupOrClose( 292 | PDEVICE_OBJECT DeviceObject, // Our device object 293 | PIRP Irp); // I/O Request Packet 294 | 295 | /************************************************************************ 296 | * prototypes for the file fsctrl.c 297 | ************************************************************************/ 298 | 299 | extern NTSTATUS SFilterFSControl( 300 | PDEVICE_OBJECT DeviceObject, // Our device object 301 | PIRP Irp); // I/O Request Packet 302 | 303 | extern NTSTATUS SFilterMountVolumeCompletion( 304 | PDEVICE_OBJECT PtrDeviceObject, 305 | PIRP PtrIrp, 306 | void *Context); 307 | 308 | extern void SFilterMountAttach( 309 | void *Context); 310 | 311 | #endif // _SFILTER_PROTOS_H_ 312 | 313 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/inc/sfilter.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfilter.h 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * The main include file for the sample filter driver. This file contains 9 | * a mish-mash of things. 10 | * 11 | * Author: R. Nagar 12 | * 13 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 14 | * 15 | *************************************************************************/ 16 | 17 | #ifndef _SFILTER_SFILTER_H_ 18 | #define _SFILTER_SFILTER_H_ 19 | 20 | // some constant definitions 21 | #define SFILTER_PANIC_IDENTIFIER (0x86427532) 22 | 23 | #define SFILTER_DRV_DIR L"\\Device\\SFilter" 24 | #define SFILTER_DOS_DRV_DIR L"\\DosDevices\\SFilter" 25 | #define SFILTER_DRV_NAME L"\\Device\\SFilter\\SampleFilterDrv" 26 | #define SFILTER_DOS_DRV_NAME L"\\DosDevices\\SFilter\\SampleFilterDrv" 27 | 28 | 29 | // Common include files - should be in the include dir of the MS supplied FSDDK 30 | #include 31 | 32 | // the following include files should be in the inc sub-dir associated with this driver 33 | #include "struct.h" 34 | #include "protos.h" 35 | // #include "errmsg.h" 36 | 37 | // global variables - minimize these 38 | extern SFilterData SFilterGlobalData; 39 | 40 | 41 | /********************************************************************************** 42 | * 43 | * The following macros make life a little easier 44 | * 45 | **********************************************************************************/ 46 | 47 | // try-finally simulation 48 | #define try_return(S) { S; goto try_exit; } 49 | #define try_return1(S) { S; goto try_exit1; } 50 | #define try_return2(S) { S; goto try_exit2; } 51 | 52 | // Flag (bit-field) manipulation 53 | #define SFilterSetFlag(Flag, Value) ((Flag) |= (Value)) 54 | #define SFilterClearFlag(Flag, Value) ((Flag) &= ~(Value)) 55 | 56 | // Align a value along a 4-byte boundary. 57 | #define SFilterQuadAlign(Value) ((((uint32)(Value)) + 7) & 0xfffffff8) 58 | 59 | // to perform a bug-check (panic), the following macro is used 60 | // it allows us to print out the file identifier, line #, and upto 3 61 | // additional DWORD arguments. 62 | #define SFilterPanic(arg1, arg2, arg3) \ 63 | (KeBugCheckEx(SFILTER_PANIC_IDENTIFIER, SFILTER_BUG_CHECK_ID | __LINE__, (uint32)(arg1), (uint32)(arg2), (uint32)(arg3))) 64 | 65 | // Release a resource in the context of the thread that originally acquired the 66 | // resource. 67 | #define SFilterReleaseResource(Resource) (ExReleaseResourceForThreadLite((Resource), ExGetCurrentResourceThread())) 68 | 69 | // the following check asserts that the passed-in device extension 70 | // pointer is valid 71 | #define SFilterAssertExtPtrValid(PtrExtension) { \ 72 | ASSERT((PtrExtension)); \ 73 | ASSERT((((PtrExtension)->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_FILTER_DEVICE) || \ 74 | ((PtrExtension)->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_ATTACHED_DEVICE)) &&\ 75 | ((PtrExtension)->NodeIdentifier.NodeSize == sizeof(SFilterDeviceExtension))); \ 76 | } 77 | 78 | // the following macro allows us to increment a large integer value atomically. 79 | // we expect an unsigned long to be supplied as the increment value. 80 | // a spin lock should be passed-in to synchronize operations 81 | #define SFilterIncrementLargeInteger(LargeIntegerOp, ULongIncrement, PtrSpinLock) { \ 82 | KIRQL OldIrql; \ 83 | KeAcquireSpinLock(PtrSpinLock, &OldIrql); \ 84 | RtlLargeIntegerAdd((LargeIntegerOp),(RtlConvertUlongToLargeInteger((ULongIncrement)))); \ 85 | KeReleaseSpinLock(PtrSpinLock, OldIrql); \ 86 | } 87 | 88 | // the following macro allows us to decrement a large integer value atomically. 89 | // we expect an unsigned long to be supplied as the decrement value. 90 | // a spin lock should be passed-in to synchronize operations 91 | #define SFilterDecrementLargeInteger(LargeIntegerOp, ULongIncrement, PtrSpinLock) { \ 92 | KIRQL OldIrql; \ 93 | KeAcquireSpinLock(PtrSpinLock, &OldIrql); \ 94 | RtlLargeIntegerSubtract((LargeIntegerOp),(RtlConvertUlongToLargeInteger((ULongIncrement)))); \ 95 | KeReleaseSpinLock(PtrSpinLock, OldIrql); \ 96 | } 97 | 98 | // the following macro allows us to check if the large integer value is zero, 99 | // atomically. Note that I have added (for convenience) a check to ensure that 100 | // the value is non-negative. 101 | #define SFilterIsLargeIntegerZero(ReturnValue, LargeIntegerOp, PtrSpinLock) { \ 102 | KIRQL OldIrql; \ 103 | KeAcquireSpinLock(PtrSpinLock, &OldIrql); \ 104 | ASSERT(RtlLargeIntegerGreaterOrEqualToZero((LargeIntegerOp))); \ 105 | ReturnValue = RtlLargeIntegerEqualToZero((LargeIntegerOp)); \ 106 | KeReleaseSpinLock(PtrSpinLock, OldIrql); \ 107 | } 108 | 109 | /********************************************************************************** 110 | * 111 | * End of macro definitions 112 | * 113 | **********************************************************************************/ 114 | 115 | // each file has a unique bug-check identifier associated with it. 116 | // Here is a list of constant definitions for these identifiers 117 | #define SFILTER_FILE_INIT (0x00000001) 118 | #define SFILTER_FILE_ATTACH (0x00000002) 119 | #define SFILTER_FILE_FAST_IO (0x00000003) 120 | #define SFILTER_FILE_MISC (0x00000004) 121 | #define SFILTER_FILE_DISPATCH (0x00000005) 122 | #define SFILTER_FILE_CREATE (0x00000006) 123 | #define SFILTER_FILE_CLOSE (0x00000007) 124 | #define SFILTER_FILE_FSCTRL (0x00000008) 125 | 126 | #if DBG 127 | #define SFilterBreakPoint() DbgBreakPoint() 128 | #else 129 | #define SFilterBreakPoint() 130 | #endif 131 | 132 | #endif // _SFILTER_SFILTER_H_ 133 | 134 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/inc/struct.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: struct.h 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * This file contains structure definitions for the sample filter 9 | * driver. Note that all structures are prefixed with the letters 10 | * "SFilter". The structures are all aligned using normal alignment 11 | * used by the compiler (typically quad-word aligned). 12 | * 13 | * Author: R. Nagar 14 | * 15 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 16 | * 17 | *************************************************************************/ 18 | 19 | #ifndef _SFILTER_STRUCTURES_H_ 20 | #define _SFILTER_STRUCTURES_H_ 21 | 22 | /************************************************************************** 23 | some useful definitions 24 | **************************************************************************/ 25 | #ifdef _CPU_X86_ 26 | typedef char int8; 27 | typedef short int16; 28 | typedef int int32; 29 | 30 | typedef unsigned char uint8; 31 | typedef unsigned short uint16; 32 | typedef unsigned int uint32; 33 | 34 | // we will use the LARGE_INTEGER structure as defined by NT 35 | 36 | #else // Please define appropriate types here 37 | 38 | !!!! You must define your types here for compilation to proceed !!!! 39 | 40 | #endif // if _CPU_X86_ 41 | 42 | /************************************************************************** 43 | some empty typedefs defined here so we can reference them easily 44 | **************************************************************************/ 45 | struct _SFilterIdentifier; 46 | struct _SFilterData; 47 | 48 | /************************************************************************** 49 | each structure has a unique "node type" or signature associated with it 50 | **************************************************************************/ 51 | #define SFILTER_NODE_TYPE_GLOBAL_DATA (0xfdecba10) 52 | #define SFILTER_NODE_TYPE_FILTER_DEVICE (0xfdecba11) 53 | #define SFILTER_NODE_TYPE_ATTACHED_DEVICE (0xfdecba12) 54 | #define SFILTER_NODE_TYPE_MOUNT_COMPLETION (0xfdecba13) 55 | 56 | /************************************************************************** 57 | every structure has a node type, and a node size associated with it. 58 | The node type serves as a signature field. The size is used for 59 | consistency checking ... 60 | **************************************************************************/ 61 | typedef struct _SFilterIdentifier { 62 | uint32 NodeType; // a 32 bit identifier for the structure 63 | uint32 NodeSize; // computed as sizeof(structure) 64 | } SFilterIdentifier, *PtrSFilterIdentifier; 65 | 66 | /************************************************************************** 67 | the device extension for each device object created by the filter driver 68 | **************************************************************************/ 69 | typedef struct _SFilterDeviceExtension { 70 | // A signature (including device size). 71 | SFilterIdentifier NodeIdentifier; 72 | // This is used to synchronize access to the device extension structure. 73 | ERESOURCE DeviceExtensionResource; 74 | // For convenience, a back ptr to the device object that contains this 75 | // extension. 76 | PDEVICE_OBJECT PtrAssociatedDeviceObject; 77 | // The sample filter driver keeps a private doubly-linked list of all 78 | // device objects created by the driver. 79 | LIST_ENTRY NextDeviceObject; 80 | // See Flag definitions below. 81 | uint32 DeviceExtensionFlags; 82 | // The device object we are attached to. 83 | PDEVICE_OBJECT TargetDeviceObject; 84 | // Stored for convenience. A pointer to the driver object for the 85 | // target device object (you can always obtain this information from 86 | // the target device object). 87 | PDRIVER_OBJECT TargetDriverObject; 88 | // If we are attached to a mounted volume instance, the actual FSD 89 | // created device object representing the instance of the mounted 90 | // volume. 91 | PDEVICE_OBJECT TargetMountedVolumeDeviceObject; 92 | // A count of outstanding I/O requests for which we have specified a 93 | // completion routine. 94 | LARGE_INTEGER OutstandingIoRequests; 95 | // The OutstandingIoRequests field is protected by an Executive spin lock. 96 | KSPIN_LOCK IoRequestsSpinLock; 97 | // The event object is used to synchronize detach requests with pending 98 | // I/O operations and similar stuff. 99 | KEVENT IoInProgressEvent; 100 | // You can associate other information here. 101 | } SFilterDeviceExtension, *PtrSFilterDeviceExtension; 102 | 103 | #define SFILTER_DEV_EXT_RESOURCE_INITIALIZED (0x00000001) 104 | #define SFILTER_DEV_EXT_INSERTED_GLOBAL_LIST (0x00000002) 105 | #define SFILTER_DEV_EXT_ATTACHED (0x00000004) 106 | #define SFILTER_DEV_EXT_ATTACHED_FSD (0x00000008) 107 | 108 | /************************************************************************** 109 | we will store all of our global variables in one structure. 110 | **************************************************************************/ 111 | typedef struct _SFilterData { 112 | SFilterIdentifier NodeIdentifier; 113 | // The fields in this list are protected by the following resource 114 | ERESOURCE GlobalDataResource; 115 | // Each driver has a driver object created for it by the NT I/O Mgr. 116 | // The filter driver is no exception to this rule. 117 | PDRIVER_OBJECT SFilterDriverObject; 118 | // We will create a device object for our filter driver as well ... 119 | // Although not really required, it helps if a helper application 120 | // writen by us wishes to send us control information via 121 | // IOCTL requests ... 122 | PDEVICE_OBJECT SFilterDeviceObject; 123 | // A driver private list of all device objects created by the filter driver. 124 | LIST_ENTRY NextDeviceObject; 125 | // The NT Cache Manager, the I/O Manager and we will conspire 126 | // to bypass IRP usage using the function pointers contained 127 | // in the following structure 128 | // We will require this if we layer on top of a file system. 129 | FAST_IO_DISPATCH SFilterFastIoDispatch; 130 | // Some state information is maintained in the flags field 131 | uint32 SFilterFlags; 132 | // Handle for the directory object created by the filter driver 133 | HANDLE DirectoryHandle; 134 | // Corresponding handle for the directory visible to the user 135 | HANDLE DosDirectoryHandle; 136 | } SFilterData, *PtrSFilterData; 137 | 138 | // Valid flag values for the global data structure 139 | #define SFILTER_DATA_FLAGS_RESOURCE_INITIALIZED (0x00000001) 140 | #define SFILTER_DATA_FLAGS_SYMLINK_CREATED (0x00000002) 141 | 142 | /************************************************************************** 143 | the following structure is used to pass-in as context to the mount 144 | completion routine. 145 | **************************************************************************/ 146 | 147 | typedef struct _SFilterMountCompletion { 148 | // A signature (including device size). 149 | SFilterIdentifier NodeIdentifier; 150 | // pointer to the target device object 151 | PDEVICE_OBJECT PtrDeviceObject; 152 | // pointer to the original IRP 153 | PIRP PtrOriginalIrp; 154 | // a pointer to the VPB structure in the IRP 155 | PVPB PtrVPB; 156 | // a pointer to our device extension (for the device object attached to the FSD) 157 | PtrSFilterDeviceExtension PtrDeviceExtension; 158 | // an embedded work queue item structure 159 | WORK_QUEUE_ITEM WorkItem; 160 | } SFilterMountCompletion, *PtrSFilterMountCompletion; 161 | 162 | 163 | #endif _SFILTER_STRUCTURES_H_ // has this file been included ? 164 | 165 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/readme2.txt: -------------------------------------------------------------------------------- 1 | Sample Filter Driver 2 | ------------------- 3 | 4 | The sample filter driver provided here can be used to design 5 | and implement kernel-mode filter drivers. This driver has been designed and 6 | implemented to allow filtering file system requests. 7 | Note that you should use the driver source provided here in conjunction with 8 | the chapters in the text to better understand the subtleties of implementing 9 | such kernel-mode filter drivers. 10 | 11 | Building and Installing 12 | ----------------------- 13 | 14 | 1) Set the environment variables by running the SDK SETENV.BAT and the DDK 15 | SETENV.BAT. 16 | 17 | 2) Run BUILD.EXE with the -cef option. 18 | 19 | 3) The driver is built in the OBJ\I386\CHECKED (or FREE) directory; copy 20 | it to %WINDIR%\SYSTEM32\DRIVERS. 21 | 22 | 4) Run REGINI.EXE with SFILTER.INI as an argument. 23 | 24 | 5) Reboot the machine (be careful to have a debugger installed and 25 | executing for the target machine). 26 | 27 | Restrictions: 28 | ------------ 29 | 30 | This sample driver attaches itself to all FSDs that register with 31 | the I/O Manager. It doesn't attempt to attach itself to the RAW file system, 32 | neither does it concern itself with network redirectors. 33 | 34 | If you wish to use the code with Windows NT 3.51, you may need to 35 | modify the source to open specific FSDs by name. 36 | 37 | How to use: 38 | ---------- 39 | 40 | You should modify the source provided here (e.g., add appropriate print 41 | statements) that will aid in understanding how FSD requests are 42 | issued and processed. Use this source to serve as a template in 43 | designing and implementing your own commercial filter driver. 44 | 45 | Files provided: 46 | -------------- 47 | 48 | src\sfilinit.c - Contains DriverEntry function that initializes the driver 49 | src\fastio.c - Contains fast I/O function calls implemented by the filter 50 | src\misc.c - Misc. routines (e.g., to initialize a device extension) 51 | src\fsctrl.c - Code to intercept FSD mount requests (and initiate attach) 52 | src\dispatch.c - The "pass-thru" mode, i.e., we send everything through 53 | src\create.c - Special intercept routine for create/open requests 54 | src\close.c - Special intercept routine for cleanup and close requests 55 | src\attach.c - Contains routines to perform an attach to target and^M 56 | a corresponding detach 57 | inc\protos.h - Prototypes for all functions in files listed above 58 | inc\sfilter.h - The "main" include file; also contains useful macros 59 | inc\struct.h - Structure type definitions. 60 | src\makefile - makefile! 61 | src\sources - Contains list of files to be built; used by build.exe 62 | README.TXT - What you are reading 63 | sfilter.ini - Use this file as an argument to regini.exe to modify 64 | your registry and install the driver. 65 | 66 |  67 | -------------------------------------------------------------------------------- /NTFsrc/filter-high/sfilter.ini: -------------------------------------------------------------------------------- 1 | \Registry\Machine\Software\Windows_NT_File_System_Internals\SFilter 2 | MajorVersionNumber = REG_DWORD 0x0 3 | MinorVersionNumber = REG_DWORD 0x1 4 | 5 | \Registry\Machine\System\CurrentControlSet\Services\SFilter 6 | Type = REG_DWORD 0x00000002 7 | Start = REG_DWORD 0x00000000 8 | ErrorControl = REG_DWORD 0x00000001 9 | Group = File System 10 | ImagePath = REG_EXPAND_SZ \SystemRoot\System32\drivers\sfilter.sys 11 | 12 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/attach.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: attach.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Deals with attaching to and detaching from a target device 9 | * object. Creates a device object as well to be used in the 10 | * attach process. 11 | * 12 | * Author: R. Nagar 13 | * 14 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 15 | * 16 | *************************************************************************/ 17 | 18 | #include "sfilter.h" 19 | 20 | /* define the file specific bug-check id */ 21 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_ATTACH 22 | 23 | 24 | /************************************************************************* 25 | * 26 | * Function: SFilterAttachTarget() 27 | * 28 | * Description: 29 | * We have the target FSD device object. We will create a new device object 30 | * of our own and attach this newly created device object to the target FSD 31 | * device object (representing the FSD itself or a mounted logical volume). 32 | * 33 | * Expected Interrupt Level (for execution) : 34 | * 35 | * IRQL_PASSIVE_LEVEL 36 | * 37 | * Return Value: STATUS_SUCCESS/Error 38 | * 39 | *************************************************************************/ 40 | NTSTATUS SFilterAttachTarget( 41 | PDEVICE_OBJECT PtrTargetDeviceObject, 42 | PDEVICE_OBJECT *PtrReturnedDeviceObject) 43 | { 44 | 45 | NTSTATUS RC = STATUS_SUCCESS; 46 | PDEVICE_OBJECT PtrNewDeviceObject = NULL; // device object we create. 47 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 48 | BOOLEAN InitializedDeviceObject = FALSE; 49 | BOOLEAN AcquiredDeviceObject = FALSE; 50 | 51 | ASSERT(PtrReturnedDeviceObject); 52 | 53 | try { 54 | 55 | // Create a new device object. 56 | if (!NT_SUCCESS(RC = IoCreateDevice(SFilterGlobalData.SFilterDriverObject, 57 | sizeof(SFilterDeviceExtension), 58 | NULL, // unnamed object 59 | PtrTargetDeviceObject->DeviceType, 60 | PtrTargetDeviceObject->Characteristics, 61 | FALSE, // Not exclusive. 62 | &PtrNewDeviceObject))) { 63 | // failed to create a device object; cannot do much now. 64 | SFilterBreakPoint(); 65 | try_return(RC); 66 | } 67 | 68 | // We do this whenever device objects are create on-the-fly (i.e. not as 69 | // part of driver initialization). 70 | PtrNewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 71 | 72 | // Initialize the extension for the device object. 73 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(PtrNewDeviceObject->DeviceExtension); 74 | SFilterInitDevExtension(PtrDeviceExtension, PtrNewDeviceObject, SFILTER_NODE_TYPE_ATTACHED_DEVICE); 75 | InitializedDeviceObject = TRUE; 76 | 77 | // Acquire the resource exclusively for our newly created device 78 | // object to ensure that dispatch routines requests are not processed 79 | // until we are really ready. 80 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 81 | AcquiredDeviceObject = TRUE; 82 | 83 | // attach to the target FSD. 84 | RC = IoAttachDeviceByPointer(PtrNewDeviceObject, PtrTargetDeviceObject); 85 | 86 | // The only reaon we would fail (and possibly get STATUS_NO_SUCH_DEVICE) 87 | // is if the target was being initialized or unloaded and neither should 88 | // be happenning at this time. 89 | ASSERT(NT_SUCCESS(RC)); 90 | 91 | // Note that the AlignmentRequirement, the StackSize, and the SectorSize 92 | // values will have been automatically initialized for us in the source 93 | // device object (the I/O Manager does this as part of processing the 94 | // IoAttachDeviceByPointer() request). 95 | 96 | // We should set the Flags values correctly to indicate whether 97 | // direct-IO, buffered-IO, or neither is required. Typically, FSDs 98 | // (especially native FSD implementations) do not want the I/O 99 | // Manager to touch the user buffer at all. 100 | PtrNewDeviceObject->Flags |= (PtrTargetDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)); 101 | 102 | // Initialize the TargetDeviceObject field in the extension. 103 | PtrDeviceExtension->TargetDeviceObject = PtrTargetDeviceObject; 104 | PtrDeviceExtension->TargetDriverObject = PtrTargetDeviceObject->DriverObject; 105 | SFilterSetFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_ATTACHED); 106 | SFilterSetFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_ATTACHED_FSD); 107 | 108 | // We are there now. All I/O requests will start being redirected to 109 | // us until we detach ourselves. 110 | 111 | try_exit: NOTHING; 112 | 113 | } finally { 114 | // Cleanup stuff goes here. 115 | if (AcquiredDeviceObject) { 116 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 117 | AcquiredDeviceObject = FALSE; 118 | } 119 | 120 | if (!NT_SUCCESS(RC) && PtrNewDeviceObject) { 121 | if (InitializedDeviceObject) { 122 | // The detach routine will take care of everything. 123 | SFilterDetachTarget(PtrNewDeviceObject, PtrTargetDeviceObject, PtrDeviceExtension); 124 | } 125 | } else { 126 | *PtrReturnedDeviceObject = PtrNewDeviceObject; 127 | } 128 | } 129 | 130 | return(RC); 131 | } 132 | 133 | 134 | 135 | /************************************************************************* 136 | * 137 | * Function: SFilterDetachTarget() 138 | * 139 | * Description: 140 | * This routine will detach from the target device object. It will delete 141 | * the locally created device object as well. Note that we must ensure that 142 | * no I/O requests are outstanding when this occurs (or we should drop them). 143 | * Finally, this routine could be invoked as a result of a fast detach call. 144 | * 145 | * Expected Interrupt Level (for execution) : 146 | * 147 | * IRQL_PASSIVE_LEVEL 148 | * 149 | * Return Value: None 150 | * 151 | *************************************************************************/ 152 | void SFilterDetachTarget( 153 | PDEVICE_OBJECT SourceDeviceObject, 154 | PDEVICE_OBJECT TargetDeviceObject, 155 | PtrSFilterDeviceExtension PtrDeviceExtension) 156 | { 157 | BOOLEAN AcquiredDevice = FALSE; 158 | BOOLEAN NoRequestsOutstanding = FALSE; 159 | 160 | ASSERT(SourceDeviceObject); 161 | ASSERT(PtrDeviceExtension); 162 | 163 | try { 164 | try { 165 | ASSERT(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 166 | 167 | // We will wait until all IRP-based I/O requests have been completed. 168 | 169 | while (TRUE) { 170 | // Acquire the device object resource exclusively. 171 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 172 | AcquiredDevice = TRUE; 173 | 174 | // Check if there are requests outstanding 175 | SFilterIsLargeIntegerZero(NoRequestsOutstanding, PtrDeviceExtension->OutstandingIoRequests, 176 | &(PtrDeviceExtension->IoRequestsSpinLock)); 177 | 178 | if (!NoRequestsOutstanding) { 179 | // Drop the resource and go to sleep. 180 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 181 | AcquiredDevice = FALSE; 182 | 183 | // Worst case, we will allow a few new I/O requests to slip in ... 184 | KeWaitForSingleObject((void *)(&(PtrDeviceExtension->IoInProgressEvent)), 185 | Executive, KernelMode, FALSE, NULL); 186 | } else { 187 | break; 188 | } 189 | } 190 | 191 | ASSERT(AcquiredDevice); 192 | 193 | // Detach if attached. 194 | if (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED) { 195 | IoDetachDevice(PtrDeviceExtension->TargetDeviceObject); 196 | SFilterClearFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_ATTACHED); 197 | // Blindly clear the attached-to-FSD flag 198 | SFilterClearFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_ATTACHED_FSD); 199 | } 200 | 201 | // Delete our device object. But first, take care of the device extension. 202 | SFilterDeleteDevExtension(PtrDeviceExtension, TRUE); 203 | AcquiredDevice = FALSE; 204 | // Note that on 4.0 and later systems, this will result in a recursive fast detach. 205 | IoDeleteDevice(SourceDeviceObject); 206 | 207 | } except (EXCEPTION_EXECUTE_HANDLER) { 208 | // Eat it up. 209 | ; 210 | } 211 | 212 | try_exit: NOTHING; 213 | 214 | } finally { 215 | if (AcquiredDevice) { 216 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 217 | AcquiredDevice = FALSE; 218 | } 219 | } 220 | 221 | return; 222 | } 223 | 224 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/close.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: create.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Cleanup/close entry points. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfilter.h" 17 | 18 | /* define the file specific bug-check id */ 19 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_CLOSE 20 | 21 | 22 | /************************************************************************* 23 | * 24 | * Function: SFilterCleanupOrClose() 25 | * 26 | * Description: 27 | * Intercept the cleanup/close request targeted to the FSD mounted logical 28 | * volume. This could also be a cleanup/close targeted to this filter driver in 29 | * which case we simply return success. 30 | * 31 | * Expected Interrupt Level (for execution) : 32 | * 33 | * Typically (though not guaranteed) @ IRQL_PASSIVE_LEVEL 34 | * 35 | * Return Value: STATUS_SUCCESS/Error 36 | * 37 | *************************************************************************/ 38 | NTSTATUS SFilterCleanupOrClose( 39 | PDEVICE_OBJECT DeviceObject, // Our device object 40 | PIRP Irp) // I/O Request Packet 41 | { 42 | NTSTATUS RC = STATUS_SUCCESS; 43 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 44 | PIO_STACK_LOCATION PtrCurrentStackLocation = NULL; 45 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 46 | BOOLEAN AcquiredExtension = FALSE; 47 | BOOLEAN CompleteIrp = FALSE; 48 | PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 49 | ULONG ReturnedInformation = 0; 50 | 51 | try { 52 | 53 | // Get the current I/O stack location. 54 | PtrCurrentStackLocation = IoGetCurrentIrpStackLocation(Irp); 55 | ASSERT(PtrCurrentStackLocation); 56 | 57 | // Get a pointer to the device extension that must exist for 58 | // all of the device objects created by the filter driver. 59 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(DeviceObject->DeviceExtension); 60 | SFilterAssertExtPtrValid(PtrDeviceExtension); 61 | 62 | // We really should not be here if our resource is not initialized? 63 | ASSERT(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 64 | 65 | // acquire the resource associated with particular device extension for 66 | // our target device object. 67 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 68 | AcquiredExtension = TRUE; 69 | 70 | // If the device extension is for a lower device forward the request. 71 | if ((PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_ATTACHED_DEVICE) 72 | && (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED)) { 73 | 74 | if (AcquiredExtension) { 75 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 76 | AcquiredExtension = FALSE; 77 | } 78 | 79 | RC = SFilterDefaultDispatch(DeviceObject, Irp); 80 | try_return(RC); 81 | } else if (PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_FILTER_DEVICE) { 82 | // This request was targeted to us. Simply return success. 83 | CompleteIrp = TRUE; 84 | try_return(RC); 85 | } 86 | 87 | // The filter driver does not particularly care to respond to these requests. 88 | CompleteIrp = TRUE; 89 | // does not matter what the Information field contains. 90 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 91 | 92 | try_exit: NOTHING; 93 | 94 | } finally { 95 | 96 | // Release any resources acquired. 97 | if (AcquiredExtension) { 98 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 99 | AcquiredExtension = FALSE; 100 | } 101 | 102 | // Complete the IRP only if we must. 103 | if (CompleteIrp) { 104 | Irp->IoStatus.Status = RC; 105 | Irp->IoStatus.Information = ReturnedInformation; 106 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 107 | } 108 | } 109 | 110 | return(RC); 111 | } 112 | 113 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/create.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: create.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Create/open entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfilter.h" 17 | 18 | /* define the file specific bug-check id */ 19 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_CREATE 20 | 21 | 22 | /************************************************************************* 23 | * 24 | * Function: SFilterCreate() 25 | * 26 | * Description: 27 | * Intercept the create/open request targeted to the FSD mounted logical 28 | * volume. This could also be a create targeted to this filter driver in 29 | * which case we simply return success. 30 | * 31 | * Expected Interrupt Level (for execution) : 32 | * 33 | * Typically (though not guaranteed) @ IRQL_PASSIVE_LEVEL 34 | * 35 | * Return Value: STATUS_SUCCESS/Error 36 | * 37 | *************************************************************************/ 38 | NTSTATUS SFilterCreate( 39 | PDEVICE_OBJECT DeviceObject, // Our device object 40 | PIRP Irp) // I/O Request Packet 41 | { 42 | NTSTATUS RC = STATUS_SUCCESS; 43 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 44 | PIO_STACK_LOCATION PtrCurrentStackLocation = NULL; 45 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 46 | BOOLEAN AcquiredExtension = FALSE; 47 | BOOLEAN CompleteIrp = FALSE; 48 | PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 49 | ULONG ReturnedInformation = FILE_OPENED; 50 | 51 | try { 52 | 53 | // Get the current I/O stack location. 54 | PtrCurrentStackLocation = IoGetCurrentIrpStackLocation(Irp); 55 | ASSERT(PtrCurrentStackLocation); 56 | 57 | // Get a pointer to the device extension that must exist for 58 | // all of the device objects created by the filter driver. 59 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(DeviceObject->DeviceExtension); 60 | SFilterAssertExtPtrValid(PtrDeviceExtension); 61 | 62 | // We really should not be here if our resource is not initialized? 63 | ASSERT(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 64 | 65 | // acquire the resource associated with particular device extension for 66 | // our target device object. 67 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 68 | AcquiredExtension = TRUE; 69 | 70 | // If the device extension is for a lower device forward the request. 71 | if ((PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_ATTACHED_DEVICE) 72 | && (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED)) { 73 | 74 | // Currently, this filter driver simply forwards the request. 75 | // However, you could do all sorts of stuff when you intercept a 76 | // create/open request. For example, if you wish, you could "massage" 77 | // the name and return reparse to the caller which would allow you 78 | // to essentially redirect create/open requests. 79 | 80 | if (AcquiredExtension) { 81 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 82 | AcquiredExtension = FALSE; 83 | } 84 | 85 | RC = SFilterDefaultDispatch(DeviceObject, Irp); 86 | try_return(RC); 87 | } else if (PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_FILTER_DEVICE) { 88 | // This request was targeted to us. Simply return success. 89 | // You may wish to ensure that an open/open-if type of request 90 | // was sent. You may also wish to ensure that the caller has 91 | // appropriate privileges. Currently, the filter driver does 92 | // not perform such checks. 93 | CompleteIrp = TRUE; 94 | try_return(RC); 95 | } 96 | 97 | // The filter driver does not particularly care to respond to these requests. 98 | CompleteIrp = TRUE; 99 | // does not matter what the Information field contains. 100 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 101 | 102 | try_exit: NOTHING; 103 | 104 | } finally { 105 | 106 | // Release any resources acquired. 107 | if (AcquiredExtension) { 108 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 109 | AcquiredExtension = FALSE; 110 | } 111 | 112 | // Complete the IRP only if we must. 113 | if (CompleteIrp) { 114 | Irp->IoStatus.Status = RC; 115 | Irp->IoStatus.Information = ReturnedInformation; 116 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 117 | } 118 | } 119 | 120 | return(RC); 121 | } 122 | 123 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/dispatch.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: dispatch.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Dispatch entry points. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfilter.h" 17 | 18 | /* define the file specific bug-check id */ 19 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_DISPATCH 20 | 21 | 22 | /************************************************************************* 23 | * 24 | * Function: SFilterDefaultDispatch() 25 | * 26 | * Description: 27 | * Simply forward the request to the device we are attached to. 28 | * Return INVALID_REQUEST if we are not attached to anything. 29 | * Before forwarding the request, set up a completion routine 30 | * that can be used to do interesting stuff (if so desired). 31 | * 32 | * Expected Interrupt Level (for execution) : 33 | * 34 | * Typically (though not guaranteed) @ IRQL_PASSIVE_LEVEL 35 | * 36 | * Return Value: STATUS_SUCCESS/Error 37 | * 38 | *************************************************************************/ 39 | NTSTATUS SFilterDefaultDispatch( 40 | PDEVICE_OBJECT DeviceObject, // Our device object 41 | PIRP Irp) // I/O Request Packet 42 | { 43 | NTSTATUS RC = STATUS_SUCCESS; 44 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 45 | PIO_STACK_LOCATION PtrCurrentStackLocation = NULL; 46 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 47 | BOOLEAN AcquiredExtension = FALSE; 48 | BOOLEAN CompleteIrp = FALSE; 49 | PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 50 | ULONG ReturnedInformation = 0; 51 | 52 | try { 53 | 54 | // Get the current I/O stack location. 55 | PtrCurrentStackLocation = IoGetCurrentIrpStackLocation(Irp); 56 | ASSERT(PtrCurrentStackLocation); 57 | 58 | // Get a pointer to the device extension that must exist for 59 | // all of the device objects created by the filter driver. 60 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(DeviceObject->DeviceExtension); 61 | SFilterAssertExtPtrValid(PtrDeviceExtension); 62 | 63 | // We really should not be here if our resource is not initialized? 64 | ASSERT(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 65 | 66 | // acquire the resource associated with particular device extension for 67 | // our target device object. 68 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 69 | AcquiredExtension = TRUE; 70 | 71 | // If the device extension is for a lower device forward the request. 72 | if ((PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_ATTACHED_DEVICE) 73 | && (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED)) { 74 | 75 | // Be careful about not screwing up badly. This is actually not recommended by the I/O Manager. 76 | if (Irp->CurrentLocation == 1) { 77 | // Bad!! Fudge the error code. Break if we can ... 78 | SFilterBreakPoint(); 79 | CompleteIrp = TRUE; 80 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 81 | } 82 | 83 | PtrNextIoStackLocation = IoGetNextIrpStackLocation(Irp); 84 | 85 | // So far, so good! Copy over the contents of the current stack 86 | // location into the next IRP stack location. Be careful about 87 | // how we do the copy. The following statement is convenient 88 | // but will end up screwing up any driver above us who has 89 | // set a completion routine! 90 | *PtrNextIoStackLocation = *PtrCurrentStackLocation; 91 | 92 | // We will specify a default completion routine. This will 93 | // prevent any completion routine being invoked twice 94 | // (set by a driver above us in the calling hierarchy) and also 95 | // allow us the opportunity to do whatever we like once the 96 | // function processing has been completed. 97 | // We will specify that our completion routine be invoked regardless 98 | // of how the IRP is completed/cancelled. 99 | IoSetCompletionRoutine(Irp, SFilterDefaultCompletion, PtrDeviceExtension, TRUE, TRUE, TRUE); 100 | 101 | // Forward the request. Note that if the target does not 102 | // wish to service the function, the request will get redirected 103 | // to IopInvalidDeviceRequest() (a routine that completes the 104 | // IRP with STATUS_INVALID_DEVICE_REQUEST). 105 | // However, we must release our resources before forwarding the 106 | // request. That will avoid the sort of problems discussed in 107 | // Chapter 12 of the text. 108 | 109 | PtrTargetDeviceObject = PtrDeviceExtension->TargetDeviceObject; 110 | 111 | // Increment the count of outstanding I/O requests. The count will 112 | // be decremented in the completion routine. 113 | // Acquire a special end-resource spin-lock to synchronize access. 114 | SFilterIncrementLargeInteger(PtrDeviceExtension->OutstandingIoRequests, 115 | (unsigned long)1, 116 | &(PtrDeviceExtension->IoRequestsSpinLock)); 117 | 118 | // Clear the fast-IO notification event protected by the resource 119 | // we have acquired. 120 | KeClearEvent(&(PtrDeviceExtension->IoInProgressEvent)); 121 | 122 | KdPrint(("SFilterDefaultDispatch(): Target Device Object = 0x%x, Major function = 0x%x, Minor Function = 0x%x\n", 123 | PtrTargetDeviceObject, PtrCurrentStackLocation->MajorFunction, PtrCurrentStackLocation->MinorFunction)); 124 | 125 | if (AcquiredExtension) { 126 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 127 | AcquiredExtension = FALSE; 128 | } 129 | 130 | RC = IoCallDriver(PtrTargetDeviceObject, Irp); 131 | 132 | // Note that at this time, the filter driver completion routine 133 | // does not return STATUS_MORE_PROCESSING_REQUIRED. However, if you 134 | // do modify this code and use it in your own filter driver and if your 135 | // completion routine *could* return the STATUS_MORE_PROCESSING_REQUIRED 136 | // return code, you must not blindly return the return-code obtained from 137 | // the call to IoCallDriver() above. See Chapter 12 for a discussion of 138 | // this issue. 139 | try_return(RC); 140 | } 141 | 142 | // The filter driver does not particularly care to respond to these requests. 143 | CompleteIrp = TRUE; 144 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 145 | 146 | try_exit: NOTHING; 147 | 148 | } finally { 149 | 150 | // Release any resources acquired. 151 | if (AcquiredExtension) { 152 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 153 | AcquiredExtension = FALSE; 154 | } 155 | 156 | // Complete the IRP only if we must. 157 | if (CompleteIrp) { 158 | Irp->IoStatus.Status = RC; 159 | Irp->IoStatus.Information = ReturnedInformation; 160 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 161 | } 162 | } 163 | 164 | return(RC); 165 | } 166 | 167 | 168 | 169 | /************************************************************************* 170 | * 171 | * Function: SFilterDefaultCompletion() 172 | * 173 | * Description: 174 | * Decrement the outstanding I/O count. Then let it go. Note that you 175 | * must always be aware that the completion routine could be invoked 176 | * at high IRQL and in the context of some arbitrary thread. 177 | * 178 | * Expected Interrupt Level (for execution) : 179 | * 180 | * Typically at high IRQL. Occasionally at IRQL PASSIVE_LEVEL 181 | * 182 | * Return Value: STATUS_SUCCESS/STATUS_MORE_PROCESSING_REQUIRED 183 | * 184 | *************************************************************************/ 185 | NTSTATUS SFilterDefaultCompletion( 186 | PDEVICE_OBJECT PtrDeviceObject, 187 | PIRP PtrIrp, 188 | void *Context) 189 | { 190 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 191 | BOOLEAN CanDetachProceed = FALSE; 192 | PDEVICE_OBJECT PtrAssociatedDeviceObject = NULL; 193 | 194 | // acquire the device extension resource exclusively. 195 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(Context); 196 | ASSERT(PtrDeviceExtension); 197 | 198 | if (PtrIrp->PendingReturned) { 199 | IoMarkIrpPending(PtrIrp); 200 | } 201 | 202 | PtrAssociatedDeviceObject = PtrDeviceExtension->PtrAssociatedDeviceObject; 203 | 204 | // Ensure that this is a valid device object pointer, else return 205 | // immediately. 206 | if (PtrAssociatedDeviceObject != PtrDeviceObject) { 207 | // Bug exposed; see Chapter 12 for details. 208 | return(STATUS_SUCCESS); 209 | } 210 | 211 | // Note that you could do all sorts of processing at this point 212 | // depending upon the results of the operation. Be careful though 213 | // about what you chose to do, about the fact that this completion 214 | // routine is being invoked in an arbitrary thread context and probably 215 | // at high IRQL. 216 | 217 | SFilterDecrementLargeInteger(PtrDeviceExtension->OutstandingIoRequests, 218 | (unsigned long)1, 219 | &(PtrDeviceExtension->IoRequestsSpinLock)); 220 | 221 | // If the outstanding count is 0, signal the appropriate event which will 222 | // allow any pending detach to proceed. 223 | SFilterIsLargeIntegerZero(CanDetachProceed, PtrDeviceExtension->OutstandingIoRequests, 224 | &(PtrDeviceExtension->IoRequestsSpinLock)); 225 | 226 | if (CanDetachProceed) { 227 | // signal the event object. Note that this is simply an 228 | // advisory check we do here (to wake up a sleeping thread). 229 | // It is the responsibility of the thread performing the detach to 230 | // ensure that no operations are truly in progress. 231 | KeSetEvent(&(PtrDeviceExtension->IoInProgressEvent), IO_NO_INCREMENT, FALSE); 232 | } 233 | 234 | // Although the success return value is hard-coded here, you can 235 | // return an appropriate value (either success or more-processing-reqd) 236 | // based upon what it is that you wish to do in your completion routine. 237 | return(STATUS_SUCCESS); 238 | } 239 | 240 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/fsctrl.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: fsctrl.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * File System Control Requests entry point. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfilter.h" 17 | 18 | /* define the file specific bug-check id */ 19 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_FSCTRL 20 | 21 | 22 | /************************************************************************* 23 | * 24 | * Function: SFilterFSControl() 25 | * 26 | * Description: 27 | * Intercept the fsctrl request targeted to the FSD. If you wish to 28 | * have a user-space application (or kernel-mode driver) communicate 29 | * with the filter driver, this is where your FSCTL requests would also 30 | * end up. 31 | * 32 | * Expected Interrupt Level (for execution) : 33 | * 34 | * Typically (though not guaranteed) @ IRQL_PASSIVE_LEVEL 35 | * 36 | * Return Value: STATUS_SUCCESS/Error 37 | * 38 | *************************************************************************/ 39 | NTSTATUS SFilterFSControl( 40 | PDEVICE_OBJECT DeviceObject, // Our device object 41 | PIRP Irp) // I/O Request Packet 42 | { 43 | NTSTATUS RC = STATUS_SUCCESS; 44 | PIO_STACK_LOCATION PtrNextIoStackLocation = NULL; 45 | PIO_STACK_LOCATION PtrCurrentStackLocation = NULL; 46 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 47 | BOOLEAN AcquiredExtension = FALSE; 48 | BOOLEAN CompleteIrp = FALSE; 49 | PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 50 | ULONG ReturnedInformation = 0; 51 | PtrSFilterMountCompletion PtrMountCompletion = NULL; 52 | 53 | try { 54 | 55 | // Get the current I/O stack location. 56 | PtrCurrentStackLocation = IoGetCurrentIrpStackLocation(Irp); 57 | ASSERT(PtrCurrentStackLocation); 58 | 59 | // Get a pointer to the device extension that must exist for 60 | // all of the device objects created by the filter driver. 61 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(DeviceObject->DeviceExtension); 62 | SFilterAssertExtPtrValid(PtrDeviceExtension); 63 | 64 | // We really should not be here if our resource is not initialized? 65 | ASSERT(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 66 | 67 | // acquire the resource associated with particular device extension for 68 | // our target device object. 69 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 70 | AcquiredExtension = TRUE; 71 | 72 | // If the device extension is for a lower device forward the request. 73 | if ((PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_ATTACHED_DEVICE) 74 | && (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED)) { 75 | 76 | // If we wish to intercept the mount volume, we would definitely like to 77 | // set a different completion routine. Here is the tedious way 78 | // of doing this (you could modify the common dispatch routine to 79 | // do the same). 80 | if (PtrCurrentStackLocation->MinorFunction != IRP_MN_MOUNT_VOLUME) { 81 | if (AcquiredExtension) { 82 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 83 | AcquiredExtension = FALSE; 84 | } 85 | 86 | // Note that a load FSD request could be being issued to a FS recognizer. 87 | // If you wish, you can monitor such requests and detach yourself from 88 | // the recognizer once the FSD has been loaded. That would allow the 89 | // recognizer to be unloaded. 90 | // This filter does not implement this behavior, however. 91 | 92 | RC = SFilterDefaultDispatch(DeviceObject, Irp); 93 | try_return(RC); 94 | } else { 95 | 96 | // Mount request issued. 97 | KdPrint(("SFilterFSControl(): Mount request intercepted. Target FSD = 0x%x\n", 98 | PtrDeviceExtension->TargetDriverObject)); 99 | 100 | // Be careful about not screwing up badly. This is actually not recommended by the I/O Manager. 101 | if (Irp->CurrentLocation == 1) { 102 | // Bad!! Fudge the error code. Break if we can ... 103 | SFilterBreakPoint(); 104 | CompleteIrp = TRUE; 105 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 106 | } 107 | 108 | PtrNextIoStackLocation = IoGetNextIrpStackLocation(Irp); 109 | 110 | // So far, so good! Copy over the contents of the current stack 111 | // location into the next IRP stack location. Be careful about 112 | // how we do the copy. The following statement is convenient 113 | // but will end up screwing up any driver above us who has 114 | // set a completion routine! 115 | *PtrNextIoStackLocation = *PtrCurrentStackLocation; 116 | 117 | // We need to allocate memory for the context structure. The information 118 | // that we will pass on to the mount completion routine must contain 119 | // the following: 120 | // (a) A pointer to the device extension 121 | // (b) A pointer to the VPB structure that we can currently access 122 | // in the current I/O stack location. 123 | // (c) A work queue item that can be used to post the attach request 124 | // if the mount is successfull. 125 | // The structure will be freed once the post-processing is completed. 126 | PtrMountCompletion = (PtrSFilterMountCompletion)ExAllocatePool(NonPagedPool, sizeof(SFilterMountCompletion)); 127 | if (!PtrMountCompletion) { 128 | CompleteIrp = TRUE; 129 | try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 130 | } 131 | RtlZeroMemory(PtrMountCompletion, sizeof(SFilterMountCompletion)); 132 | PtrMountCompletion->NodeIdentifier.NodeType = SFILTER_NODE_TYPE_MOUNT_COMPLETION; 133 | PtrMountCompletion->NodeIdentifier.NodeSize = sizeof(SFilterMountCompletion); 134 | PtrMountCompletion->PtrOriginalIrp = Irp; 135 | // We will store a pointer to the "real" device object. We can use the 136 | // VPB associated with the real device object once the mount operation 137 | // has completed. This *may* be the same VPB structure as the one passed in 138 | // by the I/O Manager to the FSD. However, it is possible that a "remount" 139 | // operation will be performed by the FSD in which case the FSD will replace 140 | // the VPB pointer passed-in by the I/O Manager with the "old" VPB pointer 141 | // that was already associated with the "real device object". 142 | // Bottom line is that we do not really know the "VPB" pointer until the 143 | // the FSD has processed the mount request (note that if this is NOT a 144 | // remount, the FSD will make the real device VPB pointer be the VPB pointer 145 | // passed in by the I/O Manager). 146 | PtrMountCompletion->PtrDeviceObject = PtrCurrentStackLocation->Parameters.MountVolume.Vpb->RealDevice; 147 | 148 | PtrMountCompletion->PtrDeviceExtension = PtrDeviceExtension; 149 | // might as well initialize the work item now ... 150 | ExInitializeWorkItem(&(PtrMountCompletion->WorkItem), SFilterMountAttach, PtrMountCompletion); 151 | 152 | // We will specify a default completion routine. This will 153 | // prevent any completion routine being invoked twice 154 | // (set by a driver above us in the calling hierarchy) and also 155 | // allow us the opportunity to do whatever we like once the 156 | // function processing has been completed. 157 | // We will specify that our completion routine be invoked regardless 158 | // of how the IRP is completed/cancelled. 159 | IoSetCompletionRoutine(Irp, SFilterMountVolumeCompletion, PtrMountCompletion, TRUE, TRUE, TRUE); 160 | 161 | // Forward the request. Note that if the target does not 162 | // wish to service the function, the request will get redirected 163 | // to IopInvalidDeviceRequest() (a routine that completes the 164 | // IRP with STATUS_INVALID_DEVICE_REQUEST). 165 | // However, we must release our resources before forwarding the 166 | // request. That will avoid the sort of problems discussed in 167 | // Chapter 12 of the text. 168 | 169 | PtrTargetDeviceObject = PtrDeviceExtension->TargetDeviceObject; 170 | 171 | // Increment the count of outstanding I/O requests. The count will 172 | // be decremented in the completion routine. 173 | // Acquire a special end-resource spin-lock to synchronize access. 174 | SFilterIncrementLargeInteger(PtrDeviceExtension->OutstandingIoRequests, 175 | (unsigned long)1, 176 | &(PtrDeviceExtension->IoRequestsSpinLock)); 177 | 178 | // Clear the fast-IO notification event protected by the resource 179 | // we have acquired. 180 | KeClearEvent(&(PtrDeviceExtension->IoInProgressEvent)); 181 | 182 | if (AcquiredExtension) { 183 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 184 | AcquiredExtension = FALSE; 185 | } 186 | 187 | // Note that we will mark the IRP Pending and will return 188 | // STATUS_MORE_PROCESSING_REQUIRED later in the completion 189 | // routine. 190 | 191 | IoMarkIrpPending(Irp); 192 | 193 | RC = IoCallDriver(PtrTargetDeviceObject, Irp); 194 | 195 | KdPrint(("SFilterFSControl(): Mount request intercepted. Target FSD Returned = 0x%x\n", RC)); 196 | 197 | try_return(RC = STATUS_PENDING); 198 | } 199 | } else if (PtrDeviceExtension->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_FILTER_DEVICE) { 200 | // This request was targeted to us. You may allow such requests 201 | // if you expect other drivers/applications created/developed by 202 | // you or others to be able to issue IOCTL requests to your driver. 203 | // Currently, I expect no such thing. 204 | CompleteIrp = TRUE; 205 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 206 | } 207 | 208 | // The filter driver does not particularly care to respond to these requests. 209 | CompleteIrp = TRUE; 210 | // does not matter what the Information field contains. 211 | try_return(RC = STATUS_INVALID_DEVICE_REQUEST); 212 | 213 | try_exit: NOTHING; 214 | 215 | } finally { 216 | 217 | // Release any resources acquired. 218 | if (AcquiredExtension) { 219 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 220 | AcquiredExtension = FALSE; 221 | } 222 | 223 | // Complete the IRP only if we must. 224 | if (CompleteIrp) { 225 | Irp->IoStatus.Status = RC; 226 | Irp->IoStatus.Information = ReturnedInformation; 227 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 228 | } 229 | } 230 | 231 | return(RC); 232 | } 233 | 234 | /************************************************************************* 235 | * 236 | * Function: SFilterMountVolumeCompletion() 237 | * 238 | * Description: 239 | * Return STATUS_MORE_PROCESSING_REQUIRED if the request 240 | * was successfull (mount happened). Else, let it go. 241 | * 242 | * Expected Interrupt Level (for execution) : 243 | * 244 | * Typically at high IRQL. Occasionally at IRQL PASSIVE_LEVEL 245 | * 246 | * Return Value: STATUS_SUCCESS/STATUS_MORE_PROCESSING_REQUIRED 247 | * 248 | *************************************************************************/ 249 | NTSTATUS SFilterMountVolumeCompletion( 250 | PDEVICE_OBJECT PtrDeviceObject, 251 | PIRP PtrIrp, 252 | void *Context) 253 | { 254 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 255 | BOOLEAN CanDetachProceed = FALSE; 256 | PDEVICE_OBJECT PtrAssociatedDeviceObject = NULL; 257 | PtrSFilterMountCompletion PtrMountCompletion = NULL; 258 | 259 | PtrMountCompletion = (PtrSFilterMountCompletion)(Context); 260 | ASSERT(PtrMountCompletion); 261 | ASSERT(PtrMountCompletion->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_MOUNT_COMPLETION); 262 | ASSERT(PtrMountCompletion->NodeIdentifier.NodeSize = sizeof(SFilterMountCompletion)); 263 | 264 | PtrDeviceExtension = PtrMountCompletion->PtrDeviceExtension; 265 | ASSERT(PtrDeviceExtension); 266 | 267 | if (PtrIrp->PendingReturned) { 268 | IoMarkIrpPending(PtrIrp); 269 | } 270 | 271 | // Get a pointer to the VPB that is the "real" VPB (whether a fresh mount 272 | // was performed or whether a real mount happened). 273 | PtrMountCompletion->PtrVPB = PtrMountCompletion->PtrDeviceObject->Vpb; 274 | 275 | PtrAssociatedDeviceObject = PtrDeviceExtension->PtrAssociatedDeviceObject; 276 | 277 | // Ensure that this is a valid device object pointer, else return 278 | // immediately. 279 | if (PtrAssociatedDeviceObject != PtrDeviceObject) { 280 | // Bug exposed; see Chapter 12 for details. 281 | return(STATUS_SUCCESS); 282 | } 283 | 284 | if (NT_SUCCESS(PtrIrp->IoStatus.Status)) { 285 | // Mount succeeded. We will process the remainder asynchronously 286 | // and will therefore return STATUS_MORE_PROCESSING_REQUIRED. 287 | 288 | // post the request and return. 289 | ExQueueWorkItem(&(PtrMountCompletion->WorkItem), CriticalWorkQueue); 290 | 291 | return(STATUS_MORE_PROCESSING_REQUIRED); 292 | } else { 293 | // who cares; could be that a FSD will be loaded later? 294 | SFilterDecrementLargeInteger(PtrDeviceExtension->OutstandingIoRequests, 295 | (unsigned long)1, 296 | &(PtrDeviceExtension->IoRequestsSpinLock)); 297 | 298 | // If the outstanding count is 0, signal the appropriate event which will 299 | // allow any pending detach to proceed. 300 | SFilterIsLargeIntegerZero(CanDetachProceed, PtrDeviceExtension->OutstandingIoRequests, 301 | &(PtrDeviceExtension->IoRequestsSpinLock)); 302 | 303 | if (CanDetachProceed) { 304 | // signal the event object. Note that this is simply an 305 | // advisory check we do here (to wake up a sleeping thread). 306 | // It is the responsibility of the thread performing the detach to 307 | // ensure that no operations are truly in progress. 308 | KeSetEvent(&(PtrDeviceExtension->IoInProgressEvent), IO_NO_INCREMENT, FALSE); 309 | } 310 | 311 | // free up the memory for the mount completion structure 312 | ExFreePool((void *)PtrMountCompletion); 313 | 314 | return(STATUS_SUCCESS); 315 | } 316 | } 317 | 318 | 319 | /************************************************************************* 320 | * 321 | * Function: SFilterMountAttach() 322 | * 323 | * Description: 324 | * Attach to the newly created device object representing the 325 | * mounted logical volume. Then complete the original IRP. 326 | * 327 | * Expected Interrupt Level (for execution) : 328 | * 329 | * At IRQL PASSIVE_LEVEL 330 | * 331 | * Return Value: None. 332 | * 333 | *************************************************************************/ 334 | void SFilterMountAttach( 335 | void *Context) 336 | { 337 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 338 | PtrSFilterDeviceExtension PtrNewDeviceExtension = NULL; 339 | BOOLEAN CanDetachProceed = FALSE; 340 | PDEVICE_OBJECT PtrTargetVolumeDeviceObject = NULL; 341 | PDEVICE_OBJECT PtrNewDeviceObject = NULL; 342 | PtrSFilterMountCompletion PtrMountCompletion = NULL; 343 | NTSTATUS RC = STATUS_SUCCESS; 344 | 345 | SFilterBreakPoint(); 346 | 347 | PtrMountCompletion = (PtrSFilterMountCompletion)(Context); 348 | ASSERT(PtrMountCompletion); 349 | ASSERT(PtrMountCompletion->NodeIdentifier.NodeType == SFILTER_NODE_TYPE_MOUNT_COMPLETION); 350 | ASSERT(PtrMountCompletion->NodeIdentifier.NodeSize = sizeof(SFilterMountCompletion)); 351 | 352 | // Get a pointer to the target device object. 353 | PtrTargetVolumeDeviceObject = PtrMountCompletion->PtrVPB->DeviceObject; 354 | 355 | PtrDeviceExtension = PtrMountCompletion->PtrDeviceExtension; 356 | ASSERT(PtrDeviceExtension); 357 | 358 | // issue the attach request to the target device object. 359 | RC = SFilterAttachTarget(PtrTargetVolumeDeviceObject, &PtrNewDeviceObject); 360 | 361 | KdPrint(("SFilterFSDNotification(): Result of attaching to device object 0x%x is 0x%x\n", 362 | PtrTargetVolumeDeviceObject, RC)); 363 | 364 | // if we succeeded, remove the "attached-to-fsd" flag (sorry for the hack) 365 | if (NT_SUCCESS(RC)) { 366 | ASSERT(PtrNewDeviceObject); 367 | 368 | PtrNewDeviceExtension = (PtrSFilterDeviceExtension)(PtrNewDeviceObject->DeviceExtension); 369 | 370 | SFilterClearFlag(PtrNewDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_ATTACHED_FSD); 371 | } 372 | 373 | // we are free to detach now ?? 374 | SFilterDecrementLargeInteger(PtrDeviceExtension->OutstandingIoRequests, 375 | (unsigned long)1, 376 | &(PtrDeviceExtension->IoRequestsSpinLock)); 377 | 378 | // If the outstanding count is 0, signal the appropriate event which will 379 | // allow any pending detach to proceed. 380 | SFilterIsLargeIntegerZero(CanDetachProceed, PtrDeviceExtension->OutstandingIoRequests, 381 | &(PtrDeviceExtension->IoRequestsSpinLock)); 382 | 383 | if (CanDetachProceed) { 384 | // signal the event object. Note that this is simply an 385 | // advisory check we do here (to wake up a sleeping thread). 386 | // It is the responsibility of the thread performing the detach to 387 | // ensure that no operations are truly in progress. 388 | KeSetEvent(&(PtrDeviceExtension->IoInProgressEvent), IO_NO_INCREMENT, FALSE); 389 | } 390 | 391 | IoCompleteRequest(PtrMountCompletion->PtrOriginalIrp, IO_NO_INCREMENT); 392 | 393 | // free up the memory for the mount completion structure 394 | ExFreePool((void *)PtrMountCompletion); 395 | 396 | return; 397 | } 398 | 399 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/misc.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: misc.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * Contains miscelleneous functions. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #include "sfilter.h" 17 | 18 | /* define the file specific bug-check id */ 19 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_MISC 20 | 21 | 22 | 23 | /************************************************************************* 24 | * 25 | * Function: SFilterInitDevExtension() 26 | * 27 | * Description: 28 | * Performs some rudimentary work to initialize the device extension 29 | * presumably for a newly created device object. 30 | * 31 | * Expected Interrupt Level (for execution) : 32 | * 33 | * IRQL_PASSIVE_LEVEL 34 | * 35 | * Return Value: None. 36 | * 37 | *************************************************************************/ 38 | void SFilterInitDevExtension( 39 | PtrSFilterDeviceExtension PtrDeviceExtension, 40 | PDEVICE_OBJECT PtrAssociatedDeviceObject, 41 | uint32 NodeType) 42 | { 43 | RtlZeroMemory(PtrDeviceExtension, sizeof(SFilterDeviceExtension)); 44 | 45 | PtrDeviceExtension->NodeIdentifier.NodeType = NodeType; 46 | PtrDeviceExtension->NodeIdentifier.NodeSize = sizeof(SFilterDeviceExtension); 47 | 48 | PtrDeviceExtension->PtrAssociatedDeviceObject = PtrAssociatedDeviceObject; 49 | 50 | ExInitializeResourceLite(&(PtrDeviceExtension->DeviceExtensionResource)); 51 | // Set a flag indicating that the resource has been initialized. 52 | SFilterSetFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 53 | 54 | try { 55 | ExAcquireResourceExclusiveLite(&(SFilterGlobalData.GlobalDataResource), TRUE); 56 | // Insert the object into the global list. 57 | InsertTailList(&(SFilterGlobalData.NextDeviceObject), &(PtrDeviceExtension->NextDeviceObject)); 58 | // Mark the fact that the device object has been inserted. 59 | SFilterSetFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_INSERTED_GLOBAL_LIST); 60 | } finally { 61 | SFilterReleaseResource(&(SFilterGlobalData.GlobalDataResource)); 62 | } 63 | 64 | // Initialize the Executive spin lock for this device extension. 65 | KeInitializeSpinLock(&(PtrDeviceExtension->IoRequestsSpinLock)); 66 | 67 | // Initialize the event object used to denote I/O in progress. 68 | // When set, the event signals that no I/O is currently in progress 69 | // excluding (currently) fast-IO operations. 70 | // Event is cleared in a safe fashion (protected by the resource 71 | // initialized above) BUT is set in an unsafe fashion. Therefore, the 72 | // waiting thread is responsible for rechecking that the condition 73 | // is still true (after acquiring the resource) once it has been awoken. 74 | KeInitializeEvent(&(PtrDeviceExtension->IoInProgressEvent), NotificationEvent, FALSE); 75 | 76 | return; 77 | } 78 | 79 | 80 | /************************************************************************* 81 | * 82 | * Function: SFilterDeleteDevExtension() 83 | * 84 | * Description: 85 | * Performs some rudimentary work to uninitialize the device extension 86 | * for an object presumably being deleted. 87 | * 88 | * Expected Interrupt Level (for execution) : 89 | * 90 | * IRQL_PASSIVE_LEVEL 91 | * 92 | * Return Value: None. 93 | * 94 | *************************************************************************/ 95 | void SFilterDeleteDevExtension( 96 | PtrSFilterDeviceExtension PtrDeviceExtension, 97 | BOOLEAN ResourceAcquired) 98 | { 99 | 100 | // If the caller did not invoke this routine with the device extension 101 | // resource acquired, we will acquire it here. 102 | if (!ResourceAcquired && (PtrDeviceExtension->DeviceExtensionFlags & 103 | SFILTER_DEV_EXT_RESOURCE_INITIALIZED)) { 104 | ExAcquireResourceExclusiveLite(&(PtrDeviceExtension->DeviceExtensionResource), TRUE); 105 | ResourceAcquired = TRUE; 106 | } 107 | 108 | // assert that the device object associated with the 109 | // extension to be deleted is not attached to anything. 110 | ASSERT(!(PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_ATTACHED)); 111 | 112 | // Remove the device extension from the global list. 113 | try { 114 | ExAcquireResourceExclusiveLite(&(SFilterGlobalData.GlobalDataResource), TRUE); 115 | if (PtrDeviceExtension->DeviceExtensionFlags & SFILTER_DEV_EXT_INSERTED_GLOBAL_LIST) { 116 | RemoveEntryList(&(PtrDeviceExtension->NextDeviceObject)); 117 | SFilterClearFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_INSERTED_GLOBAL_LIST); 118 | } 119 | } finally { 120 | SFilterReleaseResource(&(SFilterGlobalData.GlobalDataResource)); 121 | } 122 | 123 | if (ResourceAcquired) { 124 | SFilterReleaseResource(&(PtrDeviceExtension->DeviceExtensionResource)); 125 | } 126 | 127 | PtrDeviceExtension->NodeIdentifier.NodeType = 0; 128 | PtrDeviceExtension->NodeIdentifier.NodeSize = 0; 129 | 130 | // Uninitialize the resource. 131 | ExDeleteResourceLite(&(PtrDeviceExtension->DeviceExtensionResource)); 132 | SFilterClearFlag(PtrDeviceExtension->DeviceExtensionFlags, SFILTER_DEV_EXT_RESOURCE_INITIALIZED); 133 | 134 | return; 135 | } 136 | 137 | 138 | 139 | 140 | /************************************************************************* 141 | * 142 | * Function: SFilterCreateDirectory() 143 | * 144 | * Description: 145 | * Create a directory in the object name space. Make the directory 146 | * a temporary object if requested by the caller. 147 | * 148 | * Expected Interrupt Level (for execution) : 149 | * 150 | * IRQL_PASSIVE_LEVEL 151 | * 152 | * Return Value: STATUS_SUCCESS/an appropriate error 153 | * 154 | *************************************************************************/ 155 | NTSTATUS SFilterCreateDirectory( 156 | PWCHAR DirectoryNameStr, 157 | PHANDLE PtrReturnedHandle, 158 | BOOLEAN MakeTemporaryObject) 159 | { 160 | NTSTATUS RC = STATUS_SUCCESS; 161 | UNICODE_STRING DirectoryName; 162 | OBJECT_ATTRIBUTES DirectoryAttributes; 163 | 164 | try { 165 | // Create a Unicode string. 166 | RtlInitUnicodeString(&DirectoryName, DirectoryNameStr); 167 | 168 | // Create an object attributes structure. 169 | InitializeObjectAttributes(&DirectoryAttributes, 170 | &DirectoryName, OBJ_PERMANENT, 171 | NULL, NULL); 172 | 173 | // The following call will fail if we do not have appropriate privileges. 174 | if (!NT_SUCCESS(RC = ZwCreateDirectoryObject(PtrReturnedHandle, 175 | DIRECTORY_ALL_ACCESS, 176 | &DirectoryAttributes))) { 177 | try_return(RC); 178 | } 179 | 180 | // Make the named directory object a temporary object. 181 | ZwMakeTemporaryObject(PtrReturnedHandle); 182 | 183 | try_exit: NOTHING; 184 | 185 | } finally { 186 | NOTHING; 187 | } 188 | 189 | return(RC); 190 | } 191 | 192 | 193 | /************************************************************************* 194 | * 195 | * Function: SFilterReinitialize() 196 | * 197 | * Description: 198 | * You can read the registry if you like at this time, or do anything else 199 | * that could not be done because the filter loads at system boot time. 200 | * 201 | * Expected Interrupt Level (for execution) : 202 | * 203 | * IRQL_PASSIVE_LEVEL 204 | * 205 | * Return Value: None 206 | * 207 | *************************************************************************/ 208 | void SFilterReinitialize( 209 | PDRIVER_OBJECT DriverObject, // representing the filter driver 210 | void *Context, // this filter driver supplies registry path 211 | ULONG Count) // # times this function invoked 212 | { 213 | PUNICODE_STRING RegistryPath = NULL; 214 | 215 | // Currently, this function does not do anything 216 | // (except break into a debugger if appropriate). You could, however, 217 | // modify this function to suit your purposes (e.g. read the registry 218 | // contents for user-configurable parameters) 219 | 220 | // Note that you can specify a reinitialization routine from within this 221 | // routine to keep getting invoked whenever a new driver gets loaded. 222 | // In this manner, you can check for known FSDs that load in versions 223 | // previous to version 4.0 224 | 225 | RegistryPath = (PUNICODE_STRING)(Context); 226 | 227 | return; 228 | } 229 | 230 | 231 | /************************************************************************* 232 | * 233 | * Function: SFilterFSDNotification 234 | * 235 | * Description: 236 | * This function is invoked by the I/O Manager in version 4.0+ of the 237 | * OS whenever a FSD registers or unregisters itself. 238 | * This function could also be invoked internally by the filter driver 239 | * from the reinitialization function for versions prior to 4.0. 240 | * Currently, the filter driver will attach itself to the target device 241 | * object when the function is invoked. 242 | * 243 | * Expected Interrupt Level (for execution) : 244 | * 245 | * IRQL_PASSIVE_LEVEL (in the context of a system worker thread) 246 | * 247 | * Return Value: None 248 | * 249 | *************************************************************************/ 250 | void SFilterFSDNotification( 251 | PDEVICE_OBJECT PtrTargetFileSystemDeviceObject, 252 | BOOLEAN DriverActive) 253 | { 254 | NTSTATUS RC = STATUS_SUCCESS; 255 | PDEVICE_OBJECT PtrNewDeviceObject = NULL; 256 | 257 | if (DriverActive) { 258 | // Create a new device object and attach to the supplied device object. 259 | // Then, we will intercept all requests to the FSD including (but not 260 | // limited to) mount requests. Therefore, we will be able to attach to 261 | // device objects created on-the-fly by the FSD representing instances 262 | // of mounted logical volumes. 263 | 264 | RC = SFilterAttachTarget(PtrTargetFileSystemDeviceObject, &PtrNewDeviceObject); 265 | 266 | KdPrint(("SFilterFSDNotification(): Result of attaching to device object 0x%x is 0x%x\n", 267 | PtrTargetFileSystemDeviceObject, RC)); 268 | } else { 269 | // Nothing much to do here. Remember that it will be a rare FSD indeed 270 | // that is unloadable (though you can run into problems in versions 3.51 271 | // and before if the FSD indeed tries to unload itself). 272 | // You may wish to add code here that traverses the filter driver's linked 273 | // list of device objects attached to FSDs and delete the appropriate 274 | // (attached) device object. 275 | NOTHING; 276 | } 277 | 278 | return; 279 | } 280 | 281 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/obj/_objects.mac: -------------------------------------------------------------------------------- 1 | ALPHA_OBJECTS= \ 2 | $(_OBJ_DIR)\alpha\sfilter.res \ 3 | $(_OBJ_DIR)\alpha\sfilinit.obj \ 4 | $(_OBJ_DIR)\alpha\fastio.obj \ 5 | $(_OBJ_DIR)\alpha\misc.obj \ 6 | $(_OBJ_DIR)\alpha\attach.obj \ 7 | $(_OBJ_DIR)\alpha\dispatch.obj \ 8 | $(_OBJ_DIR)\alpha\create.obj \ 9 | $(_OBJ_DIR)\alpha\fsctrl.obj \ 10 | $(_OBJ_DIR)\alpha\close.obj 11 | 12 | PASS0_ALPHA_OBJECTS= 13 | 14 | MIPS_OBJECTS= \ 15 | $(_OBJ_DIR)\mips\sfilter.res \ 16 | $(_OBJ_DIR)\mips\sfilinit.obj \ 17 | $(_OBJ_DIR)\mips\fastio.obj \ 18 | $(_OBJ_DIR)\mips\misc.obj \ 19 | $(_OBJ_DIR)\mips\attach.obj \ 20 | $(_OBJ_DIR)\mips\dispatch.obj \ 21 | $(_OBJ_DIR)\mips\create.obj \ 22 | $(_OBJ_DIR)\mips\fsctrl.obj \ 23 | $(_OBJ_DIR)\mips\close.obj 24 | 25 | PASS0_MIPS_OBJECTS= 26 | 27 | 386_OBJECTS= \ 28 | $(_OBJ_DIR)\i386\sfilter.res \ 29 | $(_OBJ_DIR)\i386\sfilinit.obj \ 30 | $(_OBJ_DIR)\i386\fastio.obj \ 31 | $(_OBJ_DIR)\i386\misc.obj \ 32 | $(_OBJ_DIR)\i386\attach.obj \ 33 | $(_OBJ_DIR)\i386\dispatch.obj \ 34 | $(_OBJ_DIR)\i386\create.obj \ 35 | $(_OBJ_DIR)\i386\fsctrl.obj \ 36 | $(_OBJ_DIR)\i386\close.obj 37 | 38 | PASS0_386_OBJECTS= 39 | 40 | PPC_OBJECTS= \ 41 | $(_OBJ_DIR)\ppc\sfilter.res \ 42 | $(_OBJ_DIR)\ppc\sfilinit.obj \ 43 | $(_OBJ_DIR)\ppc\fastio.obj \ 44 | $(_OBJ_DIR)\ppc\misc.obj \ 45 | $(_OBJ_DIR)\ppc\attach.obj \ 46 | $(_OBJ_DIR)\ppc\dispatch.obj \ 47 | $(_OBJ_DIR)\ppc\create.obj \ 48 | $(_OBJ_DIR)\ppc\fsctrl.obj \ 49 | $(_OBJ_DIR)\ppc\close.obj 50 | 51 | PASS0_PPC_OBJECTS= 52 | 53 | -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/obj/i386/checked/sfilter.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filter-high/src/obj/i386/checked/sfilter.sys -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/obj/i386/free/sfilter.dbg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filter-high/src/obj/i386/free/sfilter.dbg -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/obj/i386/free/sfilter.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/filter-high/src/obj/i386/free/sfilter.sys -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/sfilinit.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfilinit.c 4 | * 5 | * Module: Sample Filter Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * This file contains the initialization code for the kernel mode 9 | * Sample Filter module. The DriverEntry() routine is called by the I/O 10 | * sub-system to initialize the filter driver. The filter driver is 11 | * designed to layer over FSD device objects. 12 | * 13 | * Author: R. Nagar 14 | * 15 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 16 | * 17 | *************************************************************************/ 18 | 19 | // Common include file 20 | #include "sfilter.h" 21 | 22 | // Define the file-specific bug-check id 23 | #define SFILTER_BUG_CHECK_ID SFILTER_FILE_INIT 24 | 25 | // Global variables are declared here (minimize these) 26 | SFilterData SFilterGlobalData; 27 | 28 | 29 | /************************************************************************* 30 | * 31 | * Function: DriverEntry() 32 | * 33 | * Description: 34 | * This routine is the standard entry point for most kernel mode drivers. 35 | * The routine is invoked at IRQL PASSIVE_LEVEL in the context of a 36 | * system worker thread. 37 | * All Filter driver specific data structures etc. are initialized here. 38 | * 39 | * Expected Interrupt Level (for execution) : 40 | * 41 | * IRQL_PASSIVE_LEVEL 42 | * 43 | * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded). 44 | * 45 | *************************************************************************/ 46 | NTSTATUS DriverEntry( 47 | PDRIVER_OBJECT DriverObject, // created by the I/O sub-system 48 | PUNICODE_STRING RegistryPath) // path to the registry key 49 | { 50 | NTSTATUS RC = STATUS_SUCCESS; 51 | BOOLEAN RegisteredShutdown = FALSE; 52 | PtrSFilterDeviceExtension PtrDeviceExtension = NULL; 53 | 54 | UNICODE_STRING UserVisibleName; 55 | UNICODE_STRING DriverDeviceName; 56 | 57 | // Allows us to break into the filter driver (if required) at 58 | // driver initialization (only with the debug/checked build). 59 | SFilterBreakPoint(); 60 | 61 | try { 62 | try { 63 | // initialize the global data structure 64 | RtlZeroMemory(&SFilterGlobalData, sizeof(SFilterGlobalData)); 65 | 66 | // initialize some required fields 67 | SFilterGlobalData.NodeIdentifier.NodeType = SFILTER_NODE_TYPE_GLOBAL_DATA; 68 | SFilterGlobalData.NodeIdentifier.NodeSize = sizeof(SFilterGlobalData); 69 | 70 | // initialize the global data resource and remember the fact that 71 | // the resource has been initialized 72 | RC = ExInitializeResourceLite(&(SFilterGlobalData.GlobalDataResource)); 73 | ASSERT(NT_SUCCESS(RC)); 74 | SFilterSetFlag(SFilterGlobalData.SFilterFlags, SFILTER_DATA_FLAGS_RESOURCE_INITIALIZED); 75 | 76 | // keep a ptr to the driver object sent to us by the I/O Mgr 77 | SFilterGlobalData.SFilterDriverObject = DriverObject; 78 | 79 | // initialize the layered device object list head 80 | InitializeListHead(&(SFilterGlobalData.NextDeviceObject)); 81 | 82 | // initialize the IRP major function table, and the fast I/O table 83 | SFilterInitializeFunctionPointers(DriverObject); 84 | 85 | // It would be nice to create directories in which to create 86 | // named (temporary) filter driver objects. 87 | 88 | // Start with a directory in the NT Object Name Space. 89 | if (!NT_SUCCESS(RC = SFilterCreateDirectory(SFILTER_DRV_DIR, 90 | &(SFilterGlobalData.DirectoryHandle), 91 | TRUE))) { 92 | SFilterBreakPoint(); 93 | try_return(RC); 94 | } 95 | 96 | // Now create a directory in the DOS (Win32) visible name space. 97 | if (!NT_SUCCESS(RC = SFilterCreateDirectory(SFILTER_DOS_DRV_DIR, 98 | &(SFilterGlobalData.DosDirectoryHandle), 99 | TRUE))) { 100 | SFilterBreakPoint(); 101 | try_return(RC); 102 | } 103 | 104 | // create a device object representing the driver itself 105 | // so that requests can be targeted to the driver ... 106 | RtlInitUnicodeString(&DriverDeviceName, SFILTER_DRV_NAME); 107 | if (!NT_SUCCESS(RC = IoCreateDevice( 108 | DriverObject, 109 | sizeof(SFilterDeviceExtension), 110 | &DriverDeviceName, 111 | FILE_DEVICE_FILE_SYSTEM, // For lack of anything better ? 112 | 0, 113 | FALSE, // Not exclusive. 114 | &(SFilterGlobalData.SFilterDeviceObject)))) { 115 | // failed to create a device object, leave. 116 | SFilterBreakPoint(); 117 | try_return(RC); 118 | } 119 | 120 | // Initialize the extension for the device object. 121 | PtrDeviceExtension = (PtrSFilterDeviceExtension)(SFilterGlobalData.SFilterDeviceObject->DeviceExtension); 122 | SFilterInitDevExtension(PtrDeviceExtension, SFilterGlobalData.SFilterDeviceObject, SFILTER_NODE_TYPE_FILTER_DEVICE); 123 | 124 | // In order to allow user-space helper applications to access our 125 | // device object for the filter driver, create a symbolic link to 126 | // the object. 127 | RtlInitUnicodeString(&UserVisibleName, SFILTER_DOS_DRV_NAME); 128 | if (!NT_SUCCESS(RC = IoCreateSymbolicLink(&UserVisibleName, &DriverDeviceName))) { 129 | SFilterBreakPoint(); 130 | try_return(RC); 131 | } 132 | SFilterSetFlag(SFilterGlobalData.SFilterFlags, SFILTER_DATA_FLAGS_SYMLINK_CREATED); 133 | 134 | 135 | // The filter driver is not currently unloadable. However, you could 136 | // extend the driver to support such functionality if so desired. 137 | // You must be careful about any pending I/O requests, must unattach 138 | // any previously attached device objects, release all resources. 139 | // All of the above is not easy but certainly doable for someone 140 | // sufficiently motivated :-) 141 | 142 | #if(_WIN32_WINNT >= 0x0400) 143 | // For version 4.0+ of the operating system only: 144 | // We will ask the I/O Manager to inform us whenever a FSD registers 145 | // itself. We should be able to get to all native local file system drivers 146 | // in this manner (and likely all network redirectors). 147 | 148 | // For versions prior to 4.0, see the reinitialization function 149 | // specified by this filter driver. 150 | RC = IoRegisterFsRegistrationChange(DriverObject, SFilterFSDNotification); 151 | #endif //(_WIN32_WINNT >= 0x0400) 152 | 153 | } except (EXCEPTION_EXECUTE_HANDLER) { 154 | // We encountered an exception somewhere, eat it up. 155 | RC = GetExceptionCode(); 156 | SFilterBreakPoint(); 157 | } 158 | 159 | try_exit: NOTHING; 160 | } finally { 161 | // Start unwinding if we were unsuccessful. 162 | if (!NT_SUCCESS(RC)) { 163 | 164 | if (SFilterGlobalData.SFilterFlags & SFILTER_DATA_FLAGS_SYMLINK_CREATED) { 165 | IoDeleteSymbolicLink(&UserVisibleName); 166 | } 167 | 168 | // Now, delete any device objects, etc. we may have created 169 | if (SFilterGlobalData.SFilterDeviceObject) { 170 | if (PtrDeviceExtension) { 171 | SFilterDeleteDevExtension(PtrDeviceExtension, FALSE); 172 | } 173 | // nothing (no-one) should be attached to our device 174 | // object at this time. 175 | IoDeleteDevice(SFilterGlobalData.SFilterDeviceObject); 176 | SFilterGlobalData.SFilterDeviceObject = NULL; 177 | } 178 | 179 | // Delete the directories we may have created. 180 | if (SFilterGlobalData.DirectoryHandle) { 181 | ZwClose(SFilterGlobalData.DirectoryHandle); 182 | SFilterGlobalData.DirectoryHandle = NULL; 183 | } 184 | 185 | if (SFilterGlobalData.DosDirectoryHandle) { 186 | ZwClose(SFilterGlobalData.DosDirectoryHandle); 187 | SFilterGlobalData.DosDirectoryHandle = NULL; 188 | } 189 | 190 | // delete the resource we may have initialized 191 | if (SFilterGlobalData.SFilterFlags & SFILTER_DATA_FLAGS_RESOURCE_INITIALIZED) { 192 | // uninitialize this resource 193 | ExDeleteResourceLite(&(SFilterGlobalData.GlobalDataResource)); 194 | SFilterClearFlag(SFilterGlobalData.SFilterFlags, SFILTER_DATA_FLAGS_RESOURCE_INITIALIZED); 195 | } 196 | } else { 197 | // This driver is loaded at system boot time. Therefore, not all 198 | // of the registry is available at that time. We will set a 199 | // a reinitialization function that will allow us to read user-specified 200 | // data. 201 | // For versions previous to version 4.0, we can also attach to 202 | // "known" FSDs in the reinitialization function (as long as the 203 | // driver loads suitably late in the cycle). 204 | IoRegisterDriverReinitialization(DriverObject, SFilterReinitialize, RegistryPath); 205 | } 206 | } 207 | 208 | return(RC); 209 | } 210 | 211 | 212 | 213 | /************************************************************************* 214 | * 215 | * Function: SFilterInitializeFunctionPointers() 216 | * 217 | * Description: 218 | * Initialize the IRP major function pointer array in the driver object 219 | * structure. Also initialize the fast-IO function ptr array. 220 | * 221 | * Expected Interrupt Level (for execution) : 222 | * 223 | * IRQL_PASSIVE_LEVEL 224 | * 225 | * Return Value: None 226 | * 227 | *************************************************************************/ 228 | void SFilterInitializeFunctionPointers( 229 | PDRIVER_OBJECT DriverObject) // created by the I/O sub-system 230 | { 231 | PFAST_IO_DISPATCH PtrFastIoDispatch = NULL; 232 | unsigned int Index = 0; 233 | 234 | // You must initialize the function pointer table such that your 235 | // filter driver supports all of the functions that the target 236 | // would originally support unless you really want to prevent the user 237 | // from being able to invoke a specific function. Even then, a better 238 | // way to deny the specific functionality is to initialize the specific 239 | // major function dispatch table entry to refer to your function and 240 | // then return an error from within your dispatch function. 241 | // Here, all I want to do is trap the read/write routines and let the 242 | // others go through. 243 | // However, create, cleanup, and close should also be appropriately 244 | // initialized to allow your user-space helper application to open 245 | // the device object representing the filter device. 246 | 247 | // First, initialize all function pointers to a default value. 248 | for (Index = 0; Index <= IRP_MJ_MAXIMUM_FUNCTION; Index++) { 249 | DriverObject->MajorFunction[Index] = SFilterDefaultDispatch; 250 | } 251 | 252 | // Initialize the ones we care about with unique function pointers. 253 | // Note that the functions your driver will care about will depend upon 254 | // exactly what it is that your filter wishes to do. 255 | // Currently, all we really care about is intercepting mount/verify/dismount 256 | // requests. 257 | DriverObject->MajorFunction[IRP_MJ_CREATE] = SFilterCreate; 258 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = SFilterCleanupOrClose; 259 | DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SFilterCleanupOrClose; 260 | DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SFilterFSControl; 261 | 262 | // Now, it is time to initialize the fast-IO stuff. 263 | PtrFastIoDispatch = DriverObject->FastIoDispatch = &(SFilterGlobalData.SFilterFastIoDispatch); 264 | 265 | // Initialize the global fast-IO structure. 266 | // NOTE: The fast-IO structure has undergone a substantial revision 267 | // in Windows NT Version 4.0. The structure has been extensively 268 | // expanded. 269 | // 270 | // Therefore, if your driver needs to work on both V3.51 and V4.0+, 271 | // you will have to be able to distinguish between the two versions 272 | // at compile time. 273 | PtrFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH); 274 | PtrFastIoDispatch->FastIoCheckIfPossible = SFilterFastIoCheckIfPossible; 275 | PtrFastIoDispatch->FastIoRead = SFilterFastIoRead; 276 | PtrFastIoDispatch->FastIoWrite = SFilterFastIoWrite; 277 | PtrFastIoDispatch->FastIoQueryBasicInfo = SFilterFastIoQueryBasicInfo; 278 | PtrFastIoDispatch->FastIoQueryStandardInfo = SFilterFastIoQueryStdInfo; 279 | PtrFastIoDispatch->FastIoLock = SFilterFastIoLock; 280 | PtrFastIoDispatch->FastIoUnlockSingle = SFilterFastIoUnlockSingle; 281 | PtrFastIoDispatch->FastIoUnlockAll = SFilterFastIoUnlockAll; 282 | PtrFastIoDispatch->FastIoUnlockAllByKey = SFilterFastIoUnlockAllByKey; 283 | PtrFastIoDispatch->FastIoDeviceControl = SFilterFastIoDeviceControl; 284 | 285 | PtrFastIoDispatch->AcquireFileForNtCreateSection = SFilterFastIoAcqCreateSec; 286 | PtrFastIoDispatch->ReleaseFileForNtCreateSection = SFilterFastIoRelCreateSec; 287 | 288 | // The remaining are only valid under NT Version 4.0 and later. 289 | #if(_WIN32_WINNT >= 0x0400) 290 | PtrFastIoDispatch->FastIoDetachDevice = SFilterFastIoDetachDevice; 291 | 292 | PtrFastIoDispatch->FastIoQueryNetworkOpenInfo = SFilterFastIoQueryNetInfo; 293 | 294 | /* MDL functionality */ 295 | PtrFastIoDispatch->MdlRead = SFilterFastIoMdlRead; 296 | PtrFastIoDispatch->MdlReadComplete = SFilterFastIoMdlReadComplete; 297 | PtrFastIoDispatch->PrepareMdlWrite = SFilterFastIoPrepareMdlWrite; 298 | PtrFastIoDispatch->MdlWriteComplete = SFilterFastIoMdlWriteComplete; 299 | PtrFastIoDispatch->FastIoReadCompressed = SFilterFastIoReadCompressed; 300 | PtrFastIoDispatch->FastIoWriteCompressed = SFilterFastIoWriteCompressed; 301 | PtrFastIoDispatch->MdlReadCompleteCompressed = 302 | SFilterFastIoMdlReadCompleteCompressed; 303 | PtrFastIoDispatch->MdlWriteCompleteCompressed = 304 | SFilterFastIoMdlWriteCompleteCompressed; 305 | 306 | // The only fast-IO request (currently) that actually takes an IRP. 307 | PtrFastIoDispatch->FastIoQueryOpen = SFilterFastIoQueryOpen; 308 | 309 | PtrFastIoDispatch->AcquireForModWrite = SFilterFastIoAcqModWrite; 310 | PtrFastIoDispatch->ReleaseForModWrite = SFilterFastIoRelModWrite; 311 | PtrFastIoDispatch->AcquireForCcFlush = SFilterFastIoAcqCcFlush; 312 | PtrFastIoDispatch->ReleaseForCcFlush = SFilterFastIoRelCcFlush; 313 | #endif //(_WIN32_WINNT >= 0x0400) 314 | 315 | return; 316 | } 317 | 318 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/sfilter.rc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #define VER_FILETYPE VFT_DRV 6 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 7 | #define VER_FILEDESCRIPTION_STR "Sample Filter Driver" 8 | #define VER_INTERNALNAME_STR "sfilter.sys" 9 | 10 | #include "common.ver" 11 |  -------------------------------------------------------------------------------- /NTFsrc/filter-high/src/sources: -------------------------------------------------------------------------------- 1 | # - Execute the "build" command to make the sample filter driver 2 | 3 | # The MAJORCOMP and MINORCOMP variables are defined 4 | # so that $(MAJORCOMP)$(MINORCOMP)filename can be used in 5 | # cross compiling to provide unique filenames in a flat namespace. 6 | 7 | MAJORCOMP=SAMPLE_FILTER 8 | MINORCOMP=SAMPLE_FILTER_DRV 9 | 10 | # The TARGETNAME variable is defined by the developer. It is the name of 11 | # the target (component) that is being built by this makefile. It 12 | # should NOT include any path or file extension information. 13 | 14 | TARGETNAME=sfilter 15 | 16 | # The TARGETPATH and TARGETTYPE variables are defined by the developer. 17 | # The first specifies where the target is to be build. The second specifies 18 | # the type of target. 19 | 20 | TARGETPATH=obj 21 | 22 | TARGETTYPE=DRIVER 23 | 24 | # The TARGETLIBS specifies additional libraries to link with you target 25 | # image. Each library path specification should contain an asterisk (*) 26 | # where the machine specific subdirectory name should go. 27 | 28 | #TARGETLIBS= 29 | 30 | # The INCLUDES variable specifies any include paths that are specific to 31 | # this source directory. Separate multiple directory paths with single 32 | # semicolons. Relative path specifications are okay. The INCLUDES 33 | # variable is not required. Specifying an empty INCLUDES variable 34 | # (i.e. INCLUDES= ) indicates no include paths are to be searched. 35 | # 36 | # NOTE: The "fsdk\inc" refers to the Microsoft supplied File Systems 37 | # Developers Kit include directory. 38 | 39 | INCLUDES=..\inc;\ddk-40\inc;\fsdk\inc-40; 40 | 41 | # The SOURCES variable is defined by the developer. It is a list of all the 42 | # source files for this component. Each source file should be on a separate 43 | # line using the line continuation character. This will minimize merge 44 | # conflicts if two developers adding source files to the same component. 45 | # The SOURCES variable is required. If there are no platform common source 46 | # files, an empty SOURCES variable should be used. (i.e. SOURCES= ) 47 | 48 | # Source files common to multiple platforms 49 | 50 | SOURCES=sfilinit.c \ 51 | fastio.c \ 52 | misc.c \ 53 | attach.c \ 54 | dispatch.c \ 55 | sfilter.rc \ 56 | create.c \ 57 | fsctrl.c \ 58 | close.c 59 | 60 | # i386 only source files (optional) 61 | # assembler files MUST be in a subdirectory named i386 62 | 63 | # i386_SOURCES=i386\source1.asm 64 | 65 | # mips only source files (optional) 66 | # assembler files MUST be in a subdirectory named mips 67 | 68 | # MIPS_SOURCES=mips\source1.s 69 | 70 | # Next specify any additional options for the compiler. 71 | # Define the appropriate CPU type (and insert defines 72 | # in the appropriate header file) to get the right 73 | # values for "uint8", "uint16" etc. typedefs. 74 | 75 | C_DEFINES= -DUNICODE -D_CPU_X86_ 76 | 77 | # required to compile for C++ 78 | 79 | # BLDCRT=1 80 | 81 | # 82 | # Next specify options for the linker. 83 | # 84 | 85 | # DLLBASE=0x62900000 86 | # DLLENTRY=LibMain 87 | 88 | # specify which C runtimes to link with (default is libc.lib) 89 | 90 | # USE_CRTDLL=1 (link with crtdll.lib) 91 | # USE_LIBCMT=1 (link with libcmt.lib) 92 | 93 | # Next specify one or more user mode test programs and their type 94 | # UMTEST is used for optional test programs. UMAPPL is used for 95 | # programs that always get built when the directory is built. 96 | 97 | # UMTYPE=nt 98 | # UMTEST=foo*baz 99 | # UMAPPL=foo*baz 100 | # UMBASE=0x1000000 101 | # UMLIBS=obj\*\foo.lib 102 | 103 | # Defining either (or both) the variables NTTARGETFILE0 and/or NTTARGETFILES 104 | # will cause MAKEFILE.DEF to include .\makefile.inc immediately after it 105 | # specifies the top level targets (all, clean and loc) and their dependencies. 106 | # MAKEFILE.DEF also expands NTTARGETFILE0 as the first dependent for the 107 | # "all" target and NTTARGETFILES as the last dependent for the "all" target. 108 | # Useful for specifying additional targets and dependencies that don't fit the 109 | # general case covered by MAKEFILE.DEF 110 | 111 | # NTTARGETFILE0 is built before all other compiles specified in the sources 112 | # file. 113 | 114 | # NTTARGETFILE1 is built after all other compiles specified in the sources 115 | # file but before the link step. 116 | 117 | # NTTARGETFILES is built after all compiles/links specified by the 118 | # sources file. 119 | 120 | # NTTARGETFILE0= 121 | # NTTARGETFILE1= 122 | # NTTARGETFILES= 123 | 124 | # Profiling for the working set tuner can be enabled by specifying the 125 | # NTPROFILEINPUT variable. Examine the VGA display driver and perf samples 126 | # for more details 127 | 128 | # NTPROFILEINPUT=YES 129 | 130 | 131 | # The type of product being built - NT = kernel mode 132 | 133 | UMTYPE=nt 134 |  -------------------------------------------------------------------------------- /NTFsrc/fsrec/WS_FTP.LOG: -------------------------------------------------------------------------------- 1 | 97.08.05 15:12 B C:\Users\Erik\NTFdisk\fsrec\readme3.txt --> geode /home/eray readme3.txt 2 | 97.08.06 14:20 B C:\Users\erik\NTFdisk\fsrec\readme3.txt <-- geode /work/nt/file.internals/disk readme3.txt 3 | -------------------------------------------------------------------------------- /NTFsrc/fsrec/inc/sfsrec.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfsrec.h 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * The main include file for the sample file system driver recognizer. 9 | * 10 | * Author: R. Nagar 11 | * 12 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 13 | * 14 | *************************************************************************/ 15 | 16 | #ifndef _SFSREC_SFSREC_H_ 17 | #define _SFSREC_SFSREC_H_ 18 | 19 | // Common include files; should be in the include dir of the MS supplied IFS Kit. 20 | #include 21 | 22 | typedef struct SFsRecDeviceExtension { 23 | BOOLEAN DidLoadFail; 24 | } SFsRecDeviceExtension, *PtrSFsRecDeviceExtension; 25 | 26 | // try-finally simulation 27 | #define try_return(S) { S; goto try_exit; } 28 | #define try_return1(S) { S; goto try_exit1; } 29 | #define try_return2(S) { S; goto try_exit2; } 30 | 31 | // Prototypes 32 | extern void SFsRecUnload( 33 | PDRIVER_OBJECT PtrFsRecDriverObject); 34 | 35 | extern NTSTATUS SFsRecFsControl( 36 | PDEVICE_OBJECT DeviceObject, 37 | PIRP Irp); 38 | 39 | #endif // _SFSREC_SFSREC_H_ 40 | 41 |  -------------------------------------------------------------------------------- /NTFsrc/fsrec/readme3.txt: -------------------------------------------------------------------------------- 1 | Sample File System Driver 2 | ------------------------ 3 | 4 | The sample file system driver recognizer code provided here can be^M 5 | used to design and implement your own file system driver recognizer product. 6 | 7 | !!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 8 | 9 | The code provided here is for illustration purposes only. It is not 10 | to be used as-is. Substantial modifications, enhancements and testing 11 | is required before installing any portion of the code on any 12 | machine. 13 | 14 | DO NOT EXPECT THIS CODE TO WORK. IT IS ONLY TO BE USED AS A GUIDE 15 | IN CONJUNCTION WITH THE TEXT CONTAINED IN THE BOOK IN DESIGNING YOUR 16 | OWN FSD RECOGNIZER. IT IS LACKING IN FUNCTIONALITY AND HAS NEVER BEEN 17 | INSTALLED OR TESTED AS IS COMMONLY REQUIRED. 18 | 19 | TO COMPILE THE SOURCES PROVIDED HERE, YOU MUST HAVE A COPY OF THE 20 | "ntifs.h" HEADER FILE PROVIDED BY MICROSOFT AS PART OF THE WINDOWS NT 21 | IFS KIT. 22 | 23 | !!!!!!!!!!!!!!!!!!!!!!!WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 24 | 25 | Files provided: 26 | -------------- 27 | 28 | src\sfsrec.c - File system driver recognizer initialization functions 29 | inc\sfsrec.h - The "main" include file; also contains useful macros 30 | src\makefile - makefile! 31 | src\sources - Contains list of files to be built; use by build.exe 32 | README.TXT - What you are reading 33 | 34 |  35 | -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/obj/_objects.mac: -------------------------------------------------------------------------------- 1 | ALPHA_OBJECTS= \ 2 | $(_OBJ_DIR)\alpha\sfsrec.obj 3 | 4 | PASS0_ALPHA_OBJECTS= 5 | 6 | MIPS_OBJECTS= \ 7 | $(_OBJ_DIR)\mips\sfsrec.obj 8 | 9 | PASS0_MIPS_OBJECTS= 10 | 11 | 386_OBJECTS= \ 12 | $(_OBJ_DIR)\i386\sfsrec.obj 13 | 14 | PASS0_386_OBJECTS= 15 | 16 | PPC_OBJECTS= \ 17 | $(_OBJ_DIR)\ppc\sfsrec.obj 18 | 19 | PASS0_PPC_OBJECTS= 20 | 21 | -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/obj/i386/checked/sfsrec.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/fsrec/src/obj/i386/checked/sfsrec.sys -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/obj/i386/free/sfsrec.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/fsrec/src/obj/i386/free/sfsrec.sys -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/obj/i386/sfsrec.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tpn/windows-nt-file-system-internals-book/fb47328de1cda03b3d1cb63313c8277105ffe609/NTFsrc/fsrec/src/obj/i386/sfsrec.obj -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/sfsrec.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * 3 | * File: sfsrec.c 4 | * 5 | * Module: Sample File System Driver (Kernel mode execution only) 6 | * 7 | * Description: 8 | * This file contains the initialization code for the kernel mode 9 | * Sample FSD recognizer module 10 | * 11 | * Author: R. Nagar 12 | * 13 | * (c) 1996-97 Rajeev Nagar, All Rights Reserved 14 | * 15 | *************************************************************************/ 16 | 17 | #include "sfsrec.h" 18 | 19 | #define SFSD_FS_NAME L"\\SampleFSDRecognizer" 20 | 21 | PDEVICE_OBJECT PtrFSRecDeviceObject = NULL; 22 | unsigned int SFsRecDidLoadFail = 0; 23 | 24 | extern NTSTATUS ZwLoadDriver( 25 | IN PUNICODE_STRING DriverName); 26 | 27 | 28 | /************************************************************************* 29 | * 30 | * Function: DriverEntry() 31 | * 32 | * Description: 33 | * This routine is the standard entry point for all kernel mode drivers. 34 | * The routine is invoked at IRQL PASSIVE_LEVEL in the context of a 35 | * system worker thread. 36 | * All FSD specific data structures etc. are initialized here. 37 | * 38 | * Expected Interrupt Level (for execution) : 39 | * 40 | * IRQL_PASSIVE_LEVEL 41 | * 42 | * Return Value: STATUS_SUCCESS/Error (will cause driver to be unloaded). 43 | * 44 | *************************************************************************/ 45 | NTSTATUS DriverEntry( 46 | PDRIVER_OBJECT DriverObject, 47 | PUNICODE_STRING RegistryPath) 48 | { 49 | NTSTATUS RC = STATUS_SUCCESS; 50 | UNICODE_STRING DriverDeviceName; 51 | 52 | UNICODE_STRING FileSystemName; 53 | OBJECT_ATTRIBUTES ObjectAttributes; 54 | HANDLE FileSystemHandle = NULL; 55 | IO_STATUS_BLOCK IoStatus; 56 | PtrSFsRecDeviceExtension PtrExtension = NULL; 57 | 58 | try { 59 | try { 60 | 61 | // Initialize the IRP major function table 62 | DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SFsRecFsControl; 63 | DriverObject->DriverUnload = SFsRecUnload; 64 | 65 | // Before creating a device object, check whether the FSD has been 66 | // already loaded. Obviously you should know the name of the FSD that 67 | // this recognizer has been created for. 68 | RtlInitUnicodeString(&FileSystemName, L"\\SampleFSD"); 69 | InitializeObjectAttributes(&ObjectAttributes, &FileSystemName, OBJ_CASE_INSENSITIVE, NULL, NULL); 70 | // Try to open the file system now. 71 | RC = ZwCreateFile(&FileSystemHandle, SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, 0, 72 | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0); 73 | if (RC != STATUS_OBJECT_NAME_NOT_FOUND) { 74 | // The FSD must have been already loaded. 75 | if (NT_SUCCESS(RC)) { 76 | ZwClose(FileSystemHandle); 77 | } 78 | RC = STATUS_IMAGE_ALREADY_LOADED; 79 | try_return(RC); 80 | } 81 | 82 | // Create a device object representing the file system recognizer. 83 | // Mount requests are sent to this device object. 84 | RtlInitUnicodeString(&DriverDeviceName, L"\\SampleFSDRecognizer"); 85 | 86 | if (!NT_SUCCESS(RC = IoCreateDevice(DriverObject, // Driver object for the file system rec. 87 | sizeof(SFsRecDeviceExtension), // Did a load fail? 88 | &DriverDeviceName, // Name used above 89 | FILE_DEVICE_DISK_FILE_SYSTEM, 90 | 0, // No special characteristics 91 | FALSE, 92 | &(PtrFSRecDeviceObject)))) { 93 | try_return(RC); 94 | } 95 | 96 | PtrExtension = (PtrSFsRecDeviceExtension)(PtrFSRecDeviceObject->DeviceExtension); 97 | 98 | PtrExtension->DidLoadFail = FALSE; 99 | 100 | // Register the device object with the I/O Manager. 101 | IoRegisterFileSystem(PtrFSRecDeviceObject); 102 | 103 | } except (EXCEPTION_EXECUTE_HANDLER) { 104 | // we encountered an exception somewhere, eat it up 105 | RC = GetExceptionCode(); 106 | } 107 | 108 | try_exit: NOTHING; 109 | } finally { 110 | // start unwinding if we were unsuccessful 111 | if (!NT_SUCCESS(RC) && PtrFSRecDeviceObject) { 112 | IoDeleteDevice(PtrFSRecDeviceObject); 113 | PtrFSRecDeviceObject = NULL; 114 | } 115 | } 116 | 117 | return(RC); 118 | } 119 | 120 | 121 | 122 | /************************************************************************* 123 | * 124 | * Function: SFsRecUnload() 125 | * 126 | * Description: 127 | * Unload the FS recognizer. 128 | * 129 | * Expected Interrupt Level (for execution) : 130 | * 131 | * IRQL_PASSIVE_LEVEL 132 | * 133 | * Return Value: None 134 | * 135 | *************************************************************************/ 136 | void SFsRecUnload( 137 | PDRIVER_OBJECT PtrFsRecDriverObject) 138 | { 139 | // Simple. Unregister the device object, and delete it. 140 | if (PtrFSRecDeviceObject) { 141 | IoUnregisterFileSystem(PtrFSRecDeviceObject); 142 | IoDeleteDevice(PtrFSRecDeviceObject); 143 | 144 | PtrFSRecDeviceObject = NULL; 145 | } 146 | 147 | return; 148 | } 149 | 150 | 151 | /************************************************************************* 152 | * 153 | * Function: SFsRecFsControl() 154 | * 155 | * Description: 156 | * The single dispatch routine provided. 157 | * 158 | * Expected Interrupt Level (for execution) : 159 | * 160 | * IRQL_PASSIVE_LEVEL 161 | * 162 | * Return Value: None 163 | * 164 | *************************************************************************/ 165 | NTSTATUS SFsRecFsControl( 166 | PDEVICE_OBJECT DeviceObject, 167 | PIRP Irp) 168 | { 169 | NTSTATUS RC = STATUS_UNRECOGNIZED_VOLUME; 170 | PIO_STACK_LOCATION PtrIoStackLocation = NULL; 171 | PtrSFsRecDeviceExtension PtrExtension = NULL; 172 | PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 173 | UNICODE_STRING DriverName; 174 | 175 | FsRtlEnterFileSystem(); 176 | 177 | try { 178 | 179 | try { 180 | 181 | PtrIoStackLocation = IoGetCurrentIrpStackLocation(Irp); 182 | ASSERT(PtrIoStackLocation); 183 | 184 | // Get a pointer to the device object extension. 185 | PtrExtension = (PtrSFsRecDeviceExtension)(PtrFSRecDeviceObject->DeviceExtension); 186 | 187 | switch (PtrIoStackLocation->MinorFunction) { 188 | case IRP_MN_MOUNT_VOLUME: 189 | // Fail the request immediately if a previous load has failed. 190 | // You are not required to do this however in your driver. 191 | if (PtrExtension->DidLoadFail) { 192 | try_return(RC); 193 | } 194 | 195 | // Get a pointer to the target physical/virtual device object. 196 | PtrTargetDeviceObject = PtrIoStackLocation->Parameters.MountVolume.DeviceObject; 197 | 198 | // The operations that you perform here are highly FSD specific. 199 | // Typically, you would invoke an internal function that would 200 | // (a) Get the disk geometry by issuing an IOCTL 201 | // (b) Read the first few sectors (or appropriate sectors) 202 | // to verify the on-disk metadata information. 203 | // To get the drive geometry, use the documented I/O Manager 204 | // routine called IoBuildDeviceIoControlRequest() to create an 205 | // IRP. Supply an event with this request that you will wait on 206 | // in case the lower-level driver returns STATUS_PENDING. 207 | // Similarly, to actually read on-disk sectors, create an IRP 208 | // using the IoBuildSynchronousFsdRequest() function call with 209 | // a major function of IRP_MJ_READ. 210 | 211 | // After you have obtained on-disk information, verify the metadata. 212 | // RC = SFsRecGetDiskInfoAndVerify(PtrTargetDeviceObject); 213 | 214 | if (NT_SUCCESS(RC)) { 215 | // Everything looks good. Prepare to load the driver. 216 | try_return(RC = STATUS_FS_DRIVER_REQUIRED); 217 | } 218 | break; 219 | case IRP_MN_LOAD_FILE_SYSTEM: 220 | // OK. So we processed a mount request and returned 221 | // STATUS_FS_DRIVER_REQUIRED to the I/O Manager. 222 | // This is the result! 223 | RtlInitUnicodeString(&DriverName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\SFsd"); 224 | RC = ZwLoadDriver(&DriverName); 225 | if ((!NT_SUCCESS(RC)) && (RC != STATUS_IMAGE_ALREADY_LOADED)) { 226 | PtrExtension->DidLoadFail = TRUE; 227 | } else { 228 | // Load succeeded. Mission accomplished! 229 | IoUnregisterFileSystem(PtrFSRecDeviceObject); 230 | } 231 | break; 232 | default: 233 | RC = STATUS_INVALID_DEVICE_REQUEST; 234 | break; 235 | } 236 | 237 | } except (EXCEPTION_EXECUTE_HANDLER) { 238 | RC = GetExceptionCode(); 239 | } 240 | 241 | try_exit: NOTHING; 242 | 243 | } finally { 244 | // Complete the IRP. 245 | Irp->IoStatus.Status = RC; 246 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 247 | } 248 | 249 | FsRtlExitFileSystem(); 250 | 251 | return(RC); 252 | } 253 | 254 |  -------------------------------------------------------------------------------- /NTFsrc/fsrec/src/sources: -------------------------------------------------------------------------------- 1 | # - Execute the "build" command to make the sample FSD driver recognizer 2 | 3 | # 4 | # The TARGETNAME variable is defined by the developer. It is the name of 5 | # the target (component) that is being built by this makefile. It 6 | # should NOT include any path or file extension information. 7 | # 8 | 9 | TARGETNAME=sfsrec 10 | 11 | TARGETPATH=obj 12 | 13 | TARGETTYPE=DRIVER 14 | 15 | 16 | INCLUDES=..\inc;\ddk-40\inc;\fsdk-40\inc; 17 | 18 | # Source files common to multiple platforms 19 | 20 | SOURCES=sfsrec.c 21 | 22 | # 23 | # Next specify any additional options for the compiler. 24 | # 25 | C_DEFINES= -DUNICODE -D_CPU_X86_ 26 | 27 | # The type of product being built - NT = kernel mode 28 | 29 | UMTYPE=nt 30 |  -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | README.TXT 2 | 3 | The sources for the examples and a working file system filter driver are 4 | compressed and contained in the file examples.zip. Unzipping the file 5 | produces three folders: 6 | 7 | 1. filesys, containing a README file and the sources for the example file 8 | system driver 9 | 2. fsrec, containing a README file and the sources for the example FSD 10 | recognizer 11 | 3. filter-high, containing a README file and the sources for the example 12 | file system filter driver 13 | --------------------------------------------------------------------------------