www.pudn.com > filesys.rar > devcntrl.c


/************************************************************************* 
* 
* File: devcntrl.c 
* 
* Module: Sample File System Driver (Kernel mode execution only) 
* 
* Description: 
*	Contains code to handle the "Device IOCTL" dispatch entry point. 
* 
* Author: R. Nagar 
* 
* (c) 1996-97 Rajeev Nagar, All Rights Reserved 
* 
*************************************************************************/ 
 
#include			"sfsd.h" 
 
// define the file specific bug-check id 
#define			SFSD_BUG_CHECK_ID				SFSD_FILE_DEVICE_CONTROL 
 
#if(_WIN32_WINNT < 0x0400) 
#define IOCTL_REDIR_QUERY_PATH   CTL_CODE(FILE_DEVICE_NETWORK_FILE_SYSTEM, 99, METHOD_NEITHER, FILE_ANY_ACCESS) 
 
typedef struct _QUERY_PATH_REQUEST { 
    ULONG PathNameLength; 
    PIO_SECURITY_CONTEXT SecurityContext; 
    WCHAR FilePathName[1]; 
} QUERY_PATH_REQUEST, *PQUERY_PATH_REQUEST; 
 
typedef struct _QUERY_PATH_RESPONSE { 
    ULONG LengthAccepted; 
} QUERY_PATH_RESPONSE, *PQUERY_PATH_RESPONSE; 
#endif 
 
 
/************************************************************************* 
* 
* Function: SFsdDeviceControl() 
* 
* Description: 
*	The I/O Manager will invoke this routine to handle a Device IOCTL 
*	request 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 
*	to be deferred to a worker thread context) 
* 
* Return Value: STATUS_SUCCESS/Error 
* 
*************************************************************************/ 
NTSTATUS SFsdDeviceControl( 
PDEVICE_OBJECT		DeviceObject,		// the logical volume device object 
PIRP					Irp)					// I/O Request Packet 
{ 
	NTSTATUS				RC = STATUS_SUCCESS; 
   PtrSFsdIrpContext	PtrIrpContext = NULL; 
	BOOLEAN				AreWeTopLevel = FALSE; 
 
	FsRtlEnterFileSystem(); 
	ASSERT(DeviceObject); 
	ASSERT(Irp); 
 
	// set the top level context 
	AreWeTopLevel = SFsdIsIrpTopLevel(Irp); 
 
	try { 
 
		// get an IRP context structure and issue the request 
		PtrIrpContext = SFsdAllocateIrpContext(Irp, DeviceObject); 
		ASSERT(PtrIrpContext); 
 
		RC = SFsdCommonDeviceControl(PtrIrpContext, Irp); 
 
	} except (SFsdExceptionFilter(PtrIrpContext, GetExceptionInformation())) { 
 
		RC = SFsdExceptionHandler(PtrIrpContext, Irp); 
 
		SFsdLogEvent(SFSD_ERROR_INTERNAL_ERROR, RC); 
	} 
 
	if (AreWeTopLevel) { 
		IoSetTopLevelIrp(NULL); 
	} 
 
	FsRtlExitFileSystem(); 
 
	return(RC); 
} 
 
 
 
/************************************************************************* 
* 
* Function: SFsdCommonDeviceControl() 
* 
* Description: 
*	The actual work is performed here. This routine may be invoked in one' 
*	of the two possible contexts: 
*	(a) in the context of a system worker thread 
*	(b) in the context of the original caller 
* 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS/Error 
* 
*************************************************************************/ 
NTSTATUS	SFsdCommonDeviceControl( 
PtrSFsdIrpContext			PtrIrpContext, 
PIRP							PtrIrp) 
{ 
	NTSTATUS					RC = STATUS_SUCCESS; 
	PIO_STACK_LOCATION	PtrIoStackLocation = NULL; 
	PIO_STACK_LOCATION	PtrNextIoStackLocation = NULL; 
	PFILE_OBJECT			PtrFileObject = NULL; 
	PtrSFsdFCB				PtrFCB = NULL; 
	PtrSFsdCCB				PtrCCB = NULL; 
	PtrSFsdVCB				PtrVCB = NULL; 
	BOOLEAN					CompleteIrp = FALSE; 
	ULONG						IoControlCode = 0; 
	void						*BufferPointer = NULL; 
 
	try { 
		// First, get a pointer to the current I/O stack location 
		PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 
		ASSERT(PtrIoStackLocation); 
 
		PtrFileObject = PtrIoStackLocation->FileObject; 
		ASSERT(PtrFileObject); 
 
		PtrCCB = (PtrSFsdCCB)(PtrFileObject->FsContext2); 
		ASSERT(PtrCCB); 
		PtrFCB = PtrCCB->PtrFCB; 
		ASSERT(PtrFCB); 
 
		if (PtrFCB->NodeIdentifier.NodeType == SFSD_NODE_TYPE_VCB) { 
			PtrVCB = (PtrSFsdVCB)(PtrFCB); 
		} else { 
			PtrVCB = PtrFCB->PtrVCB; 
		} 
 
		// Get the IoControlCode value 
		IoControlCode = PtrIoStackLocation->Parameters.DeviceIoControl.IoControlCode; 
 
		// You may wish to allow only	volume open operations. 
 
		switch (IoControlCode) { 
#ifdef	__THIS_IS_A_NETWORK_REDIR_ 
		case IOCTL_REDIR_QUERY_PATH: 
			// Only for network redirectors. 
			BufferPointer = (void *)(PtrIoStackLocation->Parameters.DeviceIoControl.Type3InputBuffer); 
			// Invoke the handler for this IOCTL. 
			RC = SFsdHandleQueryPath(BufferPointer); 
			CompleteIrp = TRUE; 
			try_return(RC); 
			break; 
#endif	// _THIS_IS_A_NETWORK_REDIR_ 
		default: 
			// Invoke the lower level driver in the chain. 
			PtrNextIoStackLocation = IoGetNextIrpStackLocation(PtrIrp); 
			*PtrNextIoStackLocation = *PtrIoStackLocation; 
			// Set a completion routine. 
			IoSetCompletionRoutine(PtrIrp, SFsdDevIoctlCompletion, NULL, TRUE, TRUE, TRUE); 
			// Send the request. 
			RC = IoCallDriver(PtrVCB->TargetDeviceObject, PtrIrp); 
			break; 
		} 
 
		try_exit:	NOTHING; 
 
	} finally { 
 
		// Release the IRP context 
		if (!(PtrIrpContext->IrpContextFlags & SFSD_IRP_CONTEXT_EXCEPTION)) { 
			// Free up the Irp Context 
			SFsdReleaseIrpContext(PtrIrpContext); 
 
			if (CompleteIrp) { 
				PtrIrp->IoStatus.Status = RC; 
				PtrIrp->IoStatus.Information = 0; 
	 
				// complete the IRP 
				IoCompleteRequest(PtrIrp, IO_DISK_INCREMENT); 
			} 
		} 
	} 
 
	return(RC); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdDevIoctlCompletion() 
* 
* Description: 
*	Completion routine. 
*	 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS 
* 
*************************************************************************/ 
NTSTATUS SFsdDevIoctlCompletion( 
PDEVICE_OBJECT			PtrDeviceObject, 
PIRP						PtrIrp, 
void						*Context) 
{ 
	if (PtrIrp->PendingReturned) { 
		IoMarkIrpPending(PtrIrp); 
	} 
 
	return(STATUS_SUCCESS); 
} 
 
 
/************************************************************************* 
* 
* Function: SFsdHandleQueryPath() 
* 
* Description: 
*	Handle the MUP request. 
*	 
* Expected Interrupt Level (for execution) : 
* 
*  IRQL_PASSIVE_LEVEL 
* 
* Return Value: STATUS_SUCCESS 
* 
*************************************************************************/ 
NTSTATUS SFsdHandleQueryPath( 
void			*BufferPointer) 
{ 
	NTSTATUS					RC = STATUS_SUCCESS; 
	PQUERY_PATH_REQUEST	RequestBuffer = (PQUERY_PATH_REQUEST)BufferPointer; 
	PQUERY_PATH_RESPONSE	ReplyBuffer = (PQUERY_PATH_RESPONSE)BufferPointer; 
	ULONG						LengthOfNameToBeMatched = RequestBuffer->PathNameLength; 
	ULONG						LengthOfMatchedName = 0; 
   WCHAR                *NameToBeMatched = RequestBuffer->FilePathName; 
 
	// So here we are. Simply check the name supplied. 
	// You can use whatever algorithm you like to determine whether the 
	// sent in name is acceptable. 
	// The first character in the name is always a "\" 
	// If you like the name sent in (probably, you will like a subset 
	// of the name), set the matching length value in LengthOfMatchedName. 
 
	// if (FoundMatch) { 
	//		ReplyBuffer->LengthAccepted = LengthOfMatchedName; 
	// } else { 
	//		RC = STATUS_OBJECT_NAME_NOT_FOUND; 
	// } 
 
	return(RC); 
}