///////////////////////////////////////////////////////// // // 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 /////////////////////////////////////////////////////////////////////////////////