///////////////////////////////////////////////////////// // // Copyright (c) 2001 Microsoft Corporation // // Module Name: // connect.cpp // // Abstract: // This module contains code which deals with making and breaking // connections // ////////////////////////////////////////////////////////// #include "sysvars.h" ////////////////////////////////////////////////////////////// // private constants, types, and prototypes ////////////////////////////////////////////////////////////// const PCHAR strFunc1 = "TSConnect"; const PCHAR strFunc2 = "TSDisconnect"; // const PCHAR strFunc3 = "TSIsConnected"; const PCHAR strFunc4 = "TSConnectHandler"; const PCHAR strFunc5 = "TSDisconnectHandler"; const PCHAR strFunc6 = "TSListen"; // const PCHAR strFuncP1 = "TSGenAcceptComplete"; const PCHAR strFuncP2 = "TSGenConnectComplete"; // // this context structure stores information needed to complete // the request in the completion handler // struct CONNECT_CONTEXT { PIRP pUpperIrp; // irp from dll to complete ULONG ulWhichCommand; // command that is being completed ULONG ulListenFlag; // 0 or TDI_QUERY_ACCEPT PENDPOINT_OBJECT pEndpoint; // connection endpoint PIRP_POOL pIrpPool; PTDI_CONNECTION_INFORMATION pTdiConnectInfo; }; typedef CONNECT_CONTEXT *PCONNECT_CONTEXT; // // completion functions // TDI_STATUS TSGenConnectComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ); TDI_STATUS TSGenAcceptComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ); ///////////////////////////////////////////////////////////// // public functions ////////////////////////////////////////////////////////////// // ----------------------------------------------------------------- // // Function: TSConnect // // Arguments: pEndpoint -- connection endpoint structure // pSendBuffer -- arguments from user dll // pIrp -- completion information // // Returns: NTSTATUS (normally pending) // // Descript: This function attempts to connect the local endpoint object // with a remote endpoint // // ----------------------------------------------------------------- NTSTATUS TSConnect(PENDPOINT_OBJECT pEndpoint, PSEND_BUFFER pSendBuffer, PIRP pUpperIrp) { PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.ConnectArgs.TransAddr; ULONG ulTimeout = pSendBuffer->COMMAND_ARGS.ConnectArgs.ulTimeout; // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint2("\nCommand = ulCONNECT\n" "FileObject = %p\n" "Timeout = %u\n", pEndpoint, ulTimeout); TSPrintTaAddress(pTransportAddress->Address); } // // make sure all is kosher // if (pEndpoint->fIsConnected) { DebugPrint1("%s: endpoint already connected\n", strFunc1); return STATUS_UNSUCCESSFUL; } if (!pEndpoint->pAddressObject) { DebugPrint1("%s: endpoint not associated with transport address\n", strFunc1); return STATUS_UNSUCCESSFUL; } // // allocate all the necessary structures // PCONNECT_CONTEXT pConnectContext; PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL; // // our context // if ((TSAllocateMemory((PVOID *)&pConnectContext, sizeof(CONNECT_CONTEXT), strFunc1, "ConnectContext")) != STATUS_SUCCESS) { goto cleanup; } // // the connection information structure // if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TRANSADDR), strFunc1, "TdiConnectionInformation")) == STATUS_SUCCESS) // // set up the TdiConnectionInformation // { PUCHAR pucTemp = (PUCHAR)pTdiConnectInfo; ULONG ulAddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) + FIELD_OFFSET(TA_ADDRESS, Address) + pTransportAddress->Address[0].AddressLength; pucTemp += sizeof(TDI_CONNECTION_INFORMATION); pTdiConnectInfo->RemoteAddress = pucTemp; pTdiConnectInfo->RemoteAddressLength = ulAddrLength; RtlCopyMemory(pucTemp, pTransportAddress, ulAddrLength); } else { goto cleanup; } // // set up the completion context // pConnectContext->pUpperIrp = pUpperIrp; pConnectContext->pTdiConnectInfo = pTdiConnectInfo; pConnectContext->pEndpoint = pEndpoint; pConnectContext->ulWhichCommand = TDI_CONNECT; // // finally, the irp itself // PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, NULL); if (pLowerIrp) { LONGLONG llTimeout; PLONGLONG pllTimeout = NULL; if (ulTimeout) { llTimeout = Int32x32To64(ulTimeout, -10000); pllTimeout = &llTimeout; } // // if made it to here, everything is correctly allocated // set up irp and and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildConnect(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSGenConnectComplete, pConnectContext, pllTimeout, pTdiConnectInfo, NULL); // ReturnConnectionInfo #pragma warning(default: CONSTANT_CONDITIONAL) // // make the call to the tdi provider // pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled NTSTATUS lStatus = IoCallDriver(pEndpoint->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 there was an allocation failure // need to clean up everything else... // cleanup: if (pConnectContext) { TSFreeMemory(pConnectContext); } if (pTdiConnectInfo) { TSFreeMemory(pTdiConnectInfo); } return STATUS_INSUFFICIENT_RESOURCES; } // ----------------------------------------------------------------- // // Function: TSDisconnect // // Arguments: pEndpoint -- connection endpoint structure // pIrp -- completion information // // Returns: NTSTATUS (normally pending) // // Descript: This function attempts to disconnect a local endpoint from // a remote endpoint // // ----------------------------------------------------------------- NTSTATUS TSDisconnect(PENDPOINT_OBJECT pEndpoint, PSEND_BUFFER pSendBuffer, PIRP pUpperIrp) { ULONG ulFlags = pSendBuffer->COMMAND_ARGS.ulFlags; if (ulFlags != TDI_DISCONNECT_RELEASE) { ulFlags = TDI_DISCONNECT_ABORT; } // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint2("\nCommand = ulDISCONNECT\n" "EndpointObject = %p\n" "Flags = 0x%x\n", pEndpoint, ulFlags); } // // make sure all is kosher // if (!pEndpoint->fIsConnected) { DebugPrint1("%s: endpoint not currently connected\n", strFunc2); return STATUS_SUCCESS; } // // allocate all the necessary structures // PCONNECT_CONTEXT pConnectContext; // // first, our context // if ((TSAllocateMemory((PVOID *)&pConnectContext, sizeof(CONNECT_CONTEXT), strFunc2, "ConnectContext")) == STATUS_SUCCESS) { pConnectContext->pUpperIrp = pUpperIrp; pConnectContext->ulWhichCommand = TDI_DISCONNECT; pConnectContext->pEndpoint = pEndpoint; // // then the irp itself // PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, NULL); if (pLowerIrp) { // // if made it to here, everything is correctly allocated // set up everything and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildDisconnect(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSGenConnectComplete, pConnectContext, NULL, // pLargeInteger Time ulFlags, // TDI_DISCONNECT _ABORT or _RELEASE NULL, // RequestConnectionInfo NULL); // ReturnConnectionInfo #pragma warning(default: CONSTANT_CONDITIONAL) // // make the call to the tdi provider // pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled pEndpoint->fStartedDisconnect = TRUE; NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject, pLowerIrp); if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand)) { DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n", strFunc2, lStatus); } return STATUS_PENDING; } TSFreeMemory(pConnectContext); } return STATUS_INSUFFICIENT_RESOURCES; } // -------------------------------------------------- // // Function: TSListen // // Arguments: pEndpoint -- connection endpoint structure // // Returns: status of operation (usually success) // // Descript: Wait for an incoming call request // // -------------------------------------------------- NTSTATUS TSListen(PENDPOINT_OBJECT pEndpoint) { ULONG ulListenFlag = 0; // // show debug, if it is turned on // if (ulDebugLevel & ulDebugShowCommand) { DebugPrint1("\nCommand = ulLISTEN\n" "FileObject = %p\n", pEndpoint); } // // make sure all is kosher // if (pEndpoint->fIsConnected) { DebugPrint1("%s: endpoint already connected\n", strFunc6); return STATUS_UNSUCCESSFUL; } if (!pEndpoint->pAddressObject) { DebugPrint1("%s: endpoint not associated with transport address\n", strFunc6); return STATUS_UNSUCCESSFUL; } // // allocate all the necessary structures // PCONNECT_CONTEXT pConnectContext; PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL; // // our context // if ((TSAllocateMemory((PVOID *)&pConnectContext, sizeof(CONNECT_CONTEXT), strFunc6, "ConnectContext")) != STATUS_SUCCESS) { goto cleanup; } // // the connection information structure // if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo, sizeof(TDI_CONNECTION_INFORMATION), strFunc6, "TdiConnectionInformation")) == STATUS_SUCCESS) // // set up the TdiConnectionInformation // { pTdiConnectInfo->UserData = NULL; pTdiConnectInfo->UserDataLength = 0; pTdiConnectInfo->RemoteAddress = NULL; pTdiConnectInfo->RemoteAddressLength = 0; pTdiConnectInfo->Options = &pConnectContext->ulListenFlag; pTdiConnectInfo->OptionsLength = sizeof(ULONG); // // set up the completion context // note that the upper irp is NOT passed! // pConnectContext->pUpperIrp = NULL; pConnectContext->pTdiConnectInfo = pTdiConnectInfo; pConnectContext->pEndpoint = pEndpoint; pConnectContext->ulWhichCommand = TDI_LISTEN; pConnectContext->ulListenFlag = ulListenFlag; if (!pEndpoint->pAddressObject->pIrpPool) { pEndpoint->pAddressObject->pIrpPool = TSAllocateIrpPool(pEndpoint->pAddressObject->GenHead.pDeviceObject, ulIrpPoolSize); pConnectContext->pIrpPool = pEndpoint->pAddressObject->pIrpPool; } // // finally, the irp itself // PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, pEndpoint->pAddressObject->pIrpPool); if (pLowerIrp) { // // if made it to here, everything is correctly allocated // set up irp and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildListen(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSGenAcceptComplete, pConnectContext, ulListenFlag, pTdiConnectInfo, NULL); // ReturnConnectionInfo #pragma warning(default: CONSTANT_CONDITIONAL) NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject, pLowerIrp); if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand)) { DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n", strFunc6, lStatus); } return STATUS_SUCCESS; } } // // get here if there was an allocation failure // need to clean up everything else... // cleanup: if (pConnectContext) { TSFreeMemory(pConnectContext); } if (pTdiConnectInfo) { TSFreeMemory(pTdiConnectInfo); } return STATUS_INSUFFICIENT_RESOURCES; } // -------------------------------------------------- // // Function: TSIsConnected // // Arguments: pEndpoint -- connection endpoint structure // pReceiveBuffer -- put results in here // // Returns: STATUS_SUCCESS // // Descript: Checks to see if endpoint is currently connected // // -------------------------------------------------- NTSTATUS TSIsConnected(PENDPOINT_OBJECT pEndpoint, PRECEIVE_BUFFER pReceiveBuffer) { pReceiveBuffer->RESULTS.ulReturnValue = pEndpoint->fIsConnected; return STATUS_SUCCESS; } // -------------------------------------------------- // // Function: TSConnectHandler // // Arguments: pvTdiEventContext -- here, ptr to address object // lRemoteAddressLength -- # bytes in remote address // pvRemoteAddress -- pTransportAddress of remote // lUserDataLength -- length of data at pvUserData // pvUserData -- connect data from remote // lOptionsLength -- length of data in pvOptions // pvOptions -- transport-specific connect options // pConnectionContext -- return ptr to connection context // ppAcceptIrp -- return ptr to TdiBuildAccept irp // // Returns: STATUS_CONNECTION_REFUSED if are rejecting connection // STATUS_MORE_PROCESSING_REQUIRED is accepting and have supplied // a ppAcceptIrp // // Descript: listens for an offerred connection, then // accepts it or rejects it // // -------------------------------------------------- TDI_STATUS TSConnectHandler(PVOID pvTdiEventContext, LONG lRemoteAddressLength, PVOID pvRemoteAddress, LONG lUserDataLength, PVOID pvUserData, LONG lOptionsLength, PVOID pvOptions, CONNECTION_CONTEXT *pConnectionContext, PIRP *ppAcceptIrp) { PADDRESS_OBJECT pAddressObject = (PADDRESS_OBJECT)pvTdiEventContext; PENDPOINT_OBJECT pEndpoint = pAddressObject->pEndpoint; // // show the information passed in. // Note that we actually use very little of it.. // if (ulDebugLevel & ulDebugShowHandlers) { DebugPrint1("\n >>>> %s\n", strFunc4); DebugPrint2("pAddressObject = %p\n" "RemoteAddressLength = %d\n", pAddressObject, lRemoteAddressLength); if (lRemoteAddressLength) { PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS)pvRemoteAddress; DebugPrint0("RemoteAddress: "); TSPrintTaAddress(&pTransportAddress->Address[0]); } DebugPrint1("UserDataLength = %d\n", lUserDataLength); if (lUserDataLength) { PUCHAR pucTemp = (PUCHAR)pvUserData; DebugPrint0("UserData: "); for (LONG lCount = 0; lCount < lUserDataLength; lCount++) { DebugPrint1("%02x ", *pucTemp); ++pucTemp; } DebugPrint0("\n"); } DebugPrint1("OptionsLength = %d\n", lOptionsLength); if (lOptionsLength) { PUCHAR pucTemp = (PUCHAR)pvOptions; DebugPrint0("Options: "); for (LONG lCount = 0; lCount < (LONG)lOptionsLength; lCount++) { DebugPrint1("%02x ", *pucTemp); ++pucTemp; } DebugPrint0("\n"); } } // // now do the work // if (pEndpoint->fIsConnected || pEndpoint->fAcceptInProgress) { return TDI_CONN_REFUSED; } pEndpoint->fAcceptInProgress = TRUE; // // allocate all the necessary structures // PCONNECT_CONTEXT pConnectContext; // // first, our context // if ((TSAllocateMemory((PVOID *)&pConnectContext, sizeof(CONNECT_CONTEXT), strFunc4, "ConnectContext")) == STATUS_SUCCESS) { pConnectContext->pUpperIrp = NULL; pConnectContext->ulWhichCommand = TDI_ACCEPT; pConnectContext->pEndpoint = pEndpoint; // // then the irp itself // PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, pAddressObject->pIrpPool); pConnectContext->pIrpPool = pAddressObject->pIrpPool; if (pLowerIrp) { // // if made it to here, everything is correctly allocated // set up irp and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildAccept(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSGenAcceptComplete, pConnectContext, NULL, // RequestConnectionInfo NULL); // ReturnConnectionInfo #pragma warning(default: CONSTANT_CONDITIONAL) // // need to do this since we are not calling IoCallDriver // IoSetNextIrpStackLocation(pLowerIrp); *pConnectionContext = pEndpoint; *ppAcceptIrp = pLowerIrp; return TDI_MORE_PROCESSING; } TSFreeMemory(pConnectContext); } pEndpoint->fAcceptInProgress = FALSE; return TDI_CONN_REFUSED; } // -------------------------------------------------- // // Function: TdiDisconnectHandler // // Arguments: pvTdiEventContext -- here, our address object // ConnectionContext -- here, our connection object // lDisconnectDataLength -- length of data in pvDisconnectData // pvDisconnectData -- data sent by remote as part of disconnect // lDisconnectInformationLength -- length of pvDisconnectInformation // pvDisconnectInformation -- transport-specific sidconnect info // ulDisconnectFlags -- nature of disconnect // // Returns: STATUS_SUCCESS // // Descript: deals with an incoming disconnect. Note that the disconnect // is really complete at this point, as far as the protocol // is concerned. We just need to clean up our stuff // // -------------------------------------------------- TDI_STATUS TSDisconnectHandler(PVOID pvTdiEventContext, CONNECTION_CONTEXT ConnectionContext, LONG lDisconnectDataLength, PVOID pvDisconnectData, LONG lDisconnectInformationLength, PVOID pvDisconnectInformation, ULONG ulDisconnectFlags) { PENDPOINT_OBJECT pEndpoint = (PENDPOINT_OBJECT)ConnectionContext; // // show info in arguments // if (ulDebugLevel & ulDebugShowHandlers) { DebugPrint1("\n >>>> %s\n", strFunc5); DebugPrint3("pAddressObject = %p\n" "pEndpoint = %p\n" "DisconnectDataLength = %d\n", pvTdiEventContext, pEndpoint, lDisconnectDataLength); if (lDisconnectDataLength) { PUCHAR pucTemp = (PUCHAR)pvDisconnectData; DebugPrint0("DisconnectData: "); for (LONG lCount = 0; lCount < (LONG)lDisconnectDataLength; lCount++) { DebugPrint1("%02x ", *pucTemp); ++pucTemp; } DebugPrint0("\n"); } DebugPrint1("DisconnectInformationLength = %d\n", lDisconnectInformationLength); if (lDisconnectInformationLength) { PUCHAR pucTemp = (PUCHAR)pvDisconnectInformation; DebugPrint0("DisconnectInformation: "); for (LONG lCount = 0; lCount < (LONG)lDisconnectInformationLength; lCount++) { DebugPrint1("%02x ", *pucTemp); ++pucTemp; } DebugPrint0("\n"); } DebugPrint1("DisconnectFlags = 0x%08x\n", ulDisconnectFlags); if (ulDisconnectFlags & TDI_DISCONNECT_ABORT) { DebugPrint0(" TDI_DISCONNECT_ABORT\n"); } if (ulDisconnectFlags & TDI_DISCONNECT_RELEASE) { DebugPrint0(" TDI_DISCONNECT_RELEASE\n"); } } // // do our cleanup.. // pEndpoint->fIsConnected = FALSE; if ((ulDisconnectFlags & TDI_DISCONNECT_RELEASE) && (!pEndpoint->fStartedDisconnect)) { // // allocate all the necessary structures // PCONNECT_CONTEXT pConnectContext; // // first, our context // if ((TSAllocateMemory((PVOID *)&pConnectContext, sizeof(CONNECT_CONTEXT), strFunc5, "ConnectContext")) == STATUS_SUCCESS) { pConnectContext->pUpperIrp = NULL; pConnectContext->ulWhichCommand = TDI_DISCONNECT; pConnectContext->pEndpoint = pEndpoint; // // then the irp itself // PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject, pEndpoint->pAddressObject->pIrpPool); pConnectContext->pIrpPool = pEndpoint->pAddressObject->pIrpPool; if (pLowerIrp) { // // if made it to here, everything is correctly allocated // set up irp and call the tdi provider // #pragma warning(disable: CONSTANT_CONDITIONAL) TdiBuildDisconnect(pLowerIrp, pEndpoint->GenHead.pDeviceObject, pEndpoint->GenHead.pFileObject, TSGenAcceptComplete, pConnectContext, NULL, // pLargeInteger Time TDI_DISCONNECT_RELEASE, NULL, // RequestConnectionInfo NULL); // ReturnConnectionInfo #pragma warning(default: CONSTANT_CONDITIONAL) // // make the call to the tdi provider // NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject, pLowerIrp); if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand)) { DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n", strFunc5, lStatus); } } else { TSFreeMemory(pConnectContext); } } } // // get here if do NOT need to send TDI_DISCONNECT_RELEASE message back // to other end of connection // else { pEndpoint->fAcceptInProgress = FALSE; pEndpoint->fIsConnected = FALSE; } return TDI_SUCCESS; } ///////////////////////////////////////////////////////////// // private functions ///////////////////////////////////////////////////////////// // --------------------------------------------------------- // // Function: TSGenAcceptComplete // // Arguments: pDeviceObject -- device object on which call was made // 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 command, stuffs results into // receive buffer, cleans up the Irp and associated data // structures, etc // This is used to complete cases where this no IRP from the // dll to complete (ie, connect handler, listen, listen-accept, // listen-disconnect) // // --------------------------------------------------------- #pragma warning(disable: UNREFERENCED_PARAM) TDI_STATUS TSGenAcceptComplete(PDEVICE_OBJECT pDeviceObject, PIRP pLowerIrp, PVOID pvContext) { PCONNECT_CONTEXT pConnectContext = (PCONNECT_CONTEXT)pvContext; NTSTATUS lStatus = pLowerIrp->IoStatus.Status; // // dealing with completions where there is no DLL irp associated // switch (pConnectContext->ulWhichCommand) { case TDI_ACCEPT: if (NT_SUCCESS(lStatus)) { pConnectContext->pEndpoint->fIsConnected = TRUE; } pConnectContext->pEndpoint->fAcceptInProgress = FALSE; break; case TDI_LISTEN: if (NT_SUCCESS(lStatus)) { pConnectContext->pEndpoint->fIsConnected = TRUE; } else { DebugPrint1("Failure in TSListen: status = 0x%08x\n", lStatus); } break; case TDI_DISCONNECT: pConnectContext->pEndpoint->fAcceptInProgress = FALSE; pConnectContext->pEndpoint->fIsConnected = FALSE; pConnectContext->pEndpoint->fStartedDisconnect = FALSE; break; } TSFreeIrp(pLowerIrp, pConnectContext->pIrpPool); // // generic cleanup // if (pConnectContext->pTdiConnectInfo) { TSFreeMemory(pConnectContext->pTdiConnectInfo); } TSFreeMemory(pConnectContext); return TDI_MORE_PROCESSING; } #pragma warning(default: UNREFERENCED_PARAM) // --------------------------------------------------------- // // Function: TSGenConnectComplete // // Arguments: pDeviceObject -- device object on which call was made // 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 command, stuffs results into // receive buffer, completes the IRP from the dll, // cleans up the Irp and associated data structures, etc // Deals only with commands that carry an IRP from the dll // // --------------------------------------------------------- #pragma warning(disable: UNREFERENCED_PARAM) TDI_STATUS TSGenConnectComplete(PDEVICE_OBJECT pDeviceObject, PIRP pLowerIrp, PVOID pvContext) { PCONNECT_CONTEXT pConnectContext = (PCONNECT_CONTEXT)pvContext; NTSTATUS lStatus = pLowerIrp->IoStatus.Status; // // this is completing a command from the dll // PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pConnectContext->pUpperIrp); pReceiveBuffer->lStatus = lStatus; if (NT_SUCCESS(lStatus)) { if (ulDebugLevel & ulDebugShowCommand) { if (pLowerIrp->IoStatus.Information) { DebugPrint2("%s: Information = 0x%08x\n", strFuncP2, pLowerIrp->IoStatus.Information); } } switch (pConnectContext->ulWhichCommand) { case TDI_CONNECT: pConnectContext->pEndpoint->fIsConnected = TRUE; break; case TDI_DISCONNECT: pConnectContext->pEndpoint->fIsConnected = FALSE; break; default: DebugPrint2("%s: invalid command value [0x%08x]\n", strFuncP2, pConnectContext->ulWhichCommand); DbgBreakPoint(); break; } } else { if (ulDebugLevel & ulDebugShowCommand) { DebugPrint2("%s: Completed with status 0x%08x\n", strFuncP2, lStatus); } } TSCompleteIrp(pConnectContext->pUpperIrp); TSFreeIrp(pLowerIrp, NULL); // // generic cleanup // if (pConnectContext->pTdiConnectInfo) { TSFreeMemory(pConnectContext->pTdiConnectInfo); } TSFreeMemory(pConnectContext); return TDI_MORE_PROCESSING; } #pragma warning(default: UNREFERENCED_PARAM) /////////////////////////////////////////////////////////////////////////////// // end of file connect.cpp ///////////////////////////////////////////////////////////////////////////////