www.pudn.com > FsTPM0.rar > SpecialIOFunction.cpp


 
#include "FsTPM.h" 
 
// Used to set Object's flag 
#ifndef SetFlag 
#define SetFlag(x,f)    ((x) |= (f)) 
#endif 
 
// Used to clear Object's flag 
#ifndef ClearFlag 
#define ClearFlag(x,f)  ((x) &= ~(f)) 
#endif 
 
BOOL IsSomeSpecialFile( PWCHAR WideSource, PFILE_OBJECT pFileObject, PIO_STACK_LOCATION pCurrentIrpStack) 
{ 
	if ( /*(0==pFileObject->FileName.Length)			||*/ 
		(wcsstr(WideSource,L"SYSTEM32\\CONFIG")!=0) || 
		(wcsstr(WideSource,L"NTUSER.DAT.LOG")!=0)	|| 
		(wcsstr(WideSource,L"PAGEFILE.SYS")!=0)		|| 
		(wcsstr(WideSource,L"NTUSER.DAT")!=0)		|| 
		(wcsstr(WideSource,L"SECURITY.LOG")!=0)		|| 
		(wcsstr(WideSource,L"SOFTWARE.LOG")!=0)		|| 
		(wcsstr(WideSource,L"SYSTEM.LOG")!=0)		|| 
		(wcsstr(WideSource,L"DEFAULT.LOG")!=0)		|| 
		(Is_Directory_File(pCurrentIrpStack->Parameters.Create.Options)) 
		) 
	{ 
		return TRUE; 
	} 
	return FALSE; 
} 
 
 
 
VOID  
FsTPMGetFileStandardInformation( 
								  PFILE_OBJECT FileObject, 
								  PFILE_STANDARD_INFORMATION StandardInformation, 
								  PIO_STATUS_BLOCK IoStatusBlock, 
								  PDEVICE_OBJECT pDeviceObject 
								  ) 
								  //++ 
								  // Function:	FsTPMGetFileStandardInformation 
								  // 
								  // Description: 
								  //		Get a file's standard information  
								  // 
								  // Arguments: 
								  //		IN  FileObject			- Target file object  
								  //		OUT StandardInformation - Standard information pointer 
								  //		OUT IoStatusBlock		- Point out whether this request is success. 
								  //		IN  pDeviceObject       - the Device below me 
								  // Return value: 
								  //		None 
								  // 
								  // Notice : 
								  //		This function is provided by OSR 
								  //-- 
{ 
	PIRP irp; 
	KEVENT event; 
	PIO_STACK_LOCATION ioStackLocation; 
	PDEVICE_OBJECT fsdDevice=pDeviceObject; 
 
	// 
	// Start off on the right foot - zero the information block. 
	// 
 
	RtlZeroMemory(StandardInformation, sizeof(FILE_STANDARD_INFORMATION)); 
 
	// 
	// Allocate an irp for this request.  This could also come from a  
	// private pool, for instance. 
	// 
 
	irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); 
 
	if (!irp) { 
		// 
		// Failure! 
		// 
 
		return; 
	} 
 
	irp->AssociatedIrp.SystemBuffer = StandardInformation; 
 
	irp->UserEvent = &event; 
 
	irp->UserIosb = IoStatusBlock; 
 
	irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
 
	irp->Tail.Overlay.OriginalFileObject = FileObject; 
 
	irp->RequestorMode = KernelMode; 
 
	// 
	// Initialize the event 
	// 
 
	KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
	// 
	// Set up the I/O stack location. 
	// 
 
	ioStackLocation = IoGetNextIrpStackLocation(irp); 
 
	ioStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMATION; 
 
	ioStackLocation->DeviceObject = fsdDevice; 
 
	ioStackLocation->FileObject = FileObject; 
 
	ioStackLocation->Parameters.QueryFile.Length = sizeof(FILE_STANDARD_INFORMATION); 
 
	ioStackLocation->Parameters.QueryFile.FileInformationClass = FileStandardInformation; 
 
	// 
	// Set the completion routine. 
	// 
 
	IoSetCompletionRoutine(irp, KfcIoCompletion, 0, TRUE, TRUE, TRUE); 
 
	// 
	// Send it to the FSD 
	// 
 
	(void) IoCallDriver(fsdDevice, irp); 
 
	// 
	// Wait for the I/O 
	// 
 
	KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
	// 
	// Done! 
	// 
 
	return; 
 
} 
 
 
NTSTATUS  
KfcIoCompletion( 
				PDEVICE_OBJECT DeviceObject, 
				PIRP Irp, 
				PVOID Context 
				) 
				//++ 
				// Function:	KfcIoCompletion 
				// 
				// Description: 
				//		This routine is used to handle I/O (read OR write) completion 
				// 
				// Arguments: 
				//		DeviceObject - not used 
				//		Irp - the I/O operation being completed 
				//		Context - not used 
				// 
				// Return value: 
				//		STATUS_MORE_PROCESSING_REQUIRED 
				//	 
				// Notice : 
				//		This function is provided by OSR 
				// 
				// Notes: 
				//		The purpose of this routine is to do "cleanup" on I/O operations 
				//  so we don't constantly throw away perfectly good MDLs as part of 
				//  completion processing. 
				// 
{ 
	// 
	// Copy the status information back into the "user" IOSB. 
	// 
 
	*Irp->UserIosb = Irp->IoStatus; 
 
	// 
	// Set the user event - wakes up the mainline code doing this. 
	// So that we can jump out of KeWaitForSingleObject() in my routine 
	// 
 
	KeSetEvent(Irp->UserEvent, 0, FALSE); 
 
 
	// 
	// Free the IRP now that we are done with it. 
	// 
 
	IoFreeIrp(Irp); 
 
	// 
	// We return STATUS_MORE_PROCESSING_REQUIRED because this "magic" return value 
	// tells the I/O Manager that additional processing will be done by this driver 
	// to the IRP - in fact, it might (as it is in this case) already BE done - and 
	// the IRP cannot be completed. 
	// 
 
	return STATUS_MORE_PROCESSING_REQUIRED; 
} 
 
VOID  
FsTPMRead( 
			PFILE_OBJECT FileObject, 
			PLARGE_INTEGER Offset, 
			ULONG Length, 
			PMDL Mdl, 
			PIO_STATUS_BLOCK IoStatusBlock, 
			PDEVICE_OBJECT pDevice 
			) 
			//++ 
			// Function:	FsTPMRead 
			// 
			// Description: 
			//		This routine is used to read the file object to memory discribed by MDL 
			// 
			// Arguments: 
			//		PFILE_OBJECT FileObject, 
			//		PLARGE_INTEGER Offset, 
			//		ULONG Length, 
			//		PMDL Mdl, 
			//		PIO_STATUS_BLOCK IoStatusBlock 
			// 
			// Return value: 
			//		None 
			//	 
			// Notice : 
			//		This function is provided by OSR 
			// 
{ 
	PIRP irp; 
	KEVENT event; 
	PIO_STACK_LOCATION ioStackLocation; 
	PDEVICE_OBJECT fsdDevice=pDevice; 
	// 
	// Set up the event we'll use. 
	// 
 
	KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
 
	// 
	// Allocate and build the IRP we'll be sending to the FSD. 
	// 
 
	irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); 
 
	if (!irp) { 
 
		// 
		// Allocation failed, presumably due to memory allocation failure. 
		// 
 
		IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES; 
 
		IoStatusBlock->Information = 0; 
 
	} 
 
	irp->MdlAddress = Mdl; 
 
	irp->UserEvent = &event; 
 
	irp->UserIosb = IoStatusBlock; 
 
	irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
 
	irp->Tail.Overlay.OriginalFileObject= FileObject; 
 
	irp->RequestorMode = KernelMode; 
 
 
	// 
	// Indicate that this is a READ operation. 
	// 
 
	irp->Flags = IRP_READ_OPERATION; 
 
 
	// 
	// Set up the next I/O stack location.  These are the parameters 
	// that will be passed to the underlying driver. 
	// 
 
	ioStackLocation = IoGetNextIrpStackLocation(irp); 
 
	ioStackLocation->MajorFunction = IRP_MJ_READ; 
 
	ioStackLocation->MinorFunction = 0; 
 
	ioStackLocation->DeviceObject = fsdDevice; 
 
	ioStackLocation->FileObject = FileObject; 
 
 
	// 
	// We use a completion routine to keep the I/O Manager from doing 
	// "cleanup" on our IRP - like freeing our MDL. 
	// 
 
	IoSetCompletionRoutine(irp, KfcIoCompletion, 0, TRUE, TRUE, TRUE); 
 
	ioStackLocation->Parameters.Read.Length = Length; 
 
	ioStackLocation->Parameters.Read.ByteOffset = *Offset; 
 
 
	// 
	// Send it on.  Ignore the return code. 
	// 
 
	(void) IoCallDriver(fsdDevice, irp); 
 
 
	// 
	// Wait for the I/O to complete. 
	// 
 
	KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
 
	// 
	// Done.  Return results are in the io status block. 
	// 
 
	return; 
} 
 
 
 
VOID  
FsTPMSetFileAllocation( 
						 PFILE_OBJECT FileObject, 
						 PLARGE_INTEGER AllocationSize, 
						 PIO_STATUS_BLOCK IoStatusBlock, 
						 PDEVICE_OBJECT   pDevice 
						 ) 
						 //++ 
						 // Function:	FsTPMSetFileAllocation 
						 // 
						 // Description: 
						 //		This routine sets a file's ALLOCATION size to the specified value. 
						 //  Note that this DOES NOT extend the file's EOF. 
						 // 
						 // Arguments: 
						 //		FileObject - the file on which to set the allocation size 
						 //		AllocationSize - the new allocation size 
						 //	    IoStatusBlock - the results of this operation 
						 // 
						 // Return value: 
						 //		None 
						 //	 
						 // Notice : 
						 //		This function is provided by OSR 
						 //-- 
{ 
	PIRP irp; 
	KEVENT event; 
	PIO_STACK_LOCATION ioStackLocation; 
	PDEVICE_OBJECT fsdDevice=pDevice; 
 
	// 
	// Allocate an irp for this request.  This could also come from a  
	// private pool, for instance. 
	// 
 
	irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); 
 
	if (!irp) { 
		// 
		// Failure! 
		// 
 
		return; 
	} 
 
	irp->AssociatedIrp.SystemBuffer = AllocationSize; 
 
	irp->UserEvent = &event; 
 
	irp->UserIosb = IoStatusBlock; 
 
	irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
 
	irp->Tail.Overlay.OriginalFileObject = FileObject; 
 
	irp->RequestorMode = KernelMode; 
 
 
	// 
	// Initialize the event 
	// 
 
	KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
 
	// 
	// Set up the I/O stack location. 
	// 
 
	ioStackLocation = IoGetNextIrpStackLocation(irp); 
 
	ioStackLocation->MajorFunction = IRP_MJ_SET_INFORMATION; 
 
	ioStackLocation->DeviceObject = fsdDevice; 
 
	ioStackLocation->FileObject = FileObject; 
 
	ioStackLocation->Parameters.SetFile.Length = sizeof(LARGE_INTEGER); 
 
	ioStackLocation->Parameters.SetFile.FileInformationClass = FileAllocationInformation; 
 
	ioStackLocation->Parameters.SetFile.FileObject = 0; // not used for allocation 
 
	ioStackLocation->Parameters.SetFile.AdvanceOnly = FALSE; 
 
	// 
	// Set the completion routine. 
	// 
 
	IoSetCompletionRoutine(irp, KfcIoCompletion, 0, TRUE, TRUE, TRUE); 
 
	// 
	// Send it to the FSD 
	// 
 
	(void) IoCallDriver(fsdDevice, irp); 
 
	// 
	// Wait for the I/O 
	// 
 
	KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
	// 
	// Done! 
	// 
 
	return; 
} 
 
VOID  
FsTPMWrite( 
			 PFILE_OBJECT FileObject, 
			 PLARGE_INTEGER Offset, 
			 ULONG Length, 
			 PMDL Mdl, 
			 PIO_STATUS_BLOCK IoStatusBlock, 
			 PDEVICE_OBJECT   pDevice 
			 ) 
			 //++ 
			 // Function:	FsTPMWrite 
			 // 
			 // Description: 
			 //		This routine is used to write to the file object from memory discribed by MDL 
			 // 
			 // Arguments: 
			 //		PFILE_OBJECT FileObject, 
			 //		PLARGE_INTEGER Offset, 
			 //		ULONG Length, 
			 //		PMDL Mdl, 
			 //		PIO_STATUS_BLOCK IoStatusBlock 
			 // 
			 // Return value: 
			 //		None 
			 //	 
			 // Notice : 
			 //		This function is provided by OSR 
			 // 
{ 
	PIRP irp; 
	KEVENT event; 
	PIO_STACK_LOCATION ioStackLocation; 
	PDEVICE_OBJECT fsdDevice =pDevice; 
 
	// 
	// Set up the event we'll use. 
	// 
 
	KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
 
	// 
	// Allocate and build the IRP we'll be sending to the FSD. 
	// 
 
	irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); 
 
	if (!irp) { 
 
		// 
		// Allocation failed, presumably due to memory allocation failure. 
		// 
 
		IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES; 
 
		IoStatusBlock->Information = 0; 
 
	} 
 
	irp->MdlAddress = Mdl; 
 
	irp->UserEvent = &event; 
 
	irp->UserIosb = IoStatusBlock; 
 
	irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
 
	irp->Tail.Overlay.OriginalFileObject= FileObject; 
 
	irp->RequestorMode = KernelMode; 
 
 
	// 
	// Indicate that this is a WRITE operation. 
	// 
 
	irp->Flags = IRP_WRITE_OPERATION; 
 
 
	// 
	// Set up the next I/O stack location.  These are the parameters 
	// that will be passed to the underlying driver. 
	// 
 
	ioStackLocation = IoGetNextIrpStackLocation(irp); 
 
	ioStackLocation->MajorFunction = IRP_MJ_WRITE; 
 
	ioStackLocation->MinorFunction = 0; 
 
	ioStackLocation->DeviceObject = fsdDevice; 
 
	ioStackLocation->FileObject = FileObject; 
 
 
	// 
	// We use a completion routine to keep the I/O Manager from doing 
	// "cleanup" on our IRP - like freeing our MDL. 
	// 
 
	IoSetCompletionRoutine(irp, KfcIoCompletion, 0, TRUE, TRUE, TRUE); 
 
	ioStackLocation->Parameters.Write.Length = Length; 
 
	ioStackLocation->Parameters.Write.ByteOffset = *Offset; 
 
 
	// 
	// Send it on.  Ignore the return code. 
	// 
 
	(void) IoCallDriver(fsdDevice, irp); 
 
 
	// 
	// Wait for the I/O to complete. 
	// 
 
	KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
 
	// 
	// Done.  Return results are in the io status block. 
	// 
 
	return; 
 
} 
 
 
//----------------------------------------------------------------------------- 
/*++ 
The following functions 
 
Abstract: 
This module implements routines to support synchronous API calls to 
the next lower file system driver. 
 
Revision History: 
 
02-01-2002 : created 
 
Note: 
Thank OSR and Mr. Paul for providing some useful information 
--*/ 
 
 
VOID FsTPMReferenceDeviceAndVpb(IN PFILE_OBJECT FileObject) 
{ 
	//	NTSTATUS Status; 
	PDEVICE_OBJECT RealDevice; 
	PVPB Vpb; 
 
	// 
	// Copy RealDevice and Vpb into local variables to make things easier. 
	// 
 
	RealDevice =  FileObject->DeviceObject; 
	Vpb =  FileObject->Vpb; 
 
	//ASSERT(Vpb !=  NULL ? RealDevice->Vpb !=  NULL : RealDevice->Vpb ==  NULL); 
 
	// 
	// Increment RealDevice's reference count. 
	// 
 
	ExInterlockedAddUlong((unsigned long *)&RealDevice->ReferenceCount, 1, IopDatabaseLock); 
 
	if (Vpb) 
	{ 
		KIRQL Irql; 
 
		ASSERT(FlagOn(Vpb->Flags, VPB_MOUNTED) && !FlagOn(Vpb->Flags, VPB_LOCKED)); 
 
		// 
		// Increment Vpb's reference count, if one exists. 
		// 
 
		IoAcquireVpbSpinLock(&Irql); 
		Vpb->ReferenceCount++; 
		IoReleaseVpbSpinLock(Irql); 
	} 
} 
 
 
 
NTSTATUS 
FsTPMQueryInformationFile ( 
						IN PVCB Vcb, 
						IN PFILE_OBJECT FileObject, 
						IN FILE_INFORMATION_CLASS FileInformationClass, 
						OUT PVOID FileInformation, 
						IN ULONG Length, 
						OUT PULONG ResultLength 
						) 
{ 
	PDEVICE_OBJECT DeviceObject =  Vcb->NextLowerDevice; 
	PFAST_IO_DISPATCH FastIoDispatch = 	DeviceObject->DriverObject->FastIoDispatch; 
	NTSTATUS Status; 
	KEVENT Event; 
	IO_STATUS_BLOCK IoStatus; 
	PIRP Irp; 
	PIO_STACK_LOCATION NextIrpSp; 
 
		// 
		// Try to do this request through the FastIo if possible. 
		// 
 
		if (FastIoDispatch && 
			(FileInformationClass ==  FileBasicInformation && 	FastIoDispatch->FastIoQueryBasicInfo) || 
			(FileInformationClass ==  FileStandardInformation && FastIoDispatch->FastIoQueryStandardInfo))  
		{ 
 
			// 
			// Call some FastIo routine and remember its return value. 
			// 
 
			BOOLEAN Done; 
 
			if (FileInformationClass ==  FileBasicInformation) 
			{ 
				Done =  FastIoDispatch->FastIoQueryBasicInfo( FileObject,TRUE,(PFILE_BASIC_INFORMATION)FileInformation,&IoStatus,DeviceObject ); 
			} 
 
			else 
			{ 
				Done =  FastIoDispatch->FastIoQueryStandardInfo( FileObject,TRUE,(PFILE_STANDARD_INFORMATION)FileInformation,&IoStatus,DeviceObject ); 
			} 
 
			// 
			// If we are done return to the caller with request's status. 
			// 
 
			if (Done) 
			{ 
				*ResultLength =  IoStatus.Information; 
				return IoStatus.Status; 
			} 
		} 
 
		// 
		// Now we must go through the standard IRP path so 
		// initialize event on which we will occasionaly wait. 
		// 
 
		KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 
 
		// 
		// Allocate the IRP with appropriate number of stack locations. 
		// 
 
		Irp =  IoAllocateIrp(DeviceObject->StackSize, FALSE); 
 
		if (!Irp) 
		{ 
			return STATUS_INSUFFICIENT_RESOURCES; 
		} 
 
		// 
		// Set basic fields in Irp like an OriginalFileObject, Thread and so on. 
		// Also Flags are set to make this request synchronous and buffered. 
		// 
 
		Irp->Tail.Overlay.OriginalFileObject =  FileObject; 
		Irp->Tail.Overlay.Thread =  PsGetCurrentThread(); 
 
		Irp->RequestorMode =  KernelMode; 
		Irp->UserIosb =  &IoStatus; 
		Irp->UserEvent =  &Event; 
 
		SetFlag(Irp->Flags, IRP_SYNCHRONOUS_API | IRP_BUFFERED_IO); 
 
		// 
		// Set basic fields in the next stack location like a MajorFunction 
		// and FileObject. 
		// 
 
		NextIrpSp =  IoGetNextIrpStackLocation(Irp); 
 
		NextIrpSp->MajorFunction =  IRP_MJ_QUERY_INFORMATION; 
		NextIrpSp->FileObject =  FileObject; 
 
		// 
		// Set caller's parameters for this request like Length, Buffer 
		// and FileInformationClass. 
		// 
 
		NextIrpSp->Parameters.QueryFile.Length =  Length; 
		NextIrpSp->Parameters.QueryFile.FileInformationClass =  FileInformationClass; 
 
		Irp->AssociatedIrp.SystemBuffer =  FileInformation; 
 
		// 
		// Before we call the FSD to process this request we must set 
		// completion routine which will be responsible to free the Irp 
		// and to do some little postprocessing. 
		// 
 
		IoSetCompletionRoutine( Irp,FsTPMSynchronousApiCompletion,NULL,TRUE,TRUE,TRUE ); 
 
		// 
		// Call the File System Driver to do the task requested by caller. 
		//	 
 
		Status =  IoCallDriver(DeviceObject, Irp); 
 
		if (Status ==  STATUS_PENDING) 
		{ 
			(VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 
 
			Status =  IoStatus.Status; 
		} 
 
		// 
		// Return to our caller with request's status. 
		// 
 
		*ResultLength =  IoStatus.Information; 
		return Status; 
} 
 
// 
// 
// 
 
NTSTATUS 
FsTPMSetInformationFile ( 
					  IN PVCB Vcb, 
					  IN PFILE_OBJECT FileObject, 
					  IN FILE_INFORMATION_CLASS FileInformationClass, 
					  IN PVOID FileInformation, 
					  IN ULONG Length 
					  ) 
{ 
	PDEVICE_OBJECT DeviceObject =  Vcb->NextLowerDevice; 
	NTSTATUS Status; 
	KEVENT Event; 
	IO_STATUS_BLOCK IoStatus; 
	PIRP Irp; 
	PIO_STACK_LOCATION NextIrpSp; 
 
	// 
	// Initialize event on which we will occasionaly wait. 
	// 
 
	KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 
 
	// 
	// Allocate the IRP with appropriate number of stack locations. 
	// 
 
	Irp =  IoAllocateIrp(DeviceObject->StackSize, FALSE); 
 
	if (!Irp) 
	{ 
		return STATUS_INSUFFICIENT_RESOURCES; 
	} 
 
	// 
	// Set basic fields in Irp like an OriginalFileObject, Thread and so on. 
	// Also Flags are set to make this request synchronous and buffered. 
	// 
 
	Irp->Tail.Overlay.OriginalFileObject =  FileObject; 
	Irp->Tail.Overlay.Thread =  PsGetCurrentThread(); 
 
	Irp->RequestorMode =  KernelMode; 
	Irp->UserIosb =  &IoStatus; 
	Irp->UserEvent =  &Event; 
 
	SetFlag(Irp->Flags, IRP_SYNCHRONOUS_API | IRP_BUFFERED_IO); 
 
	// 
	// Set basic fields in the next stack location like a MajorFunction 
	// and FileObject. 
	// 
 
	NextIrpSp =  IoGetNextIrpStackLocation(Irp); 
 
	NextIrpSp->MajorFunction =  IRP_MJ_SET_INFORMATION; 
	NextIrpSp->FileObject =  FileObject; 
 
	// 
	// Set caller's parameters for this request like Length, Buffer 
	// and FileInformationClass. 
	// 
 
	NextIrpSp->Parameters.SetFile.Length =  Length; 
	NextIrpSp->Parameters.SetFile.FileInformationClass = FileInformationClass; 
 
	Irp->AssociatedIrp.SystemBuffer =  FileInformation; 
 
	// 
	// Do some preprocessing for Rename and Link requests. 
	// 
 
	ASSERT((FileInformationClass <=  FileMaximumInformation) && 
		(FileInformationClass !=  FileModeInformation) && 
		(FileInformationClass !=  FileObjectIdInformation) && 
		(FileInformationClass !=  FileMoveClusterInformation)); 
 
	if (FileInformationClass ==  FileRenameInformation || 
		FileInformationClass ==  FileLinkInformation)  
	{ 
 
		PFILE_RENAME_INFORMATION RenameInfo =  (PFILE_RENAME_INFORMATION)FileInformation; 
 
		ASSERT(RenameInfo->FileNameLength !=  0 && RenameInfo->RootDirectory ==  NULL); 
		NextIrpSp->Parameters.SetFile.ReplaceIfExists =  RenameInfo->ReplaceIfExists; 
	} 
 
	// 
	// Before we call the FSD to process this request we must set 
	// completion routine which will be responsible to free the Irp 
	// and to do some little postprocessing. 
	// 
 
	IoSetCompletionRoutine( Irp,FsTPMSynchronousApiCompletion,NULL,TRUE,TRUE,TRUE ); 
 
	// 
	// Call the File System Driver to do the task requested by caller. 
	// 
 
	Status =  IoCallDriver(DeviceObject, Irp); 
 
	if (Status ==  STATUS_PENDING) 
	{ 
		(VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 
 
		Status =  IoStatus.Status; 
	} 
 
	// 
	// Return to our caller with request's status. 
	//	 
 
	return Status; 
} 
 
// 
// 
// 
 
NTSTATUS 
FsTPMSynchronousApiCompletion ( 
							IN PDEVICE_OBJECT DeviceObject, 
							IN PIRP Irp, 
							IN PVOID Context 
							) 
{ 
	//ASSERT(DeviceObject ==  NULL && Context ==  NULL); 
 
	// 
	// If there is an AuxiliaryBuffer we have to free it. 
	// 
 
	if (Irp->Tail.Overlay.AuxiliaryBuffer !=  NULL) 
	{ 
		ExFreePool(Irp->Tail.Overlay.AuxiliaryBuffer); 
	} 
 
	// 
	// If there is a Mdl associated we have to deal with it 
	// 
 
	if (Irp->MdlAddress) 
	{ 
		PMDL Mdl; 
		KdPrint(("AGFS: Buffered requests should not have an MDL!\n")); 
		KdBreakPoint(); 
 
		// 
		// 
		// 
 
		Mdl =  Irp->MdlAddress; 
 
		while (Mdl !=  NULL) 
		{ 
			MmUnlockPages(Mdl); 
 
			Mdl =  Mdl->Next; 
		} 
 
		IoFreeMdl(Irp->MdlAddress); 
	} 
 
	// 
	// We must copy the IoStatus to UserIosb and set 
	// the user event so the caller wakes up. 
	// 
 
	*Irp->UserIosb =  Irp->IoStatus; 
 
	ASSERT(Irp->UserEvent !=  NULL); 
	KeSetEvent(Irp->UserEvent, EVENT_INCREMENT, FALSE); 
 
	// 
	// Finally free the Irp. 
	// 
 
	IoFreeIrp(Irp); 
 
	// 
	// Prevent the IoCompleteRequest to do anything with 
	// this already freed Irp. 
	// 
 
	return STATUS_MORE_PROCESSING_REQUIRED; 
} 
 
#define  try_return(X)  X; goto try_exit 
NTSTATUS 
FsTPMCreateFile ( 
			  IN PVCB Vcb, 
			  IN ACCESS_MASK DesiredAccess, 
			  IN POBJECT_ATTRIBUTES ObjectAttributes, 
			  IN PLARGE_INTEGER AllocationSize OPTIONAL, 
			  IN ULONG FileAttributes, 
			  IN ULONG ShareAccess, 
			  IN ULONG Disposition, 
			  IN ULONG CreateOptions, 
			  IN PVOID EaBuffer OPTIONAL, 
			  IN ULONG EaLength, 
			  IN ULONG Options, 
			  OUT ULONG *Information, 
			  OUT	PFILE_OBJECT FileObject, 
			  OUT HANDLE *FileHandle OPTIONAL 
			  ) 
{ 
	PIRP Irp = NULL; 
	PFILE_OBJECT NewFileObject = NULL; 
	PDEVICE_OBJECT RealDevice = Vcb->RealDevice; 
	PDEVICE_OBJECT DeviceObject = Vcb->NextLowerDevice; 
	//	PVPB Vpb; 
	IO_SECURITY_CONTEXT SecurityContext; 
	ACCESS_STATE AccessState; 
	PIO_STACK_LOCATION NextIrpSp; 
	IO_STATUS_BLOCK IoStatus; 
	OBJECT_ATTRIBUTES ObjAttr; 
	NTSTATUS Status; 
	KEVENT Event; 
	LARGE_INTEGER AllocSize; 
 
	BOOLEAN CreatedAccessState =  FALSE; 
 
	// <<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 
	// I have no document to introduce AUXDATA 
	// Smith, Joel said: Note the pAuxData variable.   
	//					 Obviously, a 1k nonpaged buffer is overkill, but I haven't  
	//					 yet bothered to try to figure out what SeCreateAccessState  
	//			     	 puts in here. 
	//	 But I have seen another articles which said AUX_DATA just used to  
	// describe that the AUX device, you can see afximpl.h and  
	// http://www.sources.ru/cpp/mfc/t3552.htm . 
	// 
	ULONG *pAuxData=(ULONG*)ExAllocatePool(NonPagedPool, 1024);  
	memset(pAuxData, 0, 1024);  
 
 
	__try 
	{ 
		// 
		// Build AccessState for this create request. 
		// 
 
		Status =  SeCreateAccessState( &AccessState,pAuxData,DesiredAccess,IoGetFileObjectGenericMapping() ); 
 
		if (!NT_SUCCESS(Status)) 
		{ 
			try_return(Status); 
		} 
 
		CreatedAccessState =  TRUE; 
 
		// 
		// Initialize event on which we will occasionaly wait. 
		// 
 
		KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 
 
		// 
		// Allocate an IRP with appropriate number of stack locations. 
		// 
 
		Irp =  IoAllocateIrp(DeviceObject->StackSize, FALSE); 
 
		if (!Irp) 
		{ 
			try_return(Status =  STATUS_INSUFFICIENT_RESOURCES); 
		} 
 
		// 
		// Fill in basic Irp fields like a Thread, RequestorMode and Flags. 
		// 
 
		Irp->Tail.Overlay.Thread =  PsGetCurrentThread(); 
		Irp->RequestorMode =  KernelMode; 
		SetFlag(Irp->Flags, IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API); 
 
		// 
		// Fill in the SecurityContext for this create request. 
		// 
 
		SecurityContext.SecurityQos = (PSECURITY_QUALITY_OF_SERVICE)ObjectAttributes->SecurityQualityOfService; 
		SecurityContext.AccessState =  &AccessState; 
		SecurityContext.DesiredAccess =  DesiredAccess; 
		SecurityContext.FullCreateOptions =  CreateOptions; 
 
		// 
		// Fill in basic fields in the next stack location. 
		// 
 
		NextIrpSp =  IoGetNextIrpStackLocation(Irp); 
 
		NextIrpSp->Control =  0; 
		NextIrpSp->MajorFunction =  IRP_MJ_CREATE; 
		NextIrpSp->Flags =  (UCHAR)Options; 
 
		if (!FlagOn(ObjectAttributes->Attributes, OBJ_CASE_INSENSITIVE)) 
		{ 
			SetFlag(NextIrpSp->Flags, SL_CASE_SENSITIVE); 
		} 
 
		// 
		// Fill in the AllocationSize and EaBuffer. 
		// 
 
		AllocSize.QuadPart =  AllocationSize ? AllocationSize->QuadPart : 0; 
 
		Irp->Overlay.AllocationSize.QuadPart =  AllocSize.QuadPart; 
		Irp->AssociatedIrp.SystemBuffer =  EaBuffer; 
 
		// 
		// Fill in request parameters in next stack location. 
		// 
 
		NextIrpSp->Parameters.Create.Options =  (CreateOptions & 0xFFFFFF) | (Disposition << 24); 
		NextIrpSp->Parameters.Create.FileAttributes = (USHORT)FileAttributes; 
		NextIrpSp->Parameters.Create.ShareAccess =  (USHORT)ShareAccess; 
		NextIrpSp->Parameters.Create.SecurityContext =  &SecurityContext; 
		NextIrpSp->Parameters.Create.EaLength =  EaLength; 
 
		// 
		// Fill in other fields in Irp. 
		// 
 
		Irp->UserIosb =  &IoStatus; 
		Irp->UserEvent =  &Event; 
 
		Irp->MdlAddress =  NULL; 
		Irp->PendingReturned =  FALSE; 
		Irp->Cancel =  FALSE; 
		Irp->CancelRoutine =  NULL; 
		Irp->Tail.Overlay.AuxiliaryBuffer =  NULL; 
 
		// 
		// Create new file object. 
		// 
 
		InitializeObjectAttributes(&ObjAttr, NULL,ObjectAttributes->Attributes, 0, NULL); 
 
		Status =  ObCreateObject( KernelMode, *IoFileObjectType,&ObjAttr,KernelMode,0,sizeof(FILE_OBJECT),0,0,(void**)&NewFileObject ); 
 
		if (!NT_SUCCESS(Status)) 
		{ 
			try_return(Status); 
		} 
 
		// 
		// Zero the file object and initialize type and size. 
		// 
		RtlZeroMemory(NewFileObject, sizeof(FILE_OBJECT)); 
 
		NewFileObject->Type =  IO_TYPE_FILE; 
		NewFileObject->Size =  sizeof(FILE_OBJECT); 
 
		// 
		// Fill in the RelatedFileObject as a RootDirectory. 
		// 
 
		NewFileObject->RelatedFileObject = (PFILE_OBJECT)ObjectAttributes->RootDirectory; 
 
		// 
		// Initialize some more things when the file is for synchronous access. 
		// 
 
		if (FlagOn(CreateOptions, FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) 
		{ 
			SetFlag(NewFileObject->Flags, FO_SYNCHRONOUS_IO); 
 
			if (FlagOn(CreateOptions, FILE_SYNCHRONOUS_IO_ALERT)) 
			{ 
				SetFlag(NewFileObject->Flags, FO_ALERTABLE_IO); 
			} 
 
			KeInitializeEvent(&NewFileObject->Lock, SynchronizationEvent, FALSE); 
 
			NewFileObject->Waiters =  0; 
			NewFileObject->CurrentByteOffset.QuadPart =  0; 
		} 
 
		// 
		// Set some file object flags with respect to CreateOptions. 
		// 
 
 
		if (FlagOn(CreateOptions, FILE_NO_INTERMEDIATE_BUFFERING)) 
		{ 
			SetFlag(NewFileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING); 
		} 
 
		if (FlagOn(CreateOptions, FILE_WRITE_THROUGH)) 
		{	 
			SetFlag(NewFileObject->Flags, FO_WRITE_THROUGH); 
		} 
 
		if (FlagOn(CreateOptions, FILE_SEQUENTIAL_ONLY)) 
		{ 
			SetFlag(NewFileObject->Flags, FO_SEQUENTIAL_ONLY); 
		} 
 
		if (!FlagOn(ObjectAttributes->Attributes, OBJ_CASE_INSENSITIVE)) 
		{ 
			SetFlag(NewFileObject->Flags, FO_OPENED_CASE_SENSITIVE); 
		} 
 
		// 
		// Initialize the DeviceObject field in file object. 
		// 
 
		NewFileObject->DeviceObject =  RealDevice; 
 
		// 
		// If the caller requests no handle we must insert the 
		// file object at this time. 
		// 
 
		if (FileHandle ==  NULL) 
		{ 
			HANDLE Handle; 
 
			// 
			// Insert the file object to the Object Manager 
			// requesting one additional reference. 
			// 
 
			Status =  ObInsertObject( NewFileObject,NULL,DesiredAccess,1,(PVOID*)&NewFileObject,&Handle ); 
 
			if (!NT_SUCCESS(Status)) 
			{ 
				try_return(Status); 
			}	 
 
			// 
			// Close the handle (one reference remains). 
			// 
 
			Status =  NtClose(Handle); 
			ASSERT(NT_SUCCESS(Status)); 
 
			ClearFlag(NewFileObject->Flags, FO_HANDLE_CREATED); 
		} 
 
		// 
		// Associate the NewFileObject with the Irp 
		// 
 
		Irp->Tail.Overlay.OriginalFileObject =  NewFileObject; 
		NextIrpSp->FileObject =  NewFileObject; 
 
		// 
		// If the ObjectAttributes contains some name we must 
		// make a copy for the file object. 
		// 
 
		if (ObjectAttributes->ObjectName->Length) 
		{ 
			PUNICODE_STRING FileName =  ObjectAttributes->ObjectName; 
 
			if (FileName->Length < 0x38) 
			{ 
				NewFileObject->FileName.MaximumLength =  0x38; 
			} 
 
			else if (FileName->Length < 0x78) 
			{ 
				NewFileObject->FileName.MaximumLength =  0x78; 
			} 
 
			else if (FileName->Length < 0xF8) 
			{ 
				NewFileObject->FileName.MaximumLength =  0xF8; 
			} 
 
			else 
			{ 
				NewFileObject->FileName.MaximumLength =  FileName->Length; 
			} 
 
			NewFileObject->FileName.Buffer =(unsigned short *)ExAllocatePool(NonPagedPool, NewFileObject->FileName.MaximumLength); 
 
			if (!NewFileObject->FileName.Buffer) 
			{ 
				try_return(Status =  STATUS_INSUFFICIENT_RESOURCES); 
			} 
 
		} 
		NewFileObject->Vpb=Vcb->pVpb; 
 
		RtlCopyUnicodeString(&NewFileObject->FileName, ObjectAttributes->ObjectName); 
 
		KeInitializeEvent(&NewFileObject->Event, NotificationEvent, FALSE); 
 
		// 
		// Before we call the FSD to process this request we must set 
		// completion routine which will be responsible to free the Irp 
		// and to do some little postprocessing. 
		// 
 
		IoSetCompletionRoutine( Irp,FsTPMSynchronousApiCompletion,NULL,TRUE,TRUE,TRUE ); 
 
		// 
		// Call the File System Driver to do the task requested by caller. 
		// 
 
		Status = IoCallDriver(Vcb->pVpb->DeviceObject, Irp); 
 
		Irp =  NULL; 
 
		if (Status ==  STATUS_PENDING) 
		{ 
			(VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, 	FALSE, NULL); 
			Status =  IoStatus.Status; 
		} 
 
		if (!NT_SUCCESS(Status)) 
		{ 
			try_return(Status); 
		} 
 
		ASSERT(Status !=  STATUS_REPARSE); 
 
		// 
		// Return desired FileObject and Information. 
		// 
 
		FileObject =  NewFileObject; 
		*Information =  IoStatus.Information; 
 
		// 
		// If the caller requests handle now is the right time 
		// to insert the file object into Object Manager. 
		// 
 
		if (FileHandle !=  NULL) 
		{ 
			Status =  ObInsertObject( NewFileObject,NULL,DesiredAccess,0,NULL,FileHandle ); 
			ASSERT(NT_SUCCESS(Status)); 
			SetFlag(NewFileObject->Flags, FO_HANDLE_CREATED); 
		} 
 
		try_exit:NOTHING; 
	} 
 
	__finally 
	{	 
		// 
		// Unwind neccessary things 
		// 
 
		//	ASSERT(!AbnormalTermination());  //<<<<<<<<<<<<FileName.Length) 
				{		 
					ExFreePool(NewFileObject->FileName.Buffer); 
					NewFileObject->FileName.Length =  0; 
				} 
 
				NewFileObject->DeviceObject =  NULL; 
 
				// ASSERT(ObGetObjectPointerCount(NewFileObject) == 1); 
				ObDereferenceObject(NewFileObject); 
			} 
		} 
 
		else 
		{ 
			FsTPMReferenceDeviceAndVpb(NewFileObject); 
		} 
		ExFreePool(pAuxData); 
 
	} 
 
	return Status; 
 
} 
 
 
// 
//  本函数用于创建目录,可以有如下形式的参数:  C:\  , C:\WINDOWS\ , C:\WINDOWS\A.TXT ,注意 完整的目录应最后至少有一个"\ " 
//  若其后还跟有文件名,本函数可以忽略文件名 
// 
NTSTATUS 
FsTPMCreateDirectory( 
					   const WCHAR *pDir 
					   ) 
{ 
	FILE_OBJECT DirectoryFileObject; 
	HANDLE DirectoryHandle; 
	NTSTATUS ntStatus; 
	UNICODE_STRING Uni_Dir; 
	OBJECT_ATTRIBUTES DirectoryAttributes; 
	int Layer=-1,Len=FsTPMwcslen(pDir),pos,TmpLayer; 
	ULONG ThrowInf; // We don't want to see the value of the returned informatiom 
	UNICODE_STRING UDir={0}; 
	// So throw it. 
 
 
	while (Pos=Len) || (L'\\'==pDir[++pos] && TmpLayer==0))) 
			if (L'\\'==pDir[pos]) 
				--TmpLayer; 
		if (pos>=Len) 
			break; 
 
		ASSERT((pos>=0 && pos<=Len)); 
 
		pos++; 
 
		Uni_Dir.Buffer=(PWCHAR)ExAllocatePool(PagedPool,(pos+1)*sizeof(WCHAR)); 
		ASSERT((Uni_Dir.Buffer!=NULL)); 
		Uni_Dir.MaximumLength=Uni_Dir.Length=(pos+1)*sizeof(WCHAR); 
		RtlCopyMemory(Uni_Dir.Buffer,pDir,(pos+1)*sizeof(WCHAR)); 
		Uni_Dir.Buffer[pos]=0; 
 
		RtlInitUnicodeString(&UDir,&(Uni_Dir.Buffer[2])); 
 
		// Then we should initialize the file object's attributes 
		InitializeObjectAttributes( 
			&DirectoryAttributes, 
			&UDir, 
			OBJ_CASE_INSENSITIVE, 
			NULL, NULL 
			); 
 
		ntStatus=FsTPMCreateFile(&(((PHOOK_EXTENSION)(DriveHookDevices[pDir[0]-L'A']->DeviceExtension))->Vcb), 
			FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA, 
			&DirectoryAttributes, 
			0, 
			FILE_ATTRIBUTE_NORMAL, 
			FILE_SHARE_READ|FILE_SHARE_WRITE, 
			FILE_OPEN_IF , 
			FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE|FILE_NO_INTERMEDIATE_BUFFERING, 
			NULL, 
			0, 
			FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE|FILE_NO_INTERMEDIATE_BUFFERING, 
			&ThrowInf, 
			&DirectoryFileObject, 
			&DirectoryHandle 
			); 
		if (!NT_SUCCESS(ntStatus)) 
		{ 
			FsTPM_DbgPrint(("Create %S Failed! Reason:",Uni_Dir.Buffer)); 
			ErrorString(ntStatus); 
 
			ExFreePool(Uni_Dir.Buffer); 
			return ntStatus; 
		} 
		NtClose(DirectoryHandle); 
 
		ExFreePool(Uni_Dir.Buffer); 
	} 
	return STATUS_SUCCESS; 
} 
 
 
// 
// 注意:pAnsiString 要求在函数调用前已经分配好空间 
// 
NTSTATUS  
GetFileFullNameByObjectA( 
						IN PFILE_OBJECT FileObject, 
						IN PHOOK_EXTENSION hookExt, 
						IN OUT PCHAR pAnsiString, 
						IN int       StringLength 
						) 
{	 
	CHAR CUFileName[512]={0}; 
	CHAR Temp[512]={0}; 
	int ret; 
	PFILE_OBJECT RelateObject; 
 
	ASSERT(pAnsiString!=NULL); 
	ret=_snprintf(CUFileName,511,"%S",FileObject->FileName.Buffer); 
 
	if (ret<0) 
	{ 
		return (!STATUS_SUCCESS); 
	} 
 
     RelateObject=FileObject->RelatedFileObject; 
 
	if ('\\'!=CUFileName[0] && NULL!=RelateObject &&  
		NULL!=RelateObject->FileName.Buffer && 0!=RelateObject->FileName.Length) 
	{ 
		if (RelateObject->FileName.Buffer[RelateObject->FileName.Length/2-1]==L'\\' ) 
		{ 
			_snprintf(Temp,511,"%S%s",RelateObject->FileName.Buffer,CUFileName); 
			copy_inA(CUFileName,512,Temp); 
		}    
		else 
		{ 
			_snprintf(Temp,511,"%S\\%s",RelateObject->FileName.Buffer,CUFileName); 
			copy_inA(CUFileName,512,Temp); 
		} 
	} 
	if ('\\'!=CUFileName[0]) 
	{ 
		_snprintf(Temp,511,"X:\\%s",CUFileName); 
		copy_inA(CUFileName,512,Temp); 
	} 
	else 
	{ 
		_snprintf(Temp,511,"X:%s",CUFileName); 
		copy_inA(CUFileName,512,Temp); 
	} 
 
	ASSERT((CUFileName[2]=='\\' && CUFileName[3]!='\\')); 
 
	CUFileName[0]=hookExt->LogicalDrive; 
 
	ret=_snprintf(pAnsiString,StringLength,"%s",CUFileName); 
	if (ret<0) 
		return (!STATUS_SUCCESS); 
	else 
		return (STATUS_SUCCESS); 
} 
 
 
// 
// 注意:pWString 要求在函数调用前已经分配好空间 
// 
NTSTATUS  
GetFileFullNameByObjectW( 
						 IN PFILE_OBJECT FileObject, 
						 IN PHOOK_EXTENSION hookExt, 
						 IN OUT WCHAR * pWString, 
						 IN int       StringLength 
						 ) 
{	 
	WCHAR Temp[256]; 
	WCHAR CUFileName[256]={0}; 
	int ret=_snwprintf(CUFileName,255,L"%s",FileObject->FileName.Buffer); 
	PFILE_OBJECT RelateObject; 
 
	ASSERT(pWString!=NULL); 
 
	if (ret<0) 
	{ 
		return (!STATUS_SUCCESS); 
	} 
 
	RelateObject=FileObject->RelatedFileObject; 
 
	if (L'\\'!=CUFileName[0] && NULL!=RelateObject &&  
		NULL!=RelateObject->FileName.Buffer && 0!=RelateObject->FileName.Length) 
	{ 
		if (RelateObject->FileName.Buffer[RelateObject->FileName.Length/2-1]==L'\\' ) 
		{ 
			_snwprintf(Temp,255,L"%s%s",RelateObject->FileName.Buffer,CUFileName); 
			copy_inW(CUFileName,255,Temp); 
		}    
		else 
		{ 
			_snwprintf(Temp,255,L"%s\\%s",RelateObject->FileName.Buffer,CUFileName); 
			copy_inW(CUFileName,255,Temp); 
		} 
	} 
	if (L'\\'!=CUFileName[0]) 
	{ 
		_snwprintf(Temp,255,L"X:\\%s",CUFileName); 
		copy_inW(CUFileName,255,Temp); 
	} 
	else 
	{ 
		_snwprintf(Temp,255,L"X:%s",CUFileName); 
		copy_inW(CUFileName,255,Temp); 
	} 
 
	ASSERT((CUFileName[2]==L'\\' && CUFileName[3]!=L'\\')); 
 
	CUFileName[0]=(WCHAR)hookExt->LogicalDrive; 
 
	ret=_snwprintf(pWString,StringLength-1,L"%s",CUFileName); 
	if (ret<0) 
		return (!STATUS_SUCCESS); 
	else 
		return (STATUS_SUCCESS); 
} 
 
BOOL  
Is_Exist_File( 
			  PHOOK_EXTENSION pHookExt, 
			  PFILE_OBJECT pFileObject 
			  ) 
{ 
	WCHAR     WTarget[512]={0}; 
 
	UNICODE_STRING  CUTarget; 
 
	PFILE_OBJECT	  pTargetFileObject=NULL;  
	HANDLE			  TargetFileHandle; 
	FILE_OBJECT		  TargetFileObject; 
	VCB				  TargetVCB; 
	OBJECT_ATTRIBUTES TargetAttributes; 
 
	ULONG ThrowInf; // We don't want to see the value of the returned informatiom 
	// So throw it. 
	NTSTATUS ntStatus; 
 
 
	RtlInitUnicodeString(&CUTarget,WTarget); 
	CUTarget.MaximumLength=1024; 
 
	_snwprintf(WTarget,511,L"X:%s",pFileObject->FileName.Buffer); 
 
	WTarget[0]=(WCHAR)pHookExt->LogicalDrive; 
	// Build VCB. here , the next lower device and real device are the same 
	TargetVCB=pHookExt->Vcb; 
	// Then we should initialize the file object's attributes 
	InitializeObjectAttributes( 
		&TargetAttributes, 
		&CUTarget, 
		OBJ_CASE_INSENSITIVE, 
		NULL, NULL 
		); 
 
	ntStatus=FsTPMCreateFile(&TargetVCB, 
		FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA, 
		&TargetAttributes, 
		0, 
		FILE_ATTRIBUTE_NORMAL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		FILE_OPEN , 
		FILE_SYNCHRONOUS_IO_NONALERT, 
		NULL, 
		0, 
		FILE_SYNCHRONOUS_IO_NONALERT, 
		&ThrowInf, 
		&TargetFileObject, 
		&TargetFileHandle 
		); 
 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Create Target File Failed!\n")); 
		ZwClose(TargetFileHandle); 
		return FALSE; 
	} 
 
	ZwClose(TargetFileHandle); 
 
	ObDereferenceObject( &TargetFileObject ); 
 
	return TRUE; 
} 
 
BOOL  
Is_Directory_File( 
				  ULONG Options 
				  ) 
{ 
	if (Options & FILE_DIRECTORY_FILE) 
		return TRUE;	 
	else 
		return FALSE; 
} 
 
 
// 
//TargetFileName like C:\A.TXT , SourceFileName is so  
// 
NTSTATUS  
FsTPMCopyFileByName( 
					  IN WCHAR* TargetFileName, 
					  IN WCHAR* SourceFileName, 
					  IN PFILE_OBJECT pSourceFileObject 
					  ) 
{ 
	// We make the string like this "\??\B:\*.*" 
	WCHAR           UTarget[256]=L""; 
	UNICODE_STRING	CUTarget; 
 
	WCHAR           USource[256]=L""; 
	UNICODE_STRING	CUSource; 
 
	PFILE_OBJECT pTargetFileObject=NULL;  
	HANDLE		 TargetFileHandle=NULL,SourceFileHandle=NULL; 
	FILE_OBJECT TargetFileObject,SourceFileObject; 
	VCB				  TargetVCB,SourceVCB; 
	OBJECT_ATTRIBUTES TargetAttributes,SourceAttributes; 
 
	ULONG ThrowInf; // We don't want to see the value of the returned informatiom 
	// So throw it. 
	NTSTATUS ntStatus; 
 
	_snwprintf(UTarget,255,L"%s",TargetFileName); 
	RtlInitUnicodeString(&CUTarget,&UTarget[2]); 
	CUTarget.MaximumLength=512; 
	_snwprintf(USource,255,L"%s",SourceFileName); 
	RtlInitUnicodeString(&CUSource,&USource[2]); 
	CUSource.MaximumLength=512; 
 
 
	// We should make sure the path's name is like this : "C:\*\*.*" 
	ASSERT( (TargetFileName[0]>=L'A' && TargetFileName[0]<=L'Z')&& 
		(SourceFileName[0]>=L'A' && SourceFileName[0]<=L'Z')); 
 
	ntStatus=FsTPMCreateDirectory(UTarget); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Create Directory Fail!\n")); 
		return ntStatus; 
	} 
 
	FsTPM_DbgPrint(("Enter Copy File now!!!\n")); 
 
	// Build VCB. here , the next lower device and real device are the same 
	TargetVCB=((PHOOK_EXTENSION)(DriveHookDevices[TargetFileName[0]-L'A']->DeviceExtension))->Vcb; 
 
	SourceVCB=((PHOOK_EXTENSION)(DriveHookDevices[SourceFileName[0]-L'A']->DeviceExtension))->Vcb; 
 
	// Then we should initialize the file object's attributes 
	InitializeObjectAttributes( 
		&TargetAttributes, 
		&CUTarget, 
		OBJ_CASE_INSENSITIVE, 
		NULL, NULL 
		); 
 
	ntStatus=FsTPMCreateFile(&TargetVCB, 
		FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA, 
		&TargetAttributes, 
		0, 
		FILE_ATTRIBUTE_NORMAL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		FILE_OPEN_IF , 
		FILE_SYNCHRONOUS_IO_NONALERT, 
		NULL, 
		0, 
		FILE_SYNCHRONOUS_IO_NONALERT, 
		&ThrowInf, 
		&TargetFileObject, 
		&TargetFileHandle 
		); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Create Target File Failed!")); 
		ErrorString(ntStatus); 
 
		return ntStatus; 
	} 
	ntStatus = ObReferenceObjectByHandle( TargetFileHandle, FILE_READ_DATA|FILE_WRITE_DATA,  
		NULL, KernelMode, (void**)&pTargetFileObject, NULL ); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Get Target File Object Fail :Reason: ")); 
		ErrorString(ntStatus); 
		return ntStatus; 
	}  
 
	ASSERT(pTargetFileObject!=NULL); 
 
 
	if (NULL==pSourceFileObject) 
	{ 
		InitializeObjectAttributes( 
			&SourceAttributes, 
			&CUSource, 
			OBJ_CASE_INSENSITIVE, 
			NULL, NULL 
			); 
 
		ntStatus=FsTPMCreateFile(&SourceVCB, 
			FILE_READ_DATA|SYNCHRONIZE, 
			&SourceAttributes, 
			0, 
			FILE_ATTRIBUTE_NORMAL, 
			FILE_SHARE_READ|FILE_SHARE_WRITE, 
			FILE_OPEN_IF , 
			FILE_SYNCHRONOUS_IO_ALERT, 
			NULL, 
			0, 
			FILE_SYNCHRONOUS_IO_ALERT, 
			&ThrowInf, 
			&SourceFileObject, 
			&SourceFileHandle 
			);	 
 
		if (!NT_SUCCESS(ntStatus)) 
		{ 
			FsTPM_DbgPrint(("Create Source File Failed!")); 
			ErrorString(ntStatus); 
 
			return ntStatus; 
		} 
 
		ntStatus = ObReferenceObjectByHandle( SourceFileHandle, FILE_READ_DATA,  
			NULL, KernelMode, (void**)&pSourceFileObject, NULL ); 
 
		if (!NT_SUCCESS(ntStatus)) 
		{ 
			FsTPM_DbgPrint(("Get Source File Object Fail :Reason: ")); 
			ErrorString(ntStatus); 
 
		}  
		ASSERT(pSourceFileObject!=NULL); 
	} 
	else 
	{ 
		// FsTPM_DbgPrint(("Source File Object Count = %d \n",ObGetObjectPointerCount(pSourceFileObject))); 
 
		ntStatus = ObReferenceObjectByPointer( pSourceFileObject, FILE_READ_DATA,  
			NULL,KernelMode ); 
 
		if (!NT_SUCCESS(ntStatus)) 
		{ 
			FsTPM_DbgPrint(("Inc File Object Count  Error: ")); 
			ErrorString(ntStatus); 
			return ntStatus; 
		}  
	} 
	 
	ntStatus=FsTPMCopyFile(pTargetFileObject,pSourceFileObject,SourceVCB.NextLowerDevice,TargetVCB.NextLowerDevice); 
 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Copy File Failed!")); 
		ErrorString(ntStatus); 
 
		return ntStatus; 
	} 
	else 
	{ 
		FsTPM_DbgPrint((("Copy File Success! \n"))); 
	} 
 
 
	// We should close the handle 
	ObDereferenceObject(pTargetFileObject); 
 
	ObDereferenceObject(pSourceFileObject); 
 
	// FsTPM_DbgPrint(("After Dereference Source File Object Count = %d \n",ObGetObjectPointerCount(pSourceFileObject))); 
 
	FsTPM_DbgPrint((("Now Close Source File !\n"))); 
 
	if (NULL!=SourceFileHandle) 
	{ 
		ntStatus=ZwClose(SourceFileHandle); 
		if (!NT_SUCCESS(ntStatus)) 
		{ 
			FsTPM_DbgPrint(("Close Source File Failed! ")); 
			ErrorString(ntStatus); 
			return ntStatus; 
		} 
	} 
 
	FsTPM_DbgPrint((("Now Close Source File !\n"))); 
 
	ntStatus=ZwClose(TargetFileHandle); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Close Target File Failed!")); 
		ErrorString(ntStatus); 
		return ntStatus; 
	} 
	return STATUS_SUCCESS; 
} 
 
 
NTSTATUS 
FsTPMCopyFile( 
				PFILE_OBJECT TargetFileObject,  
				PFILE_OBJECT SourceFileObject, 
				PDEVICE_OBJECT pSourceDeviceObject, 
				PDEVICE_OBJECT pTargetDeviceObject 
				) 
				//++ 
				// Function:	FsTPMCopyFile 
				// 
				// Description: 
				//		Copy file  
				// 
				// Arguments: 
				//		TargetFileObject - Target file object  
				//		SourceFileObject - Source file object 
				// 
				// Return value: 
				//		STATUS_SUCCESS if successful, 
				//		STATUS_UNSUCCESSFUL otherwise 
				// 
				// Notice : 
				//		This function is provided by OSR 
				//-- 
{ 
	PVOID buffer; 
	PMDL mdl; 
	IO_STATUS_BLOCK iosb; 
	FILE_STANDARD_INFORMATION standardInformation; 
	LARGE_INTEGER currentOffset; 
	LONGLONG bytesToTransfer; 
 
 
	// 
	// The algorithm used by this routine is straight-forward: read 64k chunks from the 
	// source file and write it to the target file, until the entire file itself has been copied. 
	// 
 
	buffer = ExAllocatePoolWithTag(NonPagedPool, 
		MAX_TRANSFER_SIZE, 
		'BcfK'); 
 
 
	if (!buffer) { 
		// 
		// Allocation must have failed. 
		// 
 
		return STATUS_INSUFFICIENT_RESOURCES; 
 
	} 
 
	// 
	// Build an MDL describing the buffer.  We'll use THAT to do the 
	// I/O (rather than a direct buffer address.) 
	// 
 
	mdl = IoAllocateMdl(buffer, MAX_TRANSFER_SIZE, FALSE, TRUE, 0); 
 
	MmBuildMdlForNonPagedPool(mdl); 
 
	// 
	// Set up the current offset information 
	// 
 
	currentOffset.QuadPart = 0; 
 
	// 
	// Get the size of the input file. 
	// 
 
	FsTPMGetFileStandardInformation(SourceFileObject, &standardInformation, &iosb,pSourceDeviceObject); 
 
	if (!NT_SUCCESS(iosb.Status)) { 
		// 
		// This is a failure condition. 
		// 
 
		return (iosb.Status); 
 
	} 
 
	// 
	// Set the allocation size of the output file. 
	// 
 
	FsTPMSetFileAllocation(TargetFileObject, 
		&standardInformation.AllocationSize, 
		&iosb,pTargetDeviceObject); 
 
	if (!NT_SUCCESS(iosb.Status)) { 
 
		// 
		// Failure... 
		// 
 
		return (iosb.Status); 
 
	} 
 
	// 
	// Save away the information about the # of bytes to transfer. 
	// 
 
	bytesToTransfer = standardInformation.EndOfFile.QuadPart; 
 
	// 
	// Now copy the source to the target until we run out... 
	// 
 
	while (bytesToTransfer) { 
		ULONG nextTransferSize; 
 
		// 
		// The # of bytes to copy in the next operation is based upon the maximum of 
		// the balance IN the file, or KFC_MAX_TRANSFER_SIZE 
		// 
 
		nextTransferSize = (bytesToTransfer < MAX_TRANSFER_SIZE) ? 
			(ULONG) bytesToTransfer : MAX_TRANSFER_SIZE; 
 
		FsTPMRead(SourceFileObject, ¤tOffset, nextTransferSize, mdl, &iosb,pSourceDeviceObject); 
 
		if (!NT_SUCCESS(iosb.Status)) { 
 
			// 
			// An error condition occurred. 
			// 
 
			return (iosb.Status); 
 
		} 
 
		FsTPMWrite(TargetFileObject, ¤tOffset, nextTransferSize, mdl, &iosb,pTargetDeviceObject); 
 
		if (!NT_SUCCESS(iosb.Status)) { 
 
			// 
			// An error condition occurred. 
			// 
 
			return (iosb.Status); 
 
		} 
 
		// 
		// Now, update the offset/bytes to transfer information 
		// 
 
		currentOffset.QuadPart += nextTransferSize; 
 
		bytesToTransfer -= nextTransferSize; 
 
	} 
 
	// 
	// At this point, we're done with the copy operation.  Return success 
	//  
 
	return (STATUS_SUCCESS); 
} 
 
 
// Notice  you should be sure that the file is shared. 
NTSTATUS 
FsTPMCreateFileObject( 
						IN PWCHAR TargetFileName, 
						OUT PFILE_OBJECT* ppFileObject 
						) 
{ 
	//WCHAR  *UTarget=NULL; 
	//UTarget=(WCHAR*)ExAllocatePool(NonPagedPool,512); 
 
	WCHAR UTarget[256]; 
	UNICODE_STRING CUTarget; 
	PFILE_OBJECT pTargetFileObject=NULL;  
	HANDLE		 TargetFileHandle; 
	FILE_OBJECT TargetFileObject; 
	VCB				  TargetVCB; 
	OBJECT_ATTRIBUTES TargetAttributes; 
 
	ULONG ThrowInf; // We don't want to see the value of the returned informatiom 
	// So throw it. 
	NTSTATUS ntStatus; 
 
	_snwprintf(UTarget,256,L"\\??\\%s",TargetFileName); 
	RtlInitUnicodeString(&CUTarget,UTarget); 
	CUTarget.MaximumLength=512; 
 
	// We should make sure the path's name is like this : "C:\*\*.*" 
	ASSERT( (TargetFileName[0]>=L'A' && TargetFileName[0]<=L'Z')); 
 
	ntStatus=FsTPMCreateDirectory(TargetFileName); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Create Directory Fail!\n")); 
		ErrorString(ntStatus); 
		return ntStatus; 
	} 
 
	FsTPM_DbgPrint(("Enter Create File Object now!!!\n")); 
 
	// Build VCB. here , the next lower device and real device are the same 
	TargetVCB=((PHOOK_EXTENSION)(DriveHookDevices[TargetFileName[0]-'A']->DeviceExtension))->Vcb; 
	// Then we should initialize the file object's attributes 
	InitializeObjectAttributes( 
		&TargetAttributes, 
		&CUTarget, 
		OBJ_CASE_INSENSITIVE, 
		NULL, NULL 
		); 
 
//	ntStatus=ZwCreateFile(&TargetFileHandle, 
//				FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA|DELETE, 
//				&TargetAttributes, 
//				&temp, 
//				0, 
//				FILE_ATTRIBUTE_NORMAL, 
//				FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
//				FILE_OPEN_IF , 
//				FILE_SYNCHRONOUS_IO_ALERT, 
//				NULL, 
//				0 
//				); 
//				 
	ntStatus=FsTPMCreateFile(&TargetVCB, 
		FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA|DELETE, 
		&TargetAttributes, 
		0, 
		FILE_ATTRIBUTE_NORMAL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 
		FILE_OPEN_IF , 
		FILE_SYNCHRONOUS_IO_ALERT, 
		NULL, 
		0, 
		FILE_SYNCHRONOUS_IO_ALERT, 
		&ThrowInf, 
		&TargetFileObject, 
		&TargetFileHandle 
		); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(("Create Target File Failed!")); 
		ErrorString(ntStatus); 
		return ntStatus; 
	} 
	ntStatus = ObReferenceObjectByHandle( TargetFileHandle, FILE_READ_DATA|FILE_WRITE_DATA,  
		NULL, KernelMode, (void**)&pTargetFileObject, NULL ); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint((("Get Target File Object Fail\n"))); 
		ErrorString(ntStatus); 
		return ntStatus; 
	}  
	ASSERT(pTargetFileObject!=NULL); 
 
	*ppFileObject=pTargetFileObject; 
 
	return STATUS_SUCCESS; 
} 
 
 
VOID  
FsTPMWriteIRP( 
			 PFILE_OBJECT FileObject, 
			 PDEVICE_OBJECT   pDevice, 
			 PIRP             pOrgIrp, 
			 PIO_STACK_LOCATION pOrgIoStk, 
			 PIO_STATUS_BLOCK IoStatusBlock, 
			 PMDL mdl 
			 ) 
			 //++ 
			 // Function:	FsTPMWriteIRP 
			 // 
			 // Description: 
			 //		This routine is used to write to the file object from memory discribed by MDL 
			 // 
			 // Arguments: 
			 //PFILE_OBJECT     FileObject, 
			 //PDEVICE_OBJECT   pDevice, 
			 //PIRP             pOrgIrp, 
			 //PIO_STACK_LOCATION pOrgIoStk 
			 //PIO_STATUS_BLOCK IoStatusBlock, 
			 // 
			 // Return value: 
			 //		None 
{ 
	PIRP irp; 
	KEVENT event; 
	PIO_STACK_LOCATION ioStackLocation; 
	PDEVICE_OBJECT fsdDevice =pDevice; 
 
	// 
	// Set up the event we'll use. 
	// 
 
	KeInitializeEvent(&event, SynchronizationEvent, FALSE); 
 
 
	// 
	// Allocate and build the IRP we'll be sending to the FSD. 
	// 
 
	irp = IoAllocateIrp(fsdDevice->StackSize, FALSE); 
 
	if (!irp) { 
 
		// 
		// Allocation failed, presumably due to memory allocation failure. 
		// 
 
		IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES; 
 
		IoStatusBlock->Information = 0; 
		 
		return ; 
	} 
 
	irp->AssociatedIrp.SystemBuffer = pOrgIrp->AssociatedIrp.SystemBuffer; 
 
	irp->MdlAddress = pOrgIrp->MdlAddress; 
 
	irp->UserBuffer=pOrgIrp->UserBuffer; 
 
	irp->UserEvent = &event; 
 
	irp->UserIosb = IoStatusBlock; 
 
	irp->Tail.Overlay.Thread = PsGetCurrentThread(); 
 
	irp->Tail.Overlay.OriginalFileObject= FileObject; 
 
	irp->RequestorMode = KernelMode; 
 
 
	// 
	// Indicate that this is a WRITE operation. 
	// 
 
	irp->Flags = IRP_WRITE_OPERATION; 
 
 
	// 
	// Set up the next I/O stack location.  These are the parameters 
	// that will be passed to the underlying driver. 
	// 
 
	ioStackLocation = IoGetNextIrpStackLocation(irp); 
 
	ioStackLocation->MajorFunction = pOrgIoStk->MajorFunction; 
 
	ioStackLocation->MinorFunction = pOrgIoStk->MinorFunction; 
 
	ioStackLocation->DeviceObject = fsdDevice; 
 
	ioStackLocation->FileObject = FileObject; 
 
 
	// 
	// We use a completion routine to keep the I/O Manager from doing 
	// "cleanup" on our IRP - like freeing our MDL. 
	// 
 
	IoSetCompletionRoutine(irp, KfcIoCompletion, 0, TRUE, TRUE, TRUE); 
 
	ioStackLocation->Parameters.Write.Length = pOrgIoStk->Parameters.Write.Length; 
 
	ioStackLocation->Parameters.Write.ByteOffset = pOrgIoStk->Parameters.Write.ByteOffset; 
 
	ioStackLocation->Parameters.Write.Key = pOrgIoStk->Parameters.Write.Key; 
 
 
	// 
	// Send it on.  Ignore the return code. 
	// 
 
	(void) IoCallDriver(fsdDevice, irp); 
 
 
	// 
	// Wait for the I/O to complete. 
	// 
 
	KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); 
 
 
	// 
	// Done.  Return results are in the io status block. 
	// 
 
	return; 
 
} 
 
 
 
NTSTATUS  
GetFileFullNameByQuery(	 
					   OUT PUNICODE_STRING SourceFileName, 
					   IN  PHOOK_EXTENSION pHookExt , 
					   IN	PFILE_OBJECT  FileObject 
					   ) 
{ 
	VCB Vcb; 
	ULONG ResultLen; 
	NTSTATUS ntStatus; 
 
	WCHAR   USName[256]; 
 
	_snwprintf(USName,256,L"A:"); 
 
	UNICODE_STRING CUSourceName; 
 
	RtlInitUnicodeString(&CUSourceName,USName); 
	CUSourceName.MaximumLength=512; 
 
	Vcb=pHookExt->Vcb; 
 
	PFILE_NAME_INFORMATION fileNameInfo; 
 
	if (0==FileObject->FileName.Length)   // 我不知道为什么会有这样的情况 
		return STATUS_UNSUCCESSFUL; 
 
	//调查"家底",确认其真实文件名 
	fileNameInfo = (PFILE_NAME_INFORMATION)ExAllocatePool( NonPagedPool, MAXPATHLEN*sizeof(WCHAR)); 
 
	if (NULL==fileNameInfo) 
	{ 
		FsTPM_DbgPrint((("Memory Allocate Fail!\n"))); 
		if (fileNameInfo!=NULL) 
			ExFreePool(fileNameInfo); 
		return STATUS_UNSUCCESSFUL; 
	} 
	ntStatus=FsTPMQueryInformationFile(&Vcb,FileObject,FileNameInformation,fileNameInfo,(MAXPATHLEN-5)*sizeof(WCHAR),&ResultLen); 
	if (!NT_SUCCESS(ntStatus)) 
	{ 
		FsTPM_DbgPrint(((" Query Name Information of file Fail\n"))); 
		ErrorString(ntStatus); 
		if (fileNameInfo!=NULL) 
			ExFreePool(fileNameInfo); 
		return ntStatus; 
	} 
 
	fileNameInfo->FileName[fileNameInfo->FileNameLength/2]=0; 
 
	_snwprintf(CUSourceName.Buffer+wcslen(CUSourceName.Buffer),256-wcslen(CUSourceName.Buffer),L"%s",fileNameInfo->FileName); 
 
	CUSourceName.Buffer[0]=(WCHAR)(pHookExt->LogicalDrive); 
 
	CUSourceName.Length=wcslen(CUSourceName.Buffer)*sizeof(WCHAR); 
 
	RtlCopyUnicodeString( SourceFileName, &(UNICODE_STRING)CUSourceName ); 
 
	if (fileNameInfo!=NULL) 
		ExFreePool(fileNameInfo); 
 
	return STATUS_SUCCESS; 
} 
 
 
 
VOID CreateFileSizeZero(PUNICODE_STRING pUniFile,BOOL isdir) 
{ 
	// Then we should initialize the file object's attributes 
	UNICODE_STRING uFile; 
	FILE_OBJECT fileobject; 
	HANDLE      fileHandle; 
	ULONG       ThrowInf; 
 
	ULONG op1; 
	ULONG op2; 
	NTSTATUS ntStatus; 
	OBJECT_ATTRIBUTES FileAttrib; 
 
	RtlInitUnicodeString(&uFile,&pUniFile->Buffer[2]); 
	 
	InitializeObjectAttributes( 
		&FileAttrib, 
		&uFile, 
		OBJ_CASE_INSENSITIVE, 
		NULL, NULL 
		); 
 
	if (isdir) 
	{ 
		op1=FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING|FILE_DIRECTORY_FILE; 
		op2=FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING|FILE_DIRECTORY_FILE; 
	} 
	else 
	{ 
		op1=FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING; 
		op2=FILE_SYNCHRONOUS_IO_NONALERT|FILE_NO_INTERMEDIATE_BUFFERING; 
	} 
 
	ntStatus=FsTPMCreateFile(&(((PHOOK_EXTENSION)(DriveHookDevices[pUniFile->Buffer[0]-L'A']->DeviceExtension))->Vcb), 
		FILE_READ_DATA|SYNCHRONIZE|FILE_WRITE_DATA, 
		&FileAttrib, 
		0, 
		FILE_ATTRIBUTE_NORMAL, 
		FILE_SHARE_READ|FILE_SHARE_WRITE, 
		FILE_CREATE , 
		op1, 
		NULL, 
		0, 
		op2, 
		&ThrowInf, 
		&fileobject, 
		&fileHandle 
		); 
 
	ZwClose(fileHandle); 
} 
 
 
//---------------------------------------------------------------------- 
// 
// FsTPMGetProcess 
// 
// Uses undocumented data structure offsets to obtain the name of the 
// currently executing process. 
// 
//---------------------------------------------------------------------- 
PCHAR 
FsTPMGetProcess(  
				  PCHAR ProcessName  
				  ) 
{ 
	PEPROCESS       curproc; 
	char            *nameptr; 
	//    ULONG           i; 
 
	// 
	// We only do this if we determined the process name offset 
	// 
	if( ProcessNameOffset ) { 
 
		// 
		// Get a pointer to the current process block 
		// 
		curproc = PsGetCurrentProcess(); 
 
		// 
		// Dig into it to extract the name. Make sure to leave enough room 
		// in the buffer for the appended process ID. 
		// 
		nameptr   = (PCHAR) curproc + ProcessNameOffset; 
 
		strncpy( ProcessName, nameptr, NT_PROCNAMELEN-1 ); 
		ProcessName[NT_PROCNAMELEN-1] = 0; 
		//       sprintf( ProcessName + strlen(ProcessName), ":%d", PsGetCurrentProcessId()); 
 
	} else { 
 
		strcpy( ProcessName, "???" ); 
	} 
	return ProcessName; 
} 
 
//---------------------------------------------------------------------- 
// 
// FsTPMGetProcessNameOffset 
// 
// In an effort to remain version-independent, rather than using a 
// hard-coded into the KPEB (Kernel Process Environment Block), we 
// scan the KPEB looking for the name, which should match that 
// of the system process. This is because we are in the system process' 
// context in DriverEntry, where this is called. 
// 
//---------------------------------------------------------------------- 
ULONG  
FsTPMGetProcessNameOffset( 
						  VOID 
						  ) 
{ 
	PEPROCESS       curproc; 
	int             i; 
 
	curproc = PsGetCurrentProcess(); 
 
	// 
	// Scan for 12KB, hoping the KPEB never grows that big! 
	// 
	for( i = 0; i < 3*PAGE_SIZE; i++ ) { 
 
		if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) { 
 
			return i; 
		} 
	} 
 
	// 
	// Name not found - oh, well 
	// 
	return 0; 
}