//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: DdeChC.cxx // // Contents: CDdeChannelControl implementation for DDE. This // implementation requires no instance data, therefore it is // intended to be static. // // Functions: // // History: 08-May-94 Johann Posch (johannp) Created // 10-May-94 KevinRo Made simpler // 29-May-94 KevinRo Added DDE Server support // //-------------------------------------------------------------------------- #include "ddeproxy.h" // // All threads can use a single instance of this class. Therefore, we // provide the following global variable that generates the instance. // CDdeChannelControl g_CDdeChannelControl; STDMETHODIMP CDdeChannelControl::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid, IID_IUnknown) // || IsEqualIID(riid, IID_IChannelControl) ) { *ppvObj = (IChannelControl *) this; } else { *ppvObj = NULL; return E_NOINTERFACE; } return S_OK; } STDMETHODIMP_(ULONG) CDdeChannelControl::Release( THIS ) { return(1); } STDMETHODIMP_(ULONG) CDdeChannelControl::AddRef( THIS ) { return 1; } //+--------------------------------------------------------------------------- // // Method: CDdeChannelControl::DispatchCall // // Synopsis: DispatchCall is called to handle incoming calls. // // Effects: Dispatches a call to the specified in the DispatchData. // This function is the result of a call in OnData(), which // processes incoming calls from the OLE 1.0 server. // // Arguments: [pDispData] -- Points to the dispatch data structure // // Requires: // // Returns: // // Signals: // // Modifies: // // Derivation: // // Algorithm: // // History: 5-16-94 JohannP Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CDdeChannelControl::DispatchCall( PDISPATCHDATA pDispData ) { intrDebugOut((DEB_ITRACE, "CDdeChannelControl::DispatchCall(%x,pDispData=%x)\n", this, pDispData)); intrAssert(pDispData != NULL); POLE1DISPATCHDATA pData = (POLE1DISPATCHDATA)pDispData->pData; intrAssert(pData != NULL); switch (pData->wDispFunc) { case DDE_DISP_SENDONDATACHANGE: // OnDataChange { PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData; return pDData->pCDdeObject->SendOnDataChange(pDData->iArg); } case DDE_DISP_OLECALLBACK: // OleCallBack { PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData; return pDData->pCDdeObject->OleCallBack(pDData->iArg,NULL); } // // The server window has an incoming call. Look in dde\server\srvr.cxx // case DDE_DISP_SRVRWNDPROC: return(SrvrDispatchIncomingCall((PSRVRDISPATCHDATA)pDispData->pData)); // // This dispatches to a Document window // case DDE_DISP_DOCWNDPROC: return(DocDispatchIncomingCall((PDOCDISPATCHDATA)pDispData->pData)); default: intrAssert(!"Unknown wDispFunc"); } return E_FAIL; } //+--------------------------------------------------------------------------- // // Method: CDdeChannelControl::OnEvent // // Synopsis: OnEvent should never be called on this channel // // Effects: // // Arguments: [pCallData] -- // // Requires: // // Returns: // // Signals: // // Modifies: // // Derivation: // // Algorithm: // // History: 5-16-94 JohannP Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CDdeChannelControl::OnEvent( PCALLDATA pCallData ) { // should be never called intrAssert(!"CDdeChannelControl::OnEvent( PCALLDATA pCallData ) not implemented\n"); return E_FAIL; } //+--------------------------------------------------------------------------- // // Method: CDdeChannelControl::TransmitCall // // Synopsis: Transmit the parameters to the server. // // Effects: This function transmits the pCallData to the server. This // may be called multiple times, if a retry is required. // // A by product of the way the DDE channel was implemented // atop existing code is that the existing code may transmit // the first round of data on its own. If it does this, it // will set the fInitialSend to TRUE. Therefore, if this // routine sees the flag as true, it will not send the data, // but will set the flag to FALSE for a possible retry later. // // Arguments: [pCallData] -- Points to the DDE specific call data // // Requires: // // Returns: If the Post fails, this function returns E_FAIL // // Signals: // // Modifies: // // Derivation: // // Algorithm: // // History: 5-16-94 JohannP Created // // Notes: // //---------------------------------------------------------------------------- STDMETHODIMP CDdeChannelControl::TransmitCall( PCALLDATA pCallData ) { intrDebugOut((DEB_ITRACE, "CDdeChannelControl::TransmitCall(%x,pCallData=%x)\n", this, pCallData)); // reset the event pCallData->Event = 0; pCallData->fDirectedYield = FALSE; PDDECALLDATA pDdeCD = (PDDECALLDATA)pCallData->pRpcMsg; // // If the routine wPostServerMessage has already posted the // first send, then fInitialSend will be TRUE. In that case, // don't TransmitCall() this time, but reset the flag for // future retries. // if (!pDdeCD->fInitialSend) { intrDebugOut((DEB_ITRACE, "::TransmitCall(%x) PostMessage(%x,%x,%x,%x)\n", this, pDdeCD->hwndSvr, pDdeCD->wMsg, (WPARAM) pDdeCD->hwndCli, pDdeCD->lParam)); if(!PostMessage (pDdeCD->hwndSvr, pDdeCD->wMsg, (WPARAM) pDdeCD->hwndCli, pDdeCD->lParam)) { return(E_FAIL); } } else { intrDebugOut((DEB_ITRACE, "::TransmitCall(%x) Already Posted Message\n", this)); pDdeCD->fInitialSend = FALSE; } // // Figure out if we want the call control to do a directed yield. // Do this only if the server is in the same VDM as us. // if (IsWOWProcess()) { DWORD dwPID, dwTID; dwTID = GetWindowThreadProcessId(pDdeCD->hwndSvr, &dwPID); if (dwPID == GetCurrentProcessId()) { // Make sure we have the right thread id to yield to pCallData->TIDCallee = dwTID; // same VDM so do directed yield pCallData->fDirectedYield = TRUE; } } return NOERROR; }