Leaked source code of windows server 2003
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.
 
 
 
 
 
 

648 lines
19 KiB

// @doc
/**********************************************************************
*
* @module GckShell.c |
*
* Basic driver entry points for GcKernel.sys
*
* History
* ----------------------------------------------------------
* Mitchell S. Dernis Original
*
* (c) 1986-1998 Microsoft Corporation. All right reserved.
*
* @topic GckShell |
* Contains the most basic driver entry points (that any NT\WDM driver
* would have) for GcKernel.sys.
*
**********************************************************************/
#define __DEBUG_MODULE_IN_USE__ GCK_GCKSHELL_C
#include <wdm.h>
#include "Debug.h"
#include "GckShell.h"
#include "vmmid.h"
#ifdef BUILD_98
extern void* KeyBoardHook(void);
#endif
//
// Mark the pageable routines as such
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, GCK_Create)
#pragma alloc_text (PAGE, GCK_Close)
#pragma alloc_text (PAGE, GCK_Unload)
#endif
//
// Allow debug output for this moduel, and set the intial level
//
DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL));
//
// Instance the global variables
//
GCK_GLOBALS Globals;
ULONG ulWaitTime = 30;
#ifdef BUILD_98
#pragma data_seg("_LDATA", "LCODE")
LONG g_lHookRefCount = 0;
ULONG g_rgdwKeyEvents[50] = { 0 };
ULONG g_pPreviousKeyhook = 0;
UCHAR g_ucWriteIndex = 0;
UCHAR g_ucReadIndex = 0;
#pragma data_seg()
#pragma code_seg("_LTEXT", "LCODE")
#endif BUILD_98
void KeyHookC(ULONG dwScanCode)
{
#ifdef BUILD_98
g_rgdwKeyEvents[g_ucWriteIndex++] = dwScanCode;
if (g_ucWriteIndex >= 50)
{
g_ucWriteIndex = 0;
}
#else !BUILD_98
UNREFERENCED_PARAMETER (dwScanCode);
#endif BUILD_98
}
#ifdef BUILD_98
//-----------------------------------------------------------------------------
// InitHook - Sets up the keyboard hook
//-----------------------------------------------------------------------------
BOOLEAN HookKeyboard(void)
{
volatile ULONG dwHook = (ULONG)KeyBoardHook;
RtlZeroMemory((void*)g_rgdwKeyEvents, sizeof(ULONG) * 50);
g_ucWriteIndex = 0;
g_ucReadIndex = 0;
// GetVxDServiceOrdinal eax, VKD_Filter_Keyboard_Input
__asm mov eax, __VKD_Filter_Keyboard_Input
__asm mov esi, dwHook
VxDCall(__Hook_Device_Service)
__asm jc initfail
__asm mov [g_pPreviousKeyhook], esi // Since we are using C we can't use the funky callback
return TRUE;
initfail:
return FALSE;
};
#pragma code_seg()
void UnHookKeyboard()
{
volatile ULONG dwHook = (ULONG)KeyBoardHook;
// GetVxDServiceOrdinal eax, VKD_Filter_Keyboard_Input
__asm mov eax, __VKD_Filter_Keyboard_Input
__asm mov esi, dwHook
VxDCall(__Unhook_Device_Service)
__asm clc
}
#endif BUILD_98
/***********************************************************************************
**
** NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath )
**
** @func Standard DriverEntry routine
**
** @rdesc STATUS_SUCCESS or various errors
**
*************************************************************************************/
NTSTATUS DriverEntry
(
IN PDRIVER_OBJECT pDriverObject, // @parm Driver Object
IN PUNICODE_STRING puniRegistryPath // @parm Path to driver specific registry section.
)
{
NTSTATUS NtStatus = STATUS_SUCCESS;
int i;
UNREFERENCED_PARAMETER (puniRegistryPath);
PAGED_CODE();
GCK_DBG_CRITICAL_PRINT(("Built %s at %s\n", __DATE__, __TIME__));
GCK_DBG_CRITICAL_PRINT(("Entering DriverEntry, pDriverObject = 0x%0.8x, puniRegistryPath = %s\n", pDriverObject, puniRegistryPath));
// Allow Control Device module to initialize itself
NtStatus = GCK_CTRL_DriverEntry(pDriverObject, puniRegistryPath);
if( NT_ERROR(NtStatus) )
{
return NtStatus;
}
// Allow Filter Device module to initialize itself
NtStatus = GCK_FLTR_DriverEntry(pDriverObject, puniRegistryPath);
if( NT_ERROR(NtStatus) )
{
return NtStatus;
}
// Allow SideWinder Virtual Bus module to initialize itself
NtStatus = GCK_SWVB_DriverEntry(pDriverObject, puniRegistryPath);
if( NT_ERROR(NtStatus) )
{
return NtStatus;
}
// Allow SideWinder Virtual Keyboard module to initialize itself
NtStatus = GCK_VKBD_DriverEntry(pDriverObject, puniRegistryPath);
if( NT_ERROR(NtStatus) )
{
return NtStatus;
}
// Hook all IRPs so we can pass them on.
GCK_DBG_TRACE_PRINT(("Filling out entry point structure\n"));
for (i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = GCK_Pass;
}
// Initialize any shared global data
#ifdef BUILD_98
g_lHookRefCount = 0;
#endif
// Define entries for IRPs we expect to handle
pDriverObject->MajorFunction[IRP_MJ_CREATE] = GCK_Create;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = GCK_Close;
pDriverObject->MajorFunction[IRP_MJ_READ] = GCK_Read;
pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GCK_Ioctl;
pDriverObject->MajorFunction[IRP_MJ_PNP] = GCK_PnP;
pDriverObject->MajorFunction[IRP_MJ_POWER] = GCK_Power;
pDriverObject->DriverExtension->AddDevice = GCK_FLTR_AddDevice; //only the filter has an add device
pDriverObject->DriverUnload = GCK_Unload;
GCK_DBG_EXIT_PRINT (("Normal exit of DriverEntry: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** VOID GCK_Unload(IN PDRIVER_OBJECT pDriverObject )
**
** @func Called to unload driver, delete Control Device here
**
*************************************************************************************/
VOID GCK_Unload
(
IN PDRIVER_OBJECT pDriverObject // @parm Driver Object for our driver
)
{
PAGED_CODE ();
GCK_DBG_ENTRY_PRINT(("Entering GCK_Unload, pDriverObject = 0x%0.8x\n", pDriverObject));
UNREFERENCED_PARAMETER(pDriverObject);
GCK_SWVB_UnLoad();
//
// We should not be unloaded until all the PDOs have been removed from
// our queue. The control device object should be the only thing left.
//
ASSERT (NULL == pDriverObject->DeviceObject);
ASSERT (NULL == Globals.pControlObject);
GCK_DBG_EXIT_PRINT(("Exiting GCK_Unload\n"));
return;
}
/***********************************************************************************
**
** NTSTATUS GCK_Create ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp )
**
** @func Handles the IRP_MJ_CREATE - Generated by Win32 CreateFile or OpenFile
**
** @rdesc STATUS_SUCCESS, or various error codes
**
*************************************************************************************/
NTSTATUS GCK_Create (
IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for context of IRP
IN PIRP pIrp // @parm pointer to IRP
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
PAGED_CODE ();
GCK_DBG_ENTRY_PRINT (("GCK_Create, pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
KdPrint(("GCK_Create, pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
KdPrint((" -- GCK_DO_TYPE_CONTROL\n"));
NtStatus = GCK_CTRL_Create(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_FILTER:
KdPrint((" -- GCK_DO_TYPE_FILTER\n"));
NtStatus = GCK_FLTR_Create(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
KdPrint((" -- GCK_DO_TYPE_SWVB\n"));
NtStatus = GCK_SWVB_Create(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
NtStatus = STATUS_UNSUCCESSFUL;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_Create. Status: 0x%0.8x\n", NtStatus));
KdPrint(("Exiting GCK_Create. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_Close ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp )
**
** @func Handles IRP_MJ_CLOSE - Generated by Win32 CloseFile
**
** @rdesc STATUS_SUCCESS or various errors
**
*************************************************************************************/
NTSTATUS GCK_Close (
IN PDEVICE_OBJECT pDeviceObject, // @parm pointer DeviceObject for context
IN PIRP pIrp // @parm pointer to IRP to handle
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
PAGED_CODE ();
GCK_DBG_ENTRY_PRINT (("GCK_Close, pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
NtStatus = GCK_CTRL_Close(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_FILTER:
NtStatus = GCK_FLTR_Close(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
NtStatus = GCK_SWVB_Close(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
NtStatus = STATUS_UNSUCCESSFUL;
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_Close. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_Read (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
**
** @func Handles IRP_MJ_READ - Generated by Win32 ReadFile
**
** @rdesc STATUS_SUCCESS, or various errors
**
*************************************************************************************/
NTSTATUS GCK_Read
(
IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object as our context
IN PIRP pIrp // @parm IRP to handle
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
GCK_DBG_RT_ENTRY_PRINT(("Entering GCK_Read. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
NtStatus = STATUS_NOT_SUPPORTED;
//Assert as we shouldn't get read on the control device
ASSERT( NT_SUCCESS(NtStatus) );
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
break;
case GCK_DO_TYPE_FILTER:
NtStatus = GCK_FLTR_Read(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
NtStatus = GCK_SWVB_Read(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
NtStatus = STATUS_UNSUCCESSFUL;
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_Read. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_Power (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
**
** @func Handles IRP_MJ_POWER
**
** @rdesc STATUS_SUCCESS, or various errors
**
*************************************************************************************/
NTSTATUS GCK_Power
(
IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for our context
IN PIRP pIrp // @parm IRP to handle
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
GCK_DBG_ENTRY_PRINT(("Entering GCK_Power. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
NtStatus = STATUS_NOT_SUPPORTED;
//Assert as we shouldn't get power on the control device
ASSERT( NT_SUCCESS(NtStatus) );
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
break;
case GCK_DO_TYPE_FILTER:
NtStatus = GCK_FLTR_Power(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
NtStatus = GCK_SWVB_Power(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
NtStatus = STATUS_UNSUCCESSFUL;
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_Power. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_PnP (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
**
** @func Handles IRP_MJ_PnP
**
** @rdesc STATUS_SUCCESS, or various errors
**
*************************************************************************************/
NTSTATUS GCK_PnP
(
IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for our context
IN PIRP pIrp // @parm IRP to handle
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
GCK_DBG_ENTRY_PRINT(("Entering GCK_PnP. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
NtStatus = STATUS_NOT_SUPPORTED;
//Assert as we shouldn't get PnP on the control device
ASSERT( NT_SUCCESS(NtStatus) );
pIrp->IoStatus.Status = NtStatus;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
break;
case GCK_DO_TYPE_FILTER:
NtStatus = GCK_FLTR_PnP(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
NtStatus = GCK_SWVB_PnP(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
NtStatus = STATUS_UNSUCCESSFUL;
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_PnP. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_Ioctl (IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
**
** @func Handles IRP_MJ_IOCTL and IRP_MJ_INTERNAL_IOCTL
**
** @rdesc STATUS_SUCCES, or various errors
**
*************************************************************************************/
NTSTATUS GCK_Ioctl
(
IN PDEVICE_OBJECT pDeviceObject, // @parm pointer to Device Object
IN PIRP pIrp // @parm pointer to IRP
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
ULONG uIoctl;
PIO_STACK_LOCATION pIrpStack;
GCK_DBG_ENTRY_PRINT(("Entering GCK_Ioctl. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
uIoctl = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
if (uIoctl == IOCTL_GCK_ENABLE_KEYHOOK)
{ // Special case IOCTL, device independant
#ifdef BUILD_WIN2K
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
#else !BUILD_WIN2K
if (InterlockedIncrement(&g_lHookRefCount) == 1)
{ // Not already hooked
HookKeyboard();
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
#endif BUILD_WIN2K
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
if (uIoctl == IOCTL_GCK_DISABLE_KEYHOOK)
{ // Special case also device independant
#ifdef BUILD_WIN2K
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
#else !BUILD_WIN2K
if (InterlockedDecrement(&g_lHookRefCount) < 1)
{ // Last hooker is going away
UnHookKeyboard();
g_lHookRefCount = 0;
}
pIrp->IoStatus.Status = STATUS_SUCCESS;
#endif BUILD_WIN2K
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
if (uIoctl == IOCTL_GCK_GET_KEYHOOK_DATA)
{
#ifdef BUILD_WIN2K
NtStatus = STATUS_UNSUCCESSFUL;
#else !BUILD_WIN2K
ULONG uOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
if (uOutLength < sizeof(ULONG))
{
NtStatus = STATUS_BUFFER_TOO_SMALL;
}
else
{
ULONG* pulIoBuffer = (ULONG*)(pIrp->AssociatedIrp.SystemBuffer);
*pulIoBuffer = 0;
pIrp->IoStatus.Information = sizeof(ULONG);
NtStatus = STATUS_SUCCESS;
if (g_lHookRefCount > 0)
{ // There is a hook
if (g_ucWriteIndex != g_ucReadIndex)
{ // We have data in the Queue
*pulIoBuffer = g_rgdwKeyEvents[g_ucReadIndex++];
if (g_ucReadIndex >= 50)
{
g_ucReadIndex = 0;
}
}
}
}
#endif BUILD_WIN2K
pIrp->IoStatus.Status = NtStatus;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return NtStatus;
}
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_CONTROL:
NtStatus = GCK_CTRL_Ioctl(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_FILTER:
NtStatus = GCK_FLTR_Ioctl(pDeviceObject, pIrp);
break;
case GCK_DO_TYPE_SWVB:
NtStatus = GCK_SWVB_Ioctl(pDeviceObject, pIrp);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
NtStatus = STATUS_UNSUCCESSFUL;
}
GCK_DBG_EXIT_PRINT(("Exiting GCK_Ioctl. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}
/***********************************************************************************
**
** NTSTATUS GCK_Pass ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp )
**
** @func Passes on unhandled IRPs to lower drivers DEBUG version trace out info
** Cannot be pageable since we have no idea what IRPs we're getting.
**
** @rdesc STATUS_SUCCESS, various errors
**
*************************************************************************************/
NTSTATUS GCK_Pass (
IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object as our context
IN PIRP pIrp // @parm IRP to pass on
)
{
NTSTATUS NtStatus;
ULONG ulGckDevObjType;
PGCK_FILTER_EXT pFilterExt;
// Debug version want IRP stack for traceouts.
#if (DBG==1)
PIO_STACK_LOCATION pIrpStack;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
#endif
GCK_DBG_ENTRY_PRINT(("Entering GCK_Pass. pDO = 0x%0.8x, pIrp = 0x%0.8x\n", pDeviceObject, pIrp));
GCK_DBG_TRACE_PRINT(
(
"GCK_Pass called with Irp MajorFunction = 0x%0.8x, MinorFunction = 0x%0.8x\n",
pIrpStack->MajorFunction, pIrpStack->MinorFunction)
);
ulGckDevObjType = *(PULONG)pDeviceObject->DeviceExtension;
switch(ulGckDevObjType)
{
case GCK_DO_TYPE_FILTER:
GCK_DBG_TRACE_PRINT(( "Passing IRP to lower driver\n"));
pFilterExt = (PGCK_FILTER_EXT)pDeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation (pIrp);
NtStatus = IoCallDriver (pFilterExt->pTopOfStack, pIrp);
break;
case GCK_DO_TYPE_CONTROL:
case GCK_DO_TYPE_SWVB:
// No one to pass to, so return default status
NtStatus = pIrp->IoStatus.Status;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
break;
default:
//
// If this assertion is hit, this Device Object was never properly initialized
// by GcKernel, or it has been trashed.
//
ASSERT(FALSE);
NtStatus = STATUS_UNSUCCESSFUL;
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
};
//return
GCK_DBG_EXIT_PRINT(("Exiting GCK_Pass. Status: 0x%0.8x\n", NtStatus));
return NtStatus;
}