Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

371 lines
10 KiB

/////////////////////////////////////////////////////////
//
// Copyright (c) 2001 Microsoft Corporation
//
// Module Name:
// events.cpp
//
// Abstract:
// This module contains code which sets/clears the event handlers
//
//////////////////////////////////////////////////////////
#include "sysvars.h"
//////////////////////////////////////////////////////////////
// private constants, types, and prototypes
//////////////////////////////////////////////////////////////
const PCHAR strFunc1 = "TSSetEventHandler";
const PCHAR strFuncP1 = "TSSetEventComplete";
//
// information necessary to complete the command
//
struct EVENT_CONTEXT
{
PIRP pUpperIrp; // irp from dll to complete
};
typedef EVENT_CONTEXT *PEVENT_CONTEXT;
//
// completion function
//
TDI_STATUS
TSSetEventComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
//
// dummy event handlers
//
TDI_STATUS
TSErrorHandler(
PVOID pvTdiEventContext,
TDI_STATUS lStatus
);
TDI_STATUS
TSSendPossibleHandler(
PVOID pvTdiEventContext,
PVOID pvConnectionContext,
ULONG ulBytesAvailable
);
TDI_STATUS
TSErrorExHandler(
PVOID pvTdiEventContext,
TDI_STATUS lStatus,
PVOID pvBuffer
);
//////////////////////////////////////////////////////////////
// public functions
//////////////////////////////////////////////////////////////
// -----------------------------------------------------------------
//
// Function: TSSetEventHandler
//
// Arguments: pAddressObject -- our address object structure
// pSendBuffer -- arguments from user dll
// pIrp -- completion information
//
// Returns: NTSTATUS (normally pending)
//
// Descript: This function enables or disables event handlers
//
// -------------------------------------------------------------------------------------------
NTSTATUS
TSSetEventHandler(PGENERIC_HEADER pGenericHeader,
PSEND_BUFFER pSendBuffer,
PIRP pUpperIrp)
{
ULONG ulEventId = pSendBuffer->COMMAND_ARGS.ulEventId;
PADDRESS_OBJECT pAddressObject;
if (pGenericHeader->ulSignature == ulEndpointObject)
{
PENDPOINT_OBJECT pEndpoint = (PENDPOINT_OBJECT)pGenericHeader;
pAddressObject = pEndpoint->pAddressObject;
}
else
{
pAddressObject = (PADDRESS_OBJECT)pGenericHeader;
}
//
// show debug, if it is turned on
//
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulSETEVENTHANDLER\n"
"AddressObject = %p\n"
"EventId = 0x%08x\n",
pAddressObject,
ulEventId);
}
//
// allocate all the necessary structures
//
PEVENT_CONTEXT pEventContext = NULL;
//
// first, our context
//
if ((TSAllocateMemory((PVOID *)&pEventContext,
sizeof(EVENT_CONTEXT),
strFunc1,
"EventContext")) != STATUS_SUCCESS)
{
goto cleanup;
}
//
// then the irp itself
//
PIRP pLowerIrp = TSAllocateIrp(pAddressObject->GenHead.pDeviceObject,
NULL);
if (pLowerIrp)
{
PVOID pvEventContext = pAddressObject;
PVOID pvEventHandler = NULL;
BOOLEAN fNeedIrpPool = FALSE;
switch (ulEventId)
{
case TDI_EVENT_CONNECT:
pvEventHandler = (PVOID)TSConnectHandler;
fNeedIrpPool = TRUE;
break;
case TDI_EVENT_DISCONNECT:
pvEventHandler = (PVOID)TSDisconnectHandler;
fNeedIrpPool = TRUE;
break;
case TDI_EVENT_ERROR:
pvEventHandler = (PVOID)TSErrorHandler;
break;
case TDI_EVENT_RECEIVE:
fNeedIrpPool = TRUE;
pvEventHandler = (PVOID)TSReceiveHandler;
break;
case TDI_EVENT_RECEIVE_DATAGRAM:
fNeedIrpPool = TRUE;
pvEventHandler = (PVOID)TSRcvDatagramHandler;
break;
case TDI_EVENT_RECEIVE_EXPEDITED:
fNeedIrpPool = TRUE;
pvEventHandler = (PVOID)TSRcvExpeditedHandler;
break;
case TDI_EVENT_SEND_POSSIBLE:
pvEventHandler = (PVOID)TSSendPossibleHandler;
break;
case TDI_EVENT_CHAINED_RECEIVE:
pvEventHandler = (PVOID)TSChainedReceiveHandler;
break;
case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
pvEventHandler = (PVOID)TSChainedRcvDatagramHandler;
break;
case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
pvEventHandler = (PVOID)TSChainedRcvExpeditedHandler;
break;
case TDI_EVENT_ERROR_EX:
pvEventHandler = (PVOID)TSErrorExHandler;
break;
}
//
// if need to have irp pool for the handler, make sure that there
// is one allocated..
//
if ((!pAddressObject->pIrpPool) && fNeedIrpPool)
{
pAddressObject->pIrpPool
= TSAllocateIrpPool(pAddressObject->GenHead.pDeviceObject,
ulIrpPoolSize);
}
//
// if made it to here, everything is correctly allocated
// set up irp and call the tdi provider
//
pEventContext->pUpperIrp = pUpperIrp;
#pragma warning(disable: CONSTANT_CONDITIONAL)
TdiBuildSetEventHandler(pLowerIrp,
pAddressObject->GenHead.pDeviceObject,
pAddressObject->GenHead.pFileObject,
TSSetEventComplete,
pEventContext,
ulEventId,
pvEventHandler,
pvEventContext);
#pragma warning(default: CONSTANT_CONDITIONAL)
//
// make the call to the tdi provider
//
pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
NTSTATUS lStatus = IoCallDriver(pAddressObject->GenHead.pDeviceObject,
pLowerIrp);
if (((!NT_SUCCESS(lStatus)) && ulDebugLevel & ulDebugShowCommand))
{
DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
strFunc1,
lStatus);
}
return STATUS_PENDING;
}
//
// get here if an allocation error occurred
//
cleanup:
if (pEventContext)
{
TSFreeMemory(pEventContext);
}
return STATUS_INSUFFICIENT_RESOURCES;
}
/////////////////////////////////////////////////////////////
// private functions
/////////////////////////////////////////////////////////////
// ---------------------------------------------------------
//
// Function: TSSetEventComplete
//
// Arguments: pDeviceObject -- device object that called tdiquery
// pIrp -- IRP used in the call
// pContext -- context used for the call
//
// Returns: status of operation (STATUS_MORE_PROCESSING_REQUIRED)
//
// Descript: Gets the result of the setevent, stuffs results into
// receive buffer, completes the IRP from the dll, and
// cleans up the Irp and associated data from the setevent
//
// ---------------------------------------------------------
#pragma warning(disable: UNREFERENCED_PARAM)
TDI_STATUS
TSSetEventComplete(PDEVICE_OBJECT pDeviceObject,
PIRP pLowerIrp,
PVOID pvContext)
{
PEVENT_CONTEXT pEventContext = (PEVENT_CONTEXT)pvContext;
NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pEventContext->pUpperIrp);
pReceiveBuffer->lStatus = lStatus;
if (ulDebugLevel & ulDebugShowCommand)
{
if (NT_SUCCESS(lStatus))
{
if (pLowerIrp->IoStatus.Information)
{
DebugPrint2("%s: Information = 0x%08x\n",
strFuncP1,
pLowerIrp->IoStatus.Information);
}
}
else
{
DebugPrint2("%s: Completed with status 0x%08x\n",
strFuncP1,
lStatus);
}
}
TSCompleteIrp(pEventContext->pUpperIrp);
//
// now cleanup
//
TSFreeIrp(pLowerIrp, NULL);
TSFreeMemory(pEventContext);
return TDI_MORE_PROCESSING;
}
#pragma warning(default: UNREFERENCED_PARAM)
/////////////////////////////////////////////
// dummy event handlers
/////////////////////////////////////////////
#pragma warning(disable: UNREFERENCED_PARAM)
TDI_STATUS
TSErrorHandler(PVOID pvTdiEventContext,
TDI_STATUS TdiStatus)
{
return TSErrorExHandler(pvTdiEventContext,
TdiStatus,
NULL);
}
TDI_STATUS
TSSendPossibleHandler(PVOID pvTdiEventContext,
PVOID pvConnectionContext,
ULONG ulBytesAvailable)
{
DebugPrint3("TSSendPossibleHandler Called\n"
"AddressObject = %p\n"
"ConnectContext = %p\n"
"BytesAvail = 0x%08x\n",
pvTdiEventContext,
pvConnectionContext,
ulBytesAvailable);
return TDI_SUCCESS;
}
TDI_STATUS
TSErrorExHandler(PVOID pvTdiEventContext,
TDI_STATUS TdiStatus,
PVOID pvBuffer)
{
PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext;
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint3("TSErrorExHandler Called\n"
"AddressObject = %p\n"
"Status = 0x%08x\n"
"Buffer = %p\n",
pvTdiEventContext,
TdiStatus,
pvBuffer);
}
return STATUS_SUCCESS;
}
#pragma warning(default: UNREFERENCED_PARAM)
/////////////////////////////////////////////////////////////////////////////////
// end of file events.cpp
/////////////////////////////////////////////////////////////////////////////////