home *** CD-ROM | disk | FTP | other *** search
/ HTBasic 9.3 / HTBasic 9.3.iso / 93win / data1.cab / DLL_Toolkit / Source / HTBDde / MFCDDE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2005-03-02  |  28.3 KB  |  1,383 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. /*
  3.     File:        mfcdde.cc
  4.     Purpose:    Dde class for MFC
  5.     Author:        Julian Smart
  6. */
  7.  
  8. /////////////////////////////////////////////////////////////////////
  9. // Includes - For compilers that support precompilation, include "wx.h".
  10. //
  11. #include "stdafx.h"
  12. // #include "wx_utils.h"
  13. #include "mfcdde.h"
  14. #include <ddeml.h>
  15.  
  16. #ifdef WIN32
  17. #define _EXPORT
  18. #else
  19. #define _EXPORT _export
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////
  23. // Function Prototypes
  24. //
  25. static CDdeConnection * DdeFindConnection(HCONV hConv);
  26. static void DdeDeleteConnection(HCONV hConv);
  27. static CDdeServer * DdeFindServer(const CString& m_sServiceName);
  28. extern "C" HDDEDATA EXPENTRY _EXPORT _DdeCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD lData1, DWORD lData2);
  29.  
  30. /////////////////////////////////////////////////////////////////////
  31. // Add topic name to atom table before using in conversations
  32. //
  33. static HSZ DdeAddAtom(const CString& sAtomName);
  34. static HSZ DdeGetAtom(const CString& sAtomName);
  35. static void DdePrintError(void);
  36.  
  37. /////////////////////////////////////////////////////////////////////
  38. // Globals
  39. //
  40. static DWORD            g_nDdeIdInst = 0L;
  41. static CMapStringToOb    g_DdeAtomTable;
  42. static CObList            g_DdeObjects;
  43. char *                    g_pDdeDefaultIpcBuffer = NULL;
  44. int                        g_nDdeDefaultIpcBufferSize = MAX_PATH;
  45. BOOL                    g_bDdeInitialized = FALSE;
  46.  
  47.  
  48. /////////////////////////////////////////////////////////////////////////////
  49. /*
  50.     Function:        DdeInitialize
  51.  
  52.     Description:    
  53.  
  54.     Return type:    void 
  55.  
  56.     Notes:
  57.         
  58. */
  59. void DdeInitialize()
  60. {
  61.     if (g_bDdeInitialized)
  62.  
  63.     {
  64.         return;
  65.     }
  66.  
  67.     g_bDdeInitialized = TRUE;
  68.     
  69.     // Should insert filter flags
  70.     DdeInitialize(&g_nDdeIdInst, (PFNCALLBACK)MakeProcInstance(
  71.         (FARPROC)_DdeCallback, AfxGetInstanceHandle()),
  72.         APPCLASS_STANDARD,
  73.         0L);
  74. }
  75.  
  76.  
  77. /////////////////////////////////////////////////////////////////////////////
  78. /*
  79.     Function:        DdeCleanUp
  80.  
  81.     Description:    
  82.  
  83.     Return type:    void 
  84.  
  85.     Notes:
  86.         
  87. */
  88. void DdeCleanUp()
  89. {
  90.     if (g_nDdeIdInst != 0)
  91.     {
  92.         DdeUninitialize(g_nDdeIdInst);
  93.         g_nDdeIdInst = 0;
  94.     }
  95.  
  96.     if (g_pDdeDefaultIpcBuffer)
  97.     {
  98.         delete [] g_pDdeDefaultIpcBuffer;
  99.     }
  100. }
  101.  
  102.  
  103. /////////////////////////////////////////////////////////////////////
  104. // Base class Dde object (CDdeObject)
  105. //
  106.  
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. /*
  110.     Function:        CDdeObject::CDdeObject
  111.  
  112.     Description:    Dde Object constructor - automatically adds this object
  113.                     to the global list of Dde objects.
  114.  
  115.     Return type:    
  116.     Argument:        void
  117.  
  118.     Notes:
  119.         
  120. */
  121. CDdeObject::CDdeObject(void)
  122. {
  123.     m_sServiceName = "";
  124.     g_DdeObjects.AddTail(this);
  125. }
  126.  
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. /*
  130.     Function:        CDdeObject::~CDdeObject
  131.  
  132.     Description:    Dde Object destructor - automatically removes this Dde
  133.                     object from the global list.
  134.  
  135.     Return type:    
  136.     Argument:        void
  137.  
  138.     Notes:
  139.         
  140. */
  141. CDdeObject::~CDdeObject(void)
  142. {
  143.     POSITION pos = g_DdeObjects.Find(this);
  144.  
  145.     if (pos)
  146.     {
  147.         g_DdeObjects.RemoveAt(pos);
  148.     }
  149.  
  150.     pos = m_Connections.GetHeadPosition();
  151.     CDdeConnection *pConnection = NULL;
  152.     
  153.     while (pos && (pConnection = (CDdeConnection *)m_Connections.GetNext(pos)))
  154.     {
  155.         pConnection->OnDisconnect(); // may delete the node implicitly
  156.     }
  157.  
  158.     // If any left after this, delete them
  159.     pos = m_Connections.GetHeadPosition();
  160.     pConnection = NULL;
  161.     
  162.     while (pos && (pConnection = (CDdeConnection *)m_Connections.GetNext(pos)))
  163.     {
  164.         delete pConnection;
  165.     }
  166. }
  167.  
  168.  
  169. /////////////////////////////////////////////////////////////////////////////
  170. /*
  171.     Function:        *DdeFindConnection
  172.  
  173.     Description:    Find a Dde connection
  174.  
  175.     Return type:    static CDdeConnection 
  176.     Argument:        HCONV hConv
  177.  
  178.     Notes:
  179.         
  180. */
  181. static CDdeConnection *DdeFindConnection(HCONV hConv)
  182. {
  183.     CDdeObject *pDdeObject = NULL;
  184.     
  185.     POSITION pos = g_DdeObjects.GetHeadPosition();
  186.     
  187.     while (pos && (pDdeObject = (CDdeObject *)g_DdeObjects.GetNext(pos)))
  188.     {
  189.         CDdeConnection *pConnection = pDdeObject->FindConnection(hConv);
  190.         
  191.         if (pConnection)
  192.         {
  193.             return pConnection;
  194.         }
  195.     }
  196.     
  197.     return NULL;
  198.  
  199.     /*
  200.     wxNode *node = g_DdeObjects.First();
  201.     CDdeConnection *found = NULL;
  202.     while (node && !found)
  203.     {
  204.     CDdeObject *object = (CDdeObject *)node->Data();
  205.     found = object->FindConnection(hConv);
  206.     node = node->Next();
  207.     }
  208.     return found;
  209.     */
  210. }
  211.  
  212.  
  213. /////////////////////////////////////////////////////////////////////////////
  214. /*
  215.     Function:        DdeDeleteConnection
  216.  
  217.     Description:    Global delete connection
  218.  
  219.     Return type:    static void 
  220.     Argument:        HCONV hConv
  221.  
  222.     Notes:
  223.         
  224. */
  225. static void DdeDeleteConnection(HCONV hConv)
  226. {
  227.     CDdeObject *pDdeObject = NULL;
  228.     BOOL bFound = FALSE;
  229.     
  230.     POSITION pos = g_DdeObjects.GetHeadPosition();
  231.     
  232.     while (!bFound && pos && (pDdeObject = (CDdeObject *)g_DdeObjects.GetNext(pos)))
  233.     {
  234.         bFound = pDdeObject->DeleteConnection(hConv);
  235.     }
  236.  
  237.     /*
  238.     wxNode *node = g_DdeObjects.First();
  239.     BOOL bFound = FALSE;
  240.     while (node && !bFound)
  241.     {
  242.     CDdeObject *object = (CDdeObject *)node->Data();
  243.     bFound = object->DeleteConnection(hConv);
  244.     node = node->Next();
  245.     }
  246.     */
  247. }
  248.  
  249.  
  250. /////////////////////////////////////////////////////////////////////////////
  251. /*
  252.     Function:        *CDdeObject::FindConnection
  253.  
  254.     Description:    Finds a connection
  255.  
  256.     Return type:    CDdeConnection 
  257.     Argument:        HCONV hConv
  258.  
  259.     Notes:
  260.         
  261. */
  262. CDdeConnection *CDdeObject::FindConnection(HCONV hConv)
  263. {
  264.     POSITION pos = m_Connections.GetHeadPosition();
  265.     CDdeConnection *pConnection = NULL;
  266.  
  267.     while (pos && (pConnection = (CDdeConnection *)m_Connections.GetNext(pos)))
  268.     {
  269.         if (pConnection->m_hConv == hConv)
  270.         {
  271.             return pConnection;
  272.         }
  273.     }
  274.  
  275.     return NULL;
  276. }
  277.  
  278.  
  279. /////////////////////////////////////////////////////////////////////////////
  280. /*
  281.     Function:        CDdeObject::DeleteConnection
  282.  
  283.     Description:    Only delete the entry in the map, not the actual connection
  284.  
  285.     Return type:    BOOL 
  286.     Argument:        HCONV hConv
  287.  
  288.     Notes:
  289.         
  290. */
  291. BOOL CDdeObject::DeleteConnection(HCONV hConv)
  292. {
  293.     POSITION pos = m_Connections.GetHeadPosition();
  294.     POSITION oldPos = pos;
  295.     CDdeConnection *pConnection = NULL;
  296.     
  297.     while (pos && (pConnection = (CDdeConnection *)m_Connections.GetNext(pos)))
  298.     {
  299.         if (pConnection->m_hConv == hConv)
  300.         {
  301.             m_Connections.RemoveAt(oldPos);
  302.             return TRUE;
  303.         }
  304.         
  305.         oldPos = pos;
  306.     }
  307.     
  308.     return FALSE;
  309. }
  310.  
  311.  
  312. /////////////////////////////////////////////////////////////////////////////
  313. /*
  314.     Function:        DdeFindServer
  315.  
  316.     Description:    Find a server from a service name
  317.  
  318.     Return type:    static CDdeServer 
  319.     Argument:        const CString& m_sServiceName
  320.  
  321.     Notes:
  322.         
  323. */
  324. static CDdeServer *DdeFindServer(const CString& m_sServiceName)
  325. {
  326.     CDdeObject *pDdeObject = NULL;
  327.     
  328.     POSITION pos = g_DdeObjects.GetHeadPosition();
  329.     
  330.     while (pos && (pDdeObject = (CDdeObject *)g_DdeObjects.GetNext(pos)))
  331.     {
  332.         if (pDdeObject->m_sServiceName == m_sServiceName)
  333.         {
  334.             return (CDdeServer *)pDdeObject;
  335.         }
  336.     }
  337.     return NULL;
  338.  
  339. /*
  340.     wxNode *node = g_DdeObjects.First();
  341.     CDdeServer *found = NULL;
  342.     while (node && !found)
  343.     {
  344.     CDdeObject *object = (CDdeObject *)node->Data();
  345.     
  346.       if (object->m_sServiceName == m_sServiceName)
  347.       found = (CDdeServer *)object;
  348.       else node = node->Next();
  349.       }
  350.       return found;
  351. */
  352. }
  353.  
  354.  
  355. /////////////////////////////////////////////////////////////////////
  356. // Dde Server Object (CDdeServer)
  357. //
  358.  
  359.  
  360. /////////////////////////////////////////////////////////////////////////////
  361. /*
  362.     Function:        CDdeServer::CDdeServer
  363.  
  364.     Description:    
  365.  
  366.     Return type:    
  367.     Argument:        void
  368.  
  369.     Notes:
  370.         
  371. */
  372. CDdeServer::CDdeServer(void)
  373. {
  374. }
  375.  
  376.  
  377. /////////////////////////////////////////////////////////////////////////////
  378. /*
  379.     Function:        CDdeServer::Create
  380.  
  381.     Description:    
  382.  
  383.     Return type:    BOOL 
  384.     Argument:        const CString& sServerName
  385.  
  386.     Notes:
  387.         
  388. */
  389. BOOL CDdeServer::Create(const CString& sServerName)
  390. {
  391.     m_sServiceName = sServerName;
  392.     HSZ hszServiceAtom = DdeCreateStringHandle(g_nDdeIdInst, (const char *)sServerName, CP_WINANSI);
  393.     
  394.     if (DdeNameService(g_nDdeIdInst, hszServiceAtom, NULL, DNS_REGISTER) == 0)
  395.     {
  396.         DdePrintError();
  397.         return FALSE;
  398.     }
  399.  
  400.     return TRUE;
  401. }
  402.  
  403.  
  404. /////////////////////////////////////////////////////////////////////////////
  405. /*
  406.     Function:        CDdeServer::~CDdeServer
  407.  
  408.     Description:    
  409.  
  410.     Return type:    
  411.     Argument:        void
  412.  
  413.     Notes:
  414.         
  415. */
  416. CDdeServer::~CDdeServer(void)
  417. {
  418.     if (m_sServiceName != "")
  419.     {
  420.         HSZ hszServiceAtom = DdeCreateStringHandle(g_nDdeIdInst, (const char *)m_sServiceName, CP_WINANSI);
  421.  
  422.         if (DdeNameService(g_nDdeIdInst, hszServiceAtom, NULL, DNS_UNREGISTER) == 0)
  423.         {
  424.             DdePrintError();
  425.         }
  426.     }
  427. }
  428.  
  429.  
  430. /////////////////////////////////////////////////////////////////////////////
  431. /*
  432.     Function:        CDdeServer::OnAcceptConnection
  433.  
  434.     Description:    
  435.  
  436.     Return type:    CDdeConnection *
  437.     Argument:        const CString&        sTopic
  438.  
  439.     Notes:
  440.         
  441. */
  442. CDdeConnection *CDdeServer::OnAcceptConnection(const CString& /* sTopic */)
  443. {
  444.     return new CDdeConnection;
  445. }
  446.  
  447.  
  448. /////////////////////////////////////////////////////////////////////
  449. // Dde Client Object (CDdeClient)
  450. //
  451.  
  452.  
  453. /////////////////////////////////////////////////////////////////////////////
  454. /*
  455.     Function:        CDdeClient::CDdeClient
  456.  
  457.     Description:    
  458.  
  459.     Return type:    
  460.     Argument:        void
  461.  
  462.     Notes:
  463.         
  464. */
  465. CDdeClient::CDdeClient(void)
  466. {
  467. }
  468.  
  469.  
  470. /////////////////////////////////////////////////////////////////////////////
  471. /*
  472.     Function:        CDdeClient::~CDdeClient
  473.  
  474.     Description:    
  475.  
  476.     Return type:    
  477.     Argument:        void
  478.  
  479.     Notes:
  480.         
  481. */
  482. CDdeClient::~CDdeClient(void)
  483. {
  484.     POSITION pos = m_Connections.GetHeadPosition();
  485.     CDdeConnection *pConnection = NULL;
  486.     
  487.     while (pos && (pConnection = (CDdeConnection *)m_Connections.GetNext(pos)))
  488.     {
  489.         delete pConnection; // Deletes entry in m_Connections implicitly
  490.     }
  491. }
  492.  
  493.  
  494. /////////////////////////////////////////////////////////////////////////////
  495. /*
  496.     Function:        CDdeClient::ValidHost
  497.  
  498.     Description:    
  499.  
  500.     Return type:    BOOL 
  501.     Argument:        const CString&        sHostName
  502.  
  503.     Notes:
  504.         
  505. */
  506. BOOL CDdeClient::ValidHost(const CString& /* sHostName */)
  507. {
  508.     return TRUE;
  509. }
  510.  
  511.  
  512. /////////////////////////////////////////////////////////////////////////////
  513. /*
  514.     Function:        *CDdeClient::MakeConnection
  515.  
  516.     Description:    
  517.  
  518.     Return type:    CDdeConnection 
  519.     Argument:        const CString& sHostName
  520.     Argument:        const CString& sServerName
  521.     Argument:        const CString& sTopic
  522.  
  523.     Notes:
  524.         
  525. */
  526. CDdeConnection *CDdeClient::MakeConnection(const CString& /* sHostName */, const CString& sServerName, const CString& sTopic)
  527. {
  528.     HSZ hszServiceAtom = DdeCreateStringHandle(g_nDdeIdInst, (const char *)sServerName, CP_WINANSI);
  529.     HSZ hszTopicAtom = DdeCreateStringHandle(g_nDdeIdInst, (const char *)sTopic, CP_WINANSI);
  530.     
  531.     HCONV hConv = DdeConnect(g_nDdeIdInst, hszServiceAtom, hszTopicAtom, (PCONVCONTEXT)NULL);
  532.  
  533.     if (hConv == NULL)
  534.     {
  535.         return NULL;
  536.     }
  537.     else
  538.     {
  539.         CDdeConnection *pConnection = OnMakeConnection();
  540.     
  541.         if (pConnection)
  542.         {
  543.             pConnection->m_hConv = hConv;
  544.             pConnection->m_sTopicName = sTopic;
  545.             pConnection->m_pClient = this;
  546.             m_Connections.AddTail(pConnection);
  547.         
  548.             return pConnection;
  549.         }
  550.         else
  551.         {
  552.             return NULL;
  553.         }
  554.     }
  555. }
  556.  
  557.  
  558. /////////////////////////////////////////////////////////////////////////////
  559. /*
  560.     Function:        CDdeClient::OnMakeConnection
  561.  
  562.     Description:    
  563.  
  564.     Return type:    CDdeConnection * 
  565.     Argument:        void
  566.  
  567.     Notes:
  568.         
  569. */
  570. CDdeConnection * CDdeClient::OnMakeConnection(void)
  571. {
  572.     return new CDdeConnection;
  573. }
  574.  
  575.  
  576. /////////////////////////////////////////////////////////////////////
  577. // Dde Client Object (CDdeClient)
  578. //
  579.  
  580. /////////////////////////////////////////////////////////////////////////////
  581. /*
  582.     Function:        CDdeConnection::CDdeConnection
  583.  
  584.     Description:    
  585.  
  586.     Return type:    
  587.     Argument:        char *pIpcBuffer
  588.     Argument:        int nIpcBufferSize
  589.  
  590.     Notes:
  591.         
  592. */
  593. CDdeConnection::CDdeConnection(char *pIpcBuffer, int nIpcBufferSize)
  594. {
  595.     if (pIpcBuffer == NULL)
  596.     {
  597.         if (g_pDdeDefaultIpcBuffer == NULL)
  598.         {
  599.             g_pDdeDefaultIpcBuffer = new char[g_nDdeDefaultIpcBufferSize];
  600.         }
  601.         
  602.         m_pIpcBuffer = g_pDdeDefaultIpcBuffer;
  603.         m_nIpcBufferSize = g_nDdeDefaultIpcBufferSize;
  604.     }
  605.     else
  606.     {
  607.         m_pIpcBuffer = pIpcBuffer;
  608.         m_nIpcBufferSize = nIpcBufferSize;
  609.     }
  610.     
  611.     m_sTopicName = "";
  612.     
  613.     m_pClient = NULL;
  614.     m_pServer = NULL;
  615.     
  616.     m_hConv = NULL;
  617.     m_pSendingData = NULL;
  618. }
  619.  
  620.  
  621. /////////////////////////////////////////////////////////////////////////////
  622. /*
  623.     Function:        CDdeConnection::CDdeConnection
  624.  
  625.     Description:    
  626.  
  627.     Return type:    
  628.     Argument:        void
  629.  
  630.     Notes:
  631.         
  632. */
  633. CDdeConnection::CDdeConnection(void)
  634. {
  635.     m_nTimeOut = DEFAULT_TIMEOUT;
  636.     m_hConv = NULL;
  637.     m_pSendingData = NULL;
  638.     m_pServer = NULL;
  639.     m_pClient = NULL;
  640.     
  641.     if (g_pDdeDefaultIpcBuffer == NULL)
  642.     {
  643.         g_pDdeDefaultIpcBuffer = new char[g_nDdeDefaultIpcBufferSize];
  644.     }
  645.     
  646.     m_pIpcBuffer = g_pDdeDefaultIpcBuffer;
  647.     m_nIpcBufferSize = g_nDdeDefaultIpcBufferSize;
  648.     m_sTopicName = "";
  649. }
  650.  
  651.  
  652. /////////////////////////////////////////////////////////////////////////////
  653. /*
  654.     Function:        CDdeConnection::~CDdeConnection
  655.  
  656.     Description:    
  657.  
  658.     Return type:    
  659.     Argument:        void
  660.  
  661.     Notes:
  662.         
  663. */
  664. CDdeConnection::~CDdeConnection(void)
  665. {
  666.     CDdeObject *pDdeObject = NULL;
  667.     
  668.     if (m_pServer)
  669.     {
  670.         pDdeObject = m_pServer;
  671.     }
  672.     else
  673.     {
  674.         pDdeObject = m_pClient;
  675.     }
  676.     
  677.     if (pDdeObject)
  678.     {
  679.         POSITION pos = pDdeObject->m_Connections.Find(this);
  680.         
  681.         if (pos)
  682.         {
  683.             pDdeObject->m_Connections.RemoveAt(pos);
  684.         }
  685.     }
  686. }
  687.  
  688. /////////////////////////////////////////////////////////////////////////////
  689. /*
  690.     Function:        CDdeConnection::Disconnect
  691.  
  692.     Description:    
  693.  
  694.     Return type:    BOOL 
  695.     Argument:        void
  696.  
  697.     Notes:
  698.         
  699. */
  700. BOOL CDdeConnection::Disconnect(void)
  701. {
  702.     DdeDeleteConnection(m_hConv);
  703.  
  704.     return DdeDisconnect(m_hConv);
  705. }
  706.  
  707. /////////////////////////////////////////////////////////////////////
  708. // Calls that CLIENT can make
  709. //
  710.  
  711. /////////////////////////////////////////////////////////////////////////////
  712. /*
  713.     Function:        CDdeConnection::SetTimeOut
  714.  
  715.     Description:    
  716.  
  717.     Return type:    DWORD                returns the previous timeout value
  718.     Argument:        DWORD nTimeOut
  719.  
  720.     Notes:
  721.         
  722. */
  723. DWORD CDdeConnection::SetTimeOut(DWORD nTimeOut)
  724. {
  725.     DWORD nCurrentTimeOut = m_nTimeOut;
  726.     m_nTimeOut = nTimeOut;
  727.  
  728.     return nCurrentTimeOut;
  729. }
  730.  
  731.  
  732. /////////////////////////////////////////////////////////////////////////////
  733. /*
  734.     Function:        CDdeConnection::Execute
  735.  
  736.     Description:    
  737.  
  738.     Return type:    BOOL 
  739.     Argument:        char *pData
  740.     Argument:        int nDataSize
  741.     Argument:        int nFormat
  742.  
  743.     Notes:
  744.         
  745. */
  746. BOOL CDdeConnection::Execute(char *pData, int nDataSize, int nFormat)
  747. {
  748.     DWORD dwResult;
  749.     
  750.     if (nDataSize < 0)
  751.     {
  752.         nDataSize = strlen(pData);
  753.     }
  754.     
  755.     nDataSize ++;
  756.     
  757.     return (DdeClientTransaction((LPBYTE)pData, nDataSize, m_hConv,
  758.         NULL, nFormat, XTYP_EXECUTE, m_nTimeOut, &dwResult) ? TRUE : FALSE);
  759. }
  760.  
  761.  
  762. /////////////////////////////////////////////////////////////////////////////
  763. /*
  764.     Function:        *CDdeConnection::Request
  765.  
  766.     Description:    
  767.  
  768.     Return type:    char 
  769.     Argument:        const CString& sItem
  770.     Argument:        int *pnDataSize
  771.     Argument:        int nFormat
  772.  
  773.     Notes:
  774.         
  775. */
  776. char *CDdeConnection::Request(const CString& sItem, int *pnDataSize, int nFormat)
  777. {
  778.     HSZ hszItemAtom = DdeGetAtom(sItem);
  779.     
  780.     HDDEDATA hDdeData = DdeClientTransaction(NULL, 0, m_hConv, hszItemAtom, nFormat,
  781.         XTYP_REQUEST, m_nTimeOut, NULL);
  782.     
  783.     DWORD dwLength = DdeGetData(hDdeData, (LPBYTE)(m_pIpcBuffer), m_nIpcBufferSize, 0);
  784.     
  785.     DdeFreeDataHandle(hDdeData);
  786.     
  787.     if (pnDataSize)
  788.     {
  789.         *pnDataSize = (int)dwLength;
  790.     }
  791.     
  792.     if (dwLength > 0)
  793.     {
  794.         return m_pIpcBuffer;
  795.     }
  796.     else
  797.     {
  798.         return NULL;
  799.     }
  800. }
  801.  
  802.  
  803. /////////////////////////////////////////////////////////////////////////////
  804. /*
  805.     Function:        CDdeConnection::Poke
  806.  
  807.     Description:    
  808.  
  809.     Return type:    BOOL 
  810.     Argument:        const CString& sItem
  811.     Argument:        char *pData
  812.     Argument:        int nDataSize
  813.     Argument:        int nFormat
  814.  
  815.     Notes:
  816.         
  817. */
  818. BOOL CDdeConnection::Poke(const CString& sItem, char *pData, int nDataSize, int nFormat)
  819. {
  820.     DWORD dwResult;
  821.     
  822.     if (nDataSize < 0)
  823.     {
  824.         nDataSize = strlen(pData);
  825.     }
  826.     
  827.     nDataSize ++;
  828.     
  829.     HSZ hszItemAtom = DdeGetAtom(sItem);
  830.     
  831.     return (DdeClientTransaction((LPBYTE)pData, nDataSize, m_hConv, hszItemAtom, nFormat, XTYP_POKE, m_nTimeOut, &dwResult) ? TRUE : FALSE);
  832. }
  833.  
  834.  
  835. /////////////////////////////////////////////////////////////////////////////
  836. /*
  837.     Function:        CDdeConnection::StartAdvise
  838.  
  839.     Description:    
  840.  
  841.     Return type:    BOOL 
  842.     Argument:        const CString& sItem
  843.  
  844.     Notes:
  845.         
  846. */
  847. BOOL CDdeConnection::StartAdvise(const CString& sItem)
  848. {
  849.     DWORD dwResult;
  850.     HSZ hszItemAtom = DdeGetAtom(sItem);
  851.     
  852.     return (DdeClientTransaction(NULL, 0, m_hConv, hszItemAtom, CF_TEXT, XTYP_ADVSTART, m_nTimeOut, &dwResult) ? TRUE : FALSE);
  853. }
  854.  
  855.  
  856. /////////////////////////////////////////////////////////////////////////////
  857. /*
  858.     Function:        CDdeConnection::StopAdvise
  859.  
  860.     Description:    
  861.  
  862.     Return type:    BOOL 
  863.     Argument:        const CString& sItem
  864.  
  865.     Notes:
  866.         
  867. */
  868. BOOL CDdeConnection::StopAdvise(const CString& sItem)
  869. {
  870.     DWORD dwResult;
  871.     HSZ hszItemAtom = DdeGetAtom(sItem);
  872.     
  873.     return (DdeClientTransaction(NULL, 0, m_hConv, hszItemAtom, CF_TEXT, XTYP_ADVSTOP, m_nTimeOut, &dwResult) ? TRUE : FALSE);
  874. }
  875.  
  876. /////////////////////////////////////////////////////////////////////
  877. // Calls that SERVER can make
  878. //
  879.  
  880. /////////////////////////////////////////////////////////////////////////////
  881. /*
  882.     Function:        CDdeConnection::Advise
  883.  
  884.     Description:    
  885.  
  886.     Return type:    BOOL 
  887.     Argument:        const CString& sItem
  888.     Argument:        char *pData
  889.     Argument:        int nDataSize
  890.     Argument:        int nFormat
  891.  
  892.     Notes:
  893.         
  894. */
  895. BOOL CDdeConnection::Advise(const CString& sItem, char *pData, int nDataSize, int nFormat)
  896. {
  897.     if (nDataSize < 0)
  898.     {
  899.         nDataSize = strlen(pData);
  900.     }
  901.     
  902.     nDataSize ++;
  903.     
  904.     HSZ hszItemAtom = DdeGetAtom(sItem);
  905.     HSZ hszTopicAtom = DdeGetAtom(m_sTopicName);
  906.     m_pSendingData = pData;
  907.     m_nSendingDataSize = nDataSize;
  908.     m_nSendingDataType = nFormat;
  909.     
  910.     return DdePostAdvise(g_nDdeIdInst, hszTopicAtom, hszItemAtom);
  911. }
  912.  
  913.  
  914. /////////////////////////////////////////////////////////////////////////////
  915. /*
  916.     Function:        CDdeConnection::Notify
  917.  
  918.     Description:    
  919.  
  920.     Return type:    void 
  921.     Argument:        BOOL
  922.  
  923.     Notes:
  924.         
  925. */
  926. void CDdeConnection::Notify(BOOL /* bNotify */)
  927. {
  928. }
  929.  
  930.  
  931. /////////////////////////////////////////////////////////////////////////////
  932. /*
  933.     Function:        CDdeConnection::OnDisconnect
  934.  
  935.     Description:    
  936.  
  937.     Return type:    BOOL 
  938.     Argument:        void
  939.  
  940.     Notes:
  941.         
  942. */
  943. BOOL CDdeConnection::OnDisconnect(void)
  944. {
  945.     delete this;
  946.     return TRUE;
  947. }
  948.  
  949.  
  950. #define DDERETURN HDDEDATA
  951.  
  952.  
  953. /////////////////////////////////////////////////////////////////////////////
  954. /*
  955.     Function:        _EXPORT _DdeCallback
  956.  
  957.     Description:    
  958.  
  959.     Return type:    HDDEDATA EXPENTRY 
  960.     Argument:        WORD wType
  961.     Argument:        WORD wFmt
  962.     Argument:        HCONV hConv
  963.     Argument:        HSZ hsz1
  964.     Argument:        HSZ hsz2
  965.     Argument:        HDDEDATA hData
  966.     Argument:        DWORD lData1
  967.     Argument:        DWORD lData2
  968.  
  969.     Notes:
  970.         
  971. */
  972. HDDEDATA EXPENTRY _EXPORT _DdeCallback(WORD wType, WORD wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD /* lData1 */, DWORD /* lData2 */)
  973. {
  974.     static CDdeConnection *pDdeCurrentlyConnecting = NULL;
  975.  
  976.  
  977.     switch (wType)
  978.     {
  979.     case XTYP_CONNECT:
  980.     {
  981.         char pTopicBuf[100];
  982.         char pServerBuf[100];
  983.         DdeQueryString(g_nDdeIdInst, hsz1, (LPSTR)pTopicBuf, sizeof(pTopicBuf), CP_WINANSI);
  984.         DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pServerBuf, sizeof(pTopicBuf), CP_WINANSI);
  985.         CDdeServer *pServer = DdeFindServer(pServerBuf);
  986.         
  987.         if (pServer)
  988.         {
  989.             CDdeConnection *pConnection = pServer->OnAcceptConnection(CString(pTopicBuf));
  990.             
  991.             if (pConnection)
  992.             {
  993.                 pConnection->m_pServer = pServer;
  994.                 pServer->m_Connections.AddTail(pConnection);
  995.                 pConnection->m_hConv = 0;
  996.                 pConnection->m_sTopicName = pTopicBuf;
  997.                 pDdeCurrentlyConnecting = pConnection;
  998.                 
  999.                 return (DDERETURN)TRUE;
  1000.             }
  1001.         }
  1002.         else
  1003.         {
  1004.             return (DDERETURN)0;
  1005.         }
  1006.         
  1007.         break;
  1008.     }
  1009.         
  1010.     case XTYP_CONNECT_CONFIRM:
  1011.     {
  1012.         if (pDdeCurrentlyConnecting)
  1013.         {
  1014.             pDdeCurrentlyConnecting->m_hConv = hConv;
  1015.             pDdeCurrentlyConnecting = NULL;
  1016.             
  1017.             return (DDERETURN)TRUE;
  1018.         }
  1019.         else
  1020.         {
  1021.             return 0;
  1022.         }
  1023.         
  1024.         break;
  1025.     }
  1026.         
  1027.     case XTYP_DISCONNECT:
  1028.     {
  1029.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1030.         
  1031.         if (pConnection && pConnection->OnDisconnect())
  1032.         {
  1033.             DdeDeleteConnection(hConv);  // Delete mapping: hConv => pConnection
  1034.             
  1035.             return (DDERETURN)TRUE;
  1036.         }
  1037.         else
  1038.         {
  1039.             return (DDERETURN)0;
  1040.         }
  1041.         
  1042.         break;
  1043.     }
  1044.         
  1045.     case XTYP_EXECUTE:
  1046.     {
  1047.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1048.         
  1049.         if (pConnection)
  1050.         {
  1051.             DWORD dwLength = DdeGetData(hData, (LPBYTE)(pConnection->m_pIpcBuffer), pConnection->m_nIpcBufferSize, 0);
  1052.             DdeFreeDataHandle(hData);
  1053.             if (pConnection->OnExecute(pConnection->m_sTopicName, pConnection->m_pIpcBuffer, (int)dwLength, wFmt))
  1054.             {
  1055.                 return (DDERETURN)DDE_FACK;
  1056.             }
  1057.             else
  1058.             {
  1059.                 return (DDERETURN)DDE_FNOTPROCESSED;
  1060.             }
  1061.         } 
  1062.         else
  1063.         {
  1064.             return (DDERETURN)DDE_FNOTPROCESSED;
  1065.         }
  1066.         
  1067.         break;
  1068.     }
  1069.         
  1070.     case XTYP_REQUEST:
  1071.     {
  1072.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1073.         
  1074.         if (pConnection)
  1075.         {
  1076.             char pItemName[200];
  1077.             DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pItemName, sizeof(pItemName), CP_WINANSI);
  1078.             
  1079.             int nUserSize = -1;
  1080.             char *pData = pConnection->OnRequest(pConnection->m_sTopicName, CString(pItemName), &nUserSize, wFmt);
  1081.             
  1082.             if (pData)
  1083.             {
  1084.                 if (nUserSize < 0)
  1085.                 {
  1086.                     nUserSize = strlen(pData);
  1087.                 }
  1088.                 
  1089.                 HDDEDATA hDdeData = DdeCreateDataHandle(g_nDdeIdInst, (LPBYTE)pData, nUserSize + 1, 0, hsz2, wFmt, 0);
  1090.                 
  1091.                 return (DDERETURN)hDdeData;
  1092.             } 
  1093.             else
  1094.             {
  1095.                 return (DDERETURN)0;
  1096.             }
  1097.         }
  1098.         else
  1099.         {
  1100.             return (DDERETURN)0;
  1101.         }
  1102.         
  1103.         break;
  1104.     }
  1105.         
  1106.     case XTYP_POKE:
  1107.     {
  1108.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1109.         
  1110.         if (pConnection)
  1111.         {
  1112.             char pItemName[200];
  1113.             DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pItemName, sizeof(pItemName),
  1114.                 CP_WINANSI);
  1115.             DWORD dwLength = DdeGetData(hData, (LPBYTE)(pConnection->m_pIpcBuffer), pConnection->m_nIpcBufferSize, 0);
  1116.             DdeFreeDataHandle(hData);
  1117.             pConnection->OnPoke(pConnection->m_sTopicName, CString(pItemName), pConnection->m_pIpcBuffer, (int)dwLength, wFmt);
  1118.             
  1119.             return (DDERETURN)DDE_FACK;
  1120.         }
  1121.         else
  1122.         {
  1123.             return (DDERETURN)DDE_FNOTPROCESSED;
  1124.         }
  1125.         
  1126.         break;
  1127.     }
  1128.         
  1129.     case XTYP_ADVSTART:
  1130.     {
  1131.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1132.         
  1133.         if (pConnection)
  1134.         {
  1135.             char pItemName[200];
  1136.             DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pItemName, sizeof(pItemName), CP_WINANSI);
  1137.             
  1138.             return (DDERETURN)pConnection->OnStartAdvise(pConnection->m_sTopicName, CString(pItemName));
  1139.         }
  1140.         else
  1141.         {
  1142.             return (DDERETURN)0;
  1143.         }
  1144.         
  1145.         break;
  1146.     }
  1147.         
  1148.     case XTYP_ADVSTOP:
  1149.     {
  1150.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1151.         
  1152.         if (pConnection)
  1153.         {
  1154.             char pItemName[200];
  1155.             DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pItemName, sizeof(pItemName), CP_WINANSI);
  1156.             
  1157.             return (DDERETURN)pConnection->OnStopAdvise(pConnection->m_sTopicName, CString(pItemName));
  1158.         }
  1159.         else
  1160.         {
  1161.             return (DDERETURN)0;
  1162.         }
  1163.         
  1164.         break;
  1165.     }
  1166.         
  1167.     case XTYP_ADVREQ:
  1168.     {
  1169.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1170.         
  1171.         if (pConnection && pConnection->m_pSendingData)
  1172.         {
  1173.             HDDEDATA hDdeData = DdeCreateDataHandle(g_nDdeIdInst, (LPBYTE)pConnection->m_pSendingData,
  1174.                                 pConnection->m_nSendingDataSize, 0, hsz2, pConnection->m_nSendingDataType, 0);
  1175.             pConnection->m_pSendingData = NULL;
  1176.             
  1177.             return (DDERETURN)hDdeData;
  1178.         }
  1179.         else
  1180.         {
  1181.             return (DDERETURN)NULL;
  1182.         }
  1183.         
  1184.         break;
  1185.     }
  1186.         
  1187.     case XTYP_ADVDATA:
  1188.     {
  1189.         CDdeConnection *pConnection = DdeFindConnection(hConv);
  1190.         
  1191.         if (pConnection)
  1192.         {
  1193.             char pItemName[200];
  1194.             DdeQueryString(g_nDdeIdInst, hsz2, (LPSTR)pItemName, sizeof(pItemName),
  1195.                 CP_WINANSI);
  1196.             
  1197.             DWORD dwLength = DdeGetData(hData, (LPBYTE)(pConnection->m_pIpcBuffer), pConnection->m_nIpcBufferSize, 0);
  1198.             DdeFreeDataHandle(hData);
  1199.             
  1200.             if (pConnection->OnAdvise(pConnection->m_sTopicName, CString(pItemName), pConnection->m_pIpcBuffer, (int)dwLength, wFmt))
  1201.             {
  1202.                 return (DDERETURN)DDE_FACK;
  1203.             }
  1204.             else
  1205.             {
  1206.                 return (DDERETURN)DDE_FNOTPROCESSED;
  1207.             }
  1208.         }
  1209.         else
  1210.         {
  1211.             return (DDERETURN)DDE_FNOTPROCESSED;
  1212.         }
  1213.         
  1214.         break;
  1215.     }
  1216.   }
  1217.   
  1218.   return 0;
  1219. }
  1220.  
  1221. /////////////////////////////////////////////////////////////////////
  1222. // Atom table stuff
  1223. //
  1224.  
  1225. /////////////////////////////////////////////////////////////////////////////
  1226. /*
  1227.     Function:        DdeAddAtom
  1228.  
  1229.     Description:    
  1230.  
  1231.     Return type:    static HSZ 
  1232.     Argument:        const CString& sAtomName
  1233.  
  1234.     Notes:
  1235.         
  1236. */
  1237. static HSZ DdeAddAtom(const CString& sAtomName)
  1238. {
  1239.     HSZ hszAtom = DdeCreateStringHandle(g_nDdeIdInst, (const char *)sAtomName, CP_WINANSI);
  1240.     //    g_DdeAtomTable.Append(sAtomName, (CObject *)hszAtom);
  1241.     g_DdeAtomTable.SetAt(sAtomName, (CObject *)hszAtom);
  1242.  
  1243.     return hszAtom;
  1244. }
  1245.  
  1246.  
  1247. /////////////////////////////////////////////////////////////////////////////
  1248. /*
  1249.     Function:        DdeGetAtom
  1250.  
  1251.     Description:    
  1252.  
  1253.     Return type:    static HSZ 
  1254.     Argument:        const CString& sAtomName
  1255.  
  1256.     Notes:
  1257.         
  1258. */
  1259. static HSZ DdeGetAtom(const CString& sAtomName)
  1260. {
  1261.     CObject *data = NULL;
  1262.     
  1263.     if (g_DdeAtomTable.Lookup(sAtomName, data))
  1264.     {
  1265.         return (HSZ)data;
  1266.     }
  1267.     else
  1268.     {
  1269.         return DdeAddAtom(sAtomName);
  1270.     }
  1271. /*
  1272.     wxNode *node = g_DdeAtomTable.Find(sAtomName);
  1273.     if (node)
  1274.         return (HSZ)node->Data();
  1275.     else
  1276.     {
  1277.         DdeAddAtom(sAtomName);
  1278.         return (HSZ)(g_DdeAtomTable.Find(sAtomName)->Data());
  1279.     }
  1280. */    
  1281. }
  1282.  
  1283.  
  1284. /////////////////////////////////////////////////////////////////////////////
  1285. /*
  1286.     Function:        DdePrintError
  1287.  
  1288.     Description:    
  1289.  
  1290.     Return type:    void 
  1291.     Argument:        void
  1292.  
  1293.     Notes:
  1294.         
  1295. */
  1296. void DdePrintError(void)
  1297. {
  1298.     char *szErrorText = NULL;
  1299.     
  1300.     switch (DdeGetLastError(g_nDdeIdInst))
  1301.     {
  1302.     case DMLERR_ADVACKTIMEOUT:
  1303.         szErrorText = "A request for a synchronous advise transaction has timed out.";
  1304.         break;
  1305.         
  1306.     case DMLERR_BUSY:
  1307.         szErrorText = "The response to the transaction caused the Dde_FBUSY bit to be set.";
  1308.         break;
  1309.         
  1310.     case DMLERR_DATAACKTIMEOUT:
  1311.         szErrorText = "A request for a synchronous data transaction has timed out.";
  1312.         break;
  1313.         
  1314.     case DMLERR_DLL_NOT_INITIALIZED:
  1315.         szErrorText = "A DdeML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DdeML function.";
  1316.         break;
  1317.         
  1318.     case DMLERR_DLL_USAGE:
  1319.         szErrorText = "An application initialized as APPCLASS_MONITOR has\n\rattempted to perform a Dde transaction,\n\ror an application initialized as APPCMD_CLIENTONLY has \n\rattempted to perform server transactions.";
  1320.         break;
  1321.         
  1322.     case DMLERR_EXECACKTIMEOUT:
  1323.         szErrorText = "A request for a synchronous execute transaction has timed out.";
  1324.         break;
  1325.         
  1326.     case DMLERR_INVALIDPARAMETER:
  1327.         szErrorText = "A parameter failed to be validated by the DdeML.";
  1328.         break;
  1329.         
  1330.     case DMLERR_LOW_MEMORY:
  1331.         szErrorText = "A DdeML application has created a prolonged race condition.";
  1332.         break;
  1333.         
  1334.     case DMLERR_MEMORY_ERROR:
  1335.         szErrorText = "A memory allocation failed.";
  1336.         break;
  1337.         
  1338.     case DMLERR_NO_CONV_ESTABLISHED:
  1339.         szErrorText = "A client's attempt to establish a conversation has failed.";
  1340.         break;
  1341.         
  1342.     case DMLERR_NOTPROCESSED:
  1343.         szErrorText = "A transaction failed.";
  1344.         break;
  1345.         
  1346.     case DMLERR_POKEACKTIMEOUT:
  1347.         szErrorText = "A request for a synchronous poke transaction has timed out.";
  1348.         break;
  1349.         
  1350.     case DMLERR_POSTMSG_FAILED:
  1351.         szErrorText = "An internal call to the PostMessage function has failed. ";
  1352.         break;
  1353.         
  1354.     case DMLERR_REENTRANCY:
  1355.         szErrorText = "Reentrancy problem.";
  1356.         break;
  1357.         
  1358.     case DMLERR_SERVER_DIED:
  1359.         szErrorText = "A server-side transaction was attempted on a conversation\n\rthat was terminated by the client, or the server\n\rterminated before completing a transaction.";
  1360.         break;
  1361.         
  1362.     case DMLERR_SYS_ERROR:
  1363.         szErrorText = "An internal error has occurred in the DdeML.";
  1364.         break;
  1365.         
  1366.     case DMLERR_UNADVACKTIMEOUT:
  1367.         szErrorText = "A request to end an advise transaction has timed out.";
  1368.         break;
  1369.         
  1370.     case DMLERR_UNFOUND_QUEUE_ID:
  1371.         szErrorText = "An invalid transaction identifier was passed to a DdeML function.\n\rOnce the application has returned from an XTYP_XACT_COMPLETE callback,\n\rthe transaction identifier for that callback is no longer valid.";
  1372.         break;
  1373.         
  1374.     default:
  1375.         szErrorText = "Unrecognised error type.";
  1376.         break;
  1377.     }
  1378.     
  1379.     MessageBox(NULL, (LPCSTR)szErrorText, "Dde Error", MB_OK | MB_ICONINFORMATION);
  1380.     
  1381. }
  1382.  
  1383.