HDDEDATA CMyServer::CustomCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2) { switch (wType) { case XTYP_ADVSTOP: { CString strTopic = StringFromHsz(hsz1); CDDETopic* pTopic = FindTopic(strTopic); if (pTopic) { pDdeExec->Dde.Lock(); CString strItem = StringFromHsz(hsz2); CDDEItem* pItem = pTopic->FindItem((const char*)strItem); if (pItem) { pItem->RemoveConv(hConv); if (pItem->ConvCount()==0) if (pTopic->RemoveItem((const char*)strItem)) { int i = pDdeExec->FindSubsData(pItem); if (i>=0) { pDdeExec->SubsData[i]->pItem = NULL; pDdeExec->XBuildMyDataLists(); //dbgpln("SubsData[%i]:NULL", i); } } } pDdeExec->Dde.Release(); } break; } } return NULL; }
BOOL CDDEServer::DoCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hszTopic, HSZ hszItem, HDDEDATA hData, HDDEDATA *phReturnData) { // // See if we know the topic // CString strTopic = StringFromHsz(hszTopic); // // See if this is an execute request // if (wType == XTYP_EXECUTE) { // // Call the exec function to process it // Status(_T("Exec")); DWORD dwLength = 0; void* pData = ::DdeAccessData(hData, &dwLength); BOOL b = Exec(strTopic, pData, dwLength); ::DdeUnaccessData(hData); if (b) { *phReturnData = (HDDEDATA) DDE_FACK; return TRUE; // MH - Say we processed it } // // Either no handler or it didn't get handled by the function // Status(_T("Exec failed")); *phReturnData = (HDDEDATA) DDE_FNOTPROCESSED; return FALSE; } // // See if this is a connect request. Accept it if it is. // if (wType == XTYP_CONNECT) { if (!FindTopic(strTopic)) return FALSE; // unknown topic *phReturnData = (HDDEDATA) TRUE; return TRUE; } // // For any other transaction we need to be sure this is an // item we support and in some cases, that the format requested // is supported for that item. // CString strItem = StringFromHsz(hszItem); // // Now just do whatever is required for each specific transaction // BOOL b = FALSE; DWORD dwLength = 0; void* pData = NULL; switch (wType) { case XTYP_ADVSTART: // // Confirm that the supported topic/item pair is OK and // that the format is supported if (!CanAdvise(wFmt, strTopic, strItem)) { Status(_T("Can't advise on %s|%s"), (const TCHAR*)strTopic, (const TCHAR*)strItem); return FALSE; } // // Start an advise request. Topic/item and format are ok. // *phReturnData = (HDDEDATA) TRUE; break; case XTYP_POKE: // // Some data for one of our items. // pData = ::DdeAccessData(hData, &dwLength); b = Poke(wFmt, strTopic, strItem, pData, dwLength); ::DdeUnaccessData(hData); if (!b) { // // Nobody took the data. // Maybe its not a supported item or format // Status(_T("Poke %s|%s failed"), (const TCHAR*)strTopic, (const TCHAR*)strItem); return FALSE; } // // Data at the server has changed. See if we // did this ourself (from a poke) or if it's from // someone else. If it came from elsewhere then post // an advise notice of the change. // CONVINFO ci; ci.cb = sizeof(CONVINFO); if (::DdeQueryConvInfo(hConv, (DWORD)QID_SYNC, &ci)) { if (! (ci.wStatus & ST_ISSELF)) { // // It didn't come from us // ::DdePostAdvise(m_dwDDEInstance, hszTopic, hszItem); } } *phReturnData = (HDDEDATA) DDE_FACK; // say we took it break; case XTYP_ADVDATA: // // A server topic/item has changed value // pData = ::DdeAccessData(hData, &dwLength); b = AdviseData(wFmt, hConv, strTopic, strItem, pData, dwLength); ::DdeUnaccessData(hData); if (!b) { // // Nobody took the data. // Maybe its not of interrest // Status(_T("AdviseData %s|%s failed"), (const TCHAR*)strTopic, (const TCHAR*)strItem); *phReturnData = (HDDEDATA) DDE_FNOTPROCESSED; } else { *phReturnData = (HDDEDATA) DDE_FACK; // say we took it } break; case XTYP_ADVREQ: case XTYP_REQUEST: // // Attempt to start an advise or get the data on a topic/item // See if we have a request function for this item or // a generic one for the topic // { // scope for locals. CDDEAllocator allocr(m_dwDDEInstance, hszItem, wFmt, phReturnData); Status(_T("Request %s|%s"), (const TCHAR*)strTopic, (const TCHAR*)strItem); dwLength = 0; if (!Request(wFmt, strTopic, strItem, allocr)) { // // Nobody accepted the request // Maybe unsupported topic/item or bad format // Status(_T("Request %s|%s failed"), (LPCTSTR)strTopic, (LPCTSTR)strItem); *phReturnData = NULL; return FALSE; } } // end locals scope // Data already setup via 'allocr' param, so we are done. break; default: break; } // // Say we processed the transaction in some way // return TRUE; }
HDDEDATA CDDEServer::DoWildConnect(HSZ hszTopic) { // // See how many topics we will be returning // int iTopics = 0; CString strTopic = "<null>"; if (hszTopic == NULL) { // // Count all the topics we have // iTopics = m_TopicList.GetCount(); } else { // // See if we have this topic in our list // strTopic = StringFromHsz(hszTopic); CDDETopic* pTopic = FindTopic(strTopic); if(pTopic) { iTopics++; } } // // If we have no match or no topics at all, just return // NULL now to refuse the connect // if (!iTopics) { Status(_T("Wild connect to %s refused"), (const TCHAR*)strTopic); return (HDDEDATA) NULL; } // // Allocate a chunk of DDE data big enough for all the HSZPAIRS // we'll be sending back plus space for a NULL entry on the end // HDDEDATA hData = ::DdeCreateDataHandle(m_dwDDEInstance, NULL, (iTopics + 1) * sizeof(HSZPAIR), 0, NULL, 0, 0); // // Check we actually got it. // if (!hData) return (HDDEDATA) NULL; HSZPAIR* pHszPair = (PHSZPAIR) DdeAccessData(hData, NULL); // // Copy the topic data // if (hszTopic == NULL) { // // Copy all the topics we have (includes the system topic) // POSITION pos = m_TopicList.GetHeadPosition(); while (pos) { CDDETopic* pTopic = m_TopicList.GetNext(pos); pHszPair->hszSvc = ::DdeCreateStringHandle(m_dwDDEInstance, (TCHAR*)(const TCHAR*)m_strServiceName, DDE_STRING_CODEPAGE); pHszPair->hszTopic = ::DdeCreateStringHandle(m_dwDDEInstance, (TCHAR*)(const TCHAR*)pTopic->m_strName, DDE_STRING_CODEPAGE); pHszPair++; } } else { // // Just copy the one topic asked for // pHszPair->hszSvc = m_hszServiceName; pHszPair->hszTopic = hszTopic; pHszPair++; } // // Put the terminator on the end // pHszPair->hszSvc = NULL; pHszPair->hszTopic = NULL; // // Finished with the data block // ::DdeUnaccessData(hData); // // Return the block handle // return hData; }