You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
9.2 KiB
287 lines
9.2 KiB
// @doc
|
|
/**********************************************************************
|
|
*
|
|
* @module CTRL.c |
|
|
*
|
|
* Entry points for handling IRPs to the "Control" device object.
|
|
*
|
|
* History
|
|
* ----------------------------------------------------------
|
|
* Mitchell S. Dernis Original
|
|
*
|
|
* (c) 1986-1998 Microsoft Corporation. All right reserved.
|
|
*
|
|
* @topic CTRL |
|
|
* The control device object is used for programming GcKernel.
|
|
* The main module, GckShell, delegates IRPs aimed at the control device
|
|
* here.
|
|
*
|
|
**********************************************************************/
|
|
#define __DEBUG_MODULE_IN_USE__ GCK_CTRL_C
|
|
|
|
#include <wdm.h>
|
|
#include <gckshell.h>
|
|
#include "debug.h"
|
|
|
|
//
|
|
// Mark the pageable routines as such
|
|
//
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text (INIT, GCK_CTRL_DriverEntry)
|
|
#pragma alloc_text (PAGE, GCK_CTRL_Create)
|
|
#pragma alloc_text (PAGE, GCK_CTRL_Close)
|
|
#pragma alloc_text (PAGE, GCK_CTRL_Unload)
|
|
#endif
|
|
|
|
// Allow debug output for this module, and set the intial level
|
|
DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL) );
|
|
|
|
/***********************************************************************************
|
|
**
|
|
** NTSTATUS GCK_CTRL_DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath )
|
|
**
|
|
** @func Initializing the portions of the driver related to the control device, actually
|
|
** All of this was added to GCK_CTRL_AddDevice, which is called when the first filter
|
|
** device is added.
|
|
**
|
|
** @rdesc STATUS_SUCCESS or various errors
|
|
**
|
|
*************************************************************************************/
|
|
NTSTATUS GCK_CTRL_DriverEntry
|
|
(
|
|
IN PDRIVER_OBJECT pDriverObject, // @parm Driver Object
|
|
IN PUNICODE_STRING puniRegistryPath // @parm Path to driver specific registry section.
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER (puniRegistryPath);
|
|
UNREFERENCED_PARAMETER (pDriverObject);
|
|
|
|
PAGED_CODE();
|
|
|
|
GCK_DBG_ENTRY_PRINT(("Entering GCK_CTRL_DriverEntry\n"));
|
|
|
|
//
|
|
// Initialize Globals
|
|
//
|
|
GCK_DBG_TRACE_PRINT(("Initializing CTRL globals\n"));
|
|
Globals.pControlObject = NULL;
|
|
|
|
|
|
GCK_DBG_EXIT_PRINT (("Exiting GCK_CTRL_DriverEntry: STATUS_SUCCESS\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/***********************************************************************************
|
|
**
|
|
** NTSTATUS GCK_CTRL_AddDevice( IN PDRIVER_OBJECT pDriverObject )
|
|
**
|
|
** @func Adds a Control Device. Called from GCK_FLTR_AddDevice when the first
|
|
** Device is added.
|
|
**
|
|
** @rdesc STATUS_SUCCESS, or various error codes
|
|
**
|
|
*************************************************************************************/
|
|
NTSTATUS
|
|
GCK_CTRL_AddDevice
|
|
(
|
|
IN PDRIVER_OBJECT pDriverObject
|
|
)
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PDEVICE_OBJECT pDeviceObject;
|
|
UNICODE_STRING uniNtNameString;
|
|
UNICODE_STRING uniWin32NameString;
|
|
PGCK_CONTROL_EXT pControlExt;
|
|
|
|
PAGED_CODE();
|
|
|
|
GCK_DBG_ENTRY_PRINT(("Entering GCK_CTRL_AddDevice\n"));
|
|
|
|
//
|
|
// Create a controlling device object. All control commands to the
|
|
// filter driver come via IOCTL's to this device object. It lives
|
|
// for the lifetime of the filter driver.
|
|
//
|
|
RtlInitUnicodeString (&uniNtNameString, GCK_CONTROL_NTNAME);
|
|
NtStatus = IoCreateDevice (
|
|
pDriverObject,
|
|
sizeof (GCK_CONTROL_EXT),
|
|
&uniNtNameString,
|
|
FILE_DEVICE_UNKNOWN,
|
|
0, // No standard device characteristics
|
|
FALSE, // This isn't an exclusive device
|
|
&pDeviceObject
|
|
);
|
|
|
|
if(!NT_SUCCESS (NtStatus))
|
|
{
|
|
GCK_DBG_CRITICAL_PRINT (("Couldn't create the device. Status: 0x%0.8x\n", NtStatus));
|
|
return NtStatus ;
|
|
}
|
|
|
|
//
|
|
// Create W32 symbolic link name
|
|
//
|
|
GCK_DBG_TRACE_PRINT(("Creating symbolic link\n"));
|
|
RtlInitUnicodeString (&uniWin32NameString, GCK_CONTROL_SYMNAME);
|
|
NtStatus = IoCreateSymbolicLink (&uniWin32NameString, &uniNtNameString);
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
GCK_DBG_CRITICAL_PRINT (("Couldn't create the symbolic Status: 0x%0.8x\n", NtStatus));
|
|
IoDeleteDevice (pDeviceObject);
|
|
return NtStatus;
|
|
}
|
|
|
|
//
|
|
// Initialize Globals
|
|
//
|
|
GCK_DBG_TRACE_PRINT(("Initializing CTRL globals\n"));
|
|
Globals.pControlObject = pDeviceObject;
|
|
|
|
GCK_DBG_TRACE_PRINT(("Initializing Control Device\n"));
|
|
pControlExt = pDeviceObject->DeviceExtension;
|
|
pControlExt->ulGckDevObjType = GCK_DO_TYPE_CONTROL; //Put our name on this, so we can speak for him later
|
|
pControlExt->lOutstandingIO = 1; // biassed to 1. Transition to zero signals Remove event
|
|
Globals.pControlObject->Flags |= DO_BUFFERED_IO;
|
|
Globals.pControlObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
GCK_DBG_EXIT_PRINT (("Normal exit of GCK_CTRL_AddDevice: 0x%0.8x\n", NtStatus));
|
|
return NtStatus;
|
|
}
|
|
|
|
/***********************************************************************************
|
|
**
|
|
** VOID GCK_CTRL_Remove()
|
|
**
|
|
** @func Removes the one and only Control Device. Called from GCK_FLTR_Remove
|
|
** when all of the Filter devices go away. This was necessary, as
|
|
** the PnP loader won't unload you if you still have devices around
|
|
** even if they are legacy, and even if it started your driver.
|
|
**
|
|
** @rdesc None
|
|
**
|
|
*************************************************************************************/
|
|
VOID
|
|
GCK_CTRL_Remove()
|
|
{
|
|
NTSTATUS NtStatus;
|
|
PGCK_CONTROL_EXT pControlExt;
|
|
UNICODE_STRING uniWin32NameString;
|
|
GCK_DBG_ENTRY_PRINT(("Entering GCK_CTRL_Remove\n"));
|
|
if( Globals.pControlObject)
|
|
{
|
|
GCK_DBG_TRACE_PRINT(("Removing Global Control Device\n"));
|
|
|
|
//BUGBUG
|
|
//BUGBUG Should be counting outstanding IRPs and blocking here until they
|
|
//BUGBUG complete, before removing this.
|
|
//BUGBUG
|
|
|
|
//Kill the symbolic link we created on open
|
|
RtlInitUnicodeString (&uniWin32NameString, GCK_CONTROL_SYMNAME);
|
|
NtStatus = IoDeleteSymbolicLink(&uniWin32NameString);
|
|
ASSERT( NT_SUCCESS(NtStatus) );
|
|
if( NT_SUCCESS(NtStatus) )
|
|
{
|
|
//Delete the device
|
|
IoDeleteDevice(Globals.pControlObject);
|
|
Globals.pControlObject = NULL;
|
|
}
|
|
}
|
|
GCK_DBG_EXIT_PRINT (("Exiting GCK_CTRL_Remove\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
/***********************************************************************************
|
|
**
|
|
** NTSTATUS GCK_CTRL_Create ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp )
|
|
**
|
|
** @func Handles the IRP_MJ_CREATE for the control device - Call generated by
|
|
** Win32 API CreateFile or OpenFile.
|
|
**
|
|
** @rdesc STATUS_SUCCESS, or various error codes
|
|
**
|
|
*************************************************************************************/
|
|
NTSTATUS GCK_CTRL_Create (
|
|
IN PDEVICE_OBJECT pDeviceObject, // @parm DO target for IRP
|
|
IN PIRP pIrp // @parm IRP
|
|
)
|
|
{
|
|
PGCK_CONTROL_EXT pControlExt;
|
|
|
|
PAGED_CODE ();
|
|
|
|
GCK_DBG_ENTRY_PRINT(("Entering GCK_CTRL_Create\n"));
|
|
|
|
//Cast device extension
|
|
pControlExt = (PGCK_CONTROL_EXT) pDeviceObject->DeviceExtension;
|
|
|
|
// Just an extra sanity check
|
|
ASSERT( GCK_DO_TYPE_CONTROL == pControlExt->ulGckDevObjType);
|
|
|
|
//free access to control devices
|
|
pIrp->IoStatus.Information = 0;
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
//Return
|
|
GCK_DBG_EXIT_PRINT(("Exiting GCK_CTRL_Create\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/***********************************************************************************
|
|
**
|
|
** NTSTATUS GCK_CTRL_Close ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp )
|
|
**
|
|
** @func Handles IRP_MJ_CLOSE for the control device - Call generated by Win32 API CloseFile
|
|
**
|
|
** @rdesc STATUS_SUCCESS or various errors
|
|
**
|
|
*************************************************************************************/
|
|
NTSTATUS GCK_CTRL_Close (
|
|
IN PDEVICE_OBJECT pDeviceObject, // @parm DO target for IRP
|
|
IN PIRP pIrp // @parm IRP
|
|
)
|
|
{
|
|
PGCK_CONTROL_EXT pControlExt;
|
|
PGCK_FILTER_EXT pFilterExt;
|
|
PDEVICE_OBJECT pFilterDeviceObject;
|
|
PFILE_OBJECT pFileObject;
|
|
|
|
PAGED_CODE ();
|
|
|
|
GCK_DBG_ENTRY_PRINT(("Entering GCK_CTRL_Close\n"));
|
|
|
|
//Cast device extension
|
|
pControlExt = (PGCK_CONTROL_EXT) pDeviceObject->DeviceExtension;
|
|
|
|
//Get file object from IRP
|
|
pFileObject = IoGetCurrentIrpStackLocation(pIrp)->FileObject;
|
|
|
|
// Just an extra sanity check
|
|
ASSERT( GCK_DO_TYPE_CONTROL == pControlExt->ulGckDevObjType);
|
|
|
|
//Close Test Mode for any device it was opened for
|
|
//- if it was open by this handle - if it wasn't open this is a no-op
|
|
ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
|
|
pFilterDeviceObject = Globals.pFilterObjectList;
|
|
ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
|
|
while(pFilterDeviceObject)
|
|
{
|
|
pFilterExt = (PGCK_FILTER_EXT)pFilterDeviceObject->DeviceExtension;
|
|
GCKF_EndTestScheme(pFilterExt, pFileObject);
|
|
ExAcquireFastMutex(&Globals.FilterObjectListFMutex);
|
|
pFilterDeviceObject = pFilterExt->pNextFilterObject;
|
|
ExReleaseFastMutex(&Globals.FilterObjectListFMutex);
|
|
}
|
|
|
|
//free access to control devices
|
|
pIrp->IoStatus.Information = 0;
|
|
pIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
|
|
|
|
//Return
|
|
GCK_DBG_EXIT_PRINT(("Exiting GCK_CTRL_Close.\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|