X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d162a7ee7d6bab3d0c714b865806377aeb5d0d9e..88a01064f05bea04682cfde8d82b110d4c80299b:/src/msw/dde.cpp diff --git a/src/msw/dde.cpp b/src/msw/dde.cpp index a03da5030b..d69720c31d 100644 --- a/src/msw/dde.cpp +++ b/src/msw/dde.cpp @@ -5,7 +5,7 @@ // Modified by: // Created: 01/02/97 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem +// Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "dde.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -38,36 +34,13 @@ #include "wx/module.h" #include "wx/dde.h" #include "wx/intl.h" - +#include "wx/hashmap.h" #include "wx/msw/private.h" #include -#include #include -#if defined(__TWIN32__) || defined(__GNUWIN32_OLD__) - #include "wx/msw/gnuwin32/extra.h" -#endif - -// some compilers headers don't define this one (mingw32) -#ifndef DMLERR_NO_ERROR - #define DMLERR_NO_ERROR (0) - - // this one is also missing from some mingw32 headers, but there is no way - // to test for it (I know of) - the test for DMLERR_NO_ERROR works for me, - // but is surely not the right thing to do - extern "C" - HDDEDATA STDCALL DdeClientTransaction(LPBYTE pData, - DWORD cbData, - HCONV hConv, - HSZ hszItem, - UINT wFmt, - UINT wType, - DWORD dwTimeout, - LPDWORD pdwResult); -#endif // no DMLERR_NO_ERROR - // ---------------------------------------------------------------------------- // macros and constants // ---------------------------------------------------------------------------- @@ -113,6 +86,7 @@ static HSZ DDEGetAtom(const wxString& string); // string handles static HSZ DDEAtomFromString(const wxString& s); static wxString DDEStringFromAtom(HSZ hsz); +static void DDEFreeString(HSZ hsz); // error handling static wxString DDEGetErrorMsg(UINT error); @@ -122,15 +96,17 @@ static void DDELogError(const wxString& s, UINT error = DMLERR_NO_ERROR); // global variables // ---------------------------------------------------------------------------- +WX_DECLARE_STRING_HASH_MAP( HSZ, wxAtomMap ); + static DWORD DDEIdInst = 0L; static wxDDEConnection *DDECurrentlyConnecting = NULL; -static wxList wxAtomTable(wxKEY_STRING); +static wxAtomMap wxAtomTable; #include "wx/listimpl.cpp" -WX_DEFINE_LIST(wxDDEClientList); -WX_DEFINE_LIST(wxDDEServerList); -WX_DEFINE_LIST(wxDDEConnectionList); +WX_DEFINE_LIST(wxDDEClientList) +WX_DEFINE_LIST(wxDDEServerList) +WX_DEFINE_LIST(wxDDEConnectionList) static wxDDEClientList wxDDEClientObjects; static wxDDEServerList wxDDEServerObjects; @@ -193,15 +169,12 @@ extern void wxDDEInitialize() void wxDDECleanUp() { - wxDDEClientObjects.DeleteContents(true); - wxDDEClientObjects.Clear(); - wxDDEClientObjects.DeleteContents(false); + // deleting them later won't work as DDE won't be initialized any more + wxASSERT_MSG( wxDDEServerObjects.empty() && + wxDDEClientObjects.empty(), + _T("all DDE objects should be deleted by now") ); - wxDDEServerObjects.DeleteContents(true); - wxDDEServerObjects.Clear(); - wxDDEServerObjects.DeleteContents(false); - - wxAtomTable.Clear(); + wxAtomTable.clear(); if ( DDEIdInst != 0 ) { @@ -217,7 +190,7 @@ void wxDDECleanUp() // Global find connection static wxDDEConnection *DDEFindConnection(HCONV hConv) { - wxDDEServerList::Node *serverNode = wxDDEServerObjects.GetFirst(); + wxDDEServerList::compatibility_iterator serverNode = wxDDEServerObjects.GetFirst(); wxDDEConnection *found = NULL; while (serverNode && !found) { @@ -231,7 +204,7 @@ static wxDDEConnection *DDEFindConnection(HCONV hConv) return found; } - wxDDEClientList::Node *clientNode = wxDDEClientObjects.GetFirst(); + wxDDEClientList::compatibility_iterator clientNode = wxDDEClientObjects.GetFirst(); while (clientNode && !found) { wxDDEClient *object = clientNode->GetData(); @@ -244,7 +217,7 @@ static wxDDEConnection *DDEFindConnection(HCONV hConv) // Global delete connection static void DDEDeleteConnection(HCONV hConv) { - wxDDEServerList::Node *serverNode = wxDDEServerObjects.GetFirst(); + wxDDEServerList::compatibility_iterator serverNode = wxDDEServerObjects.GetFirst(); bool found = false; while (serverNode && !found) { @@ -257,7 +230,7 @@ static void DDEDeleteConnection(HCONV hConv) return; } - wxDDEClientList::Node *clientNode = wxDDEClientObjects.GetFirst(); + wxDDEClientList::compatibility_iterator clientNode = wxDDEClientObjects.GetFirst(); while (clientNode && !found) { wxDDEClient *object = clientNode->GetData(); @@ -269,7 +242,7 @@ static void DDEDeleteConnection(HCONV hConv) // Find a server from a service name static wxDDEServer *DDEFindServer(const wxString& s) { - wxDDEServerList::Node *node = wxDDEServerObjects.GetFirst(); + wxDDEServerList::compatibility_iterator node = wxDDEServerObjects.GetFirst(); wxDDEServer *found = NULL; while (node && !found) { @@ -303,36 +276,55 @@ bool wxDDEServer::Create(const wxString& server) { m_serviceName = server; - if ( !DdeNameService(DDEIdInst, DDEAtomFromString(server), (HSZ)NULL, DNS_REGISTER) ) - { - DDELogError(wxString::Format(_("Failed to register DDE server '%s'"), - server.c_str())); + HSZ hsz = DDEAtomFromString(server); + if ( !hsz ) + { return false; } - return true; + + bool success = (DdeNameService(DDEIdInst, hsz, (HSZ) NULL, DNS_REGISTER) + != NULL); + + if (!success) + { + DDELogError(wxString::Format(_("Failed to register DDE server '%s'"), + server.c_str())); + } + + DDEFreeString(hsz); + + return success; } wxDDEServer::~wxDDEServer() { - if ( !!m_serviceName ) + if ( !m_serviceName.IsEmpty() ) { - if ( !DdeNameService(DDEIdInst, DDEAtomFromString(m_serviceName), - (HSZ)NULL, DNS_UNREGISTER) ) + HSZ hsz = DDEAtomFromString(m_serviceName); + + if (hsz) { - DDELogError(wxString::Format(_("Failed to unregister DDE server '%s'"), - m_serviceName.c_str())); + if ( !DdeNameService(DDEIdInst, hsz, + (HSZ) NULL, DNS_UNREGISTER) ) + { + DDELogError(wxString::Format( + _("Failed to unregister DDE server '%s'"), + m_serviceName.c_str())); + } + + DDEFreeString(hsz); } } wxDDEServerObjects.DeleteObject(this); - wxDDEConnectionList::Node *node = m_connections.GetFirst(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); while (node) { wxDDEConnection *connection = node->GetData(); - wxDDEConnectionList::Node *next = node->GetNext(); + wxDDEConnectionList::compatibility_iterator next = node->GetNext(); connection->SetConnected(false); connection->OnDisconnect(); // May delete the node implicitly node = next; @@ -343,7 +335,7 @@ wxDDEServer::~wxDDEServer() while (node) { wxDDEConnection *connection = node->GetData(); - wxDDEConnectionList::Node *next = node->GetNext(); + wxDDEConnectionList::compatibility_iterator next = node->GetNext(); delete connection; node = next; } @@ -356,7 +348,7 @@ wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */) wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv) { - wxDDEConnectionList::Node *node = m_connections.GetFirst(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); wxDDEConnection *found = NULL; while (node && !found) { @@ -371,22 +363,21 @@ wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv) // Only delete the entry in the map, not the actual connection bool wxDDEServer::DeleteConnection(WXHCONV conv) { - wxDDEConnectionList::Node *node = m_connections.GetFirst(); - bool found = false; - while (node && !found) + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); + while (node) { wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) { - found = true; - delete node; + m_connections.Erase(node); + return true; } else { node = node->GetNext(); } } - return found; + return false; } // ---------------------------------------------------------------------------- @@ -403,7 +394,7 @@ wxDDEClient::wxDDEClient() wxDDEClient::~wxDDEClient() { wxDDEClientObjects.DeleteObject(this); - wxDDEConnectionList::Node *node = m_connections.GetFirst(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); while (node) { wxDDEConnection *connection = node->GetData(); @@ -421,12 +412,35 @@ wxConnectionBase *wxDDEClient::MakeConnection(const wxString& WXUNUSED(host), const wxString& server, const wxString& topic) { - HCONV hConv = DdeConnect(DDEIdInst, DDEAtomFromString(server), DDEAtomFromString(topic), - (PCONVCONTEXT)NULL); + HSZ hszServer = DDEAtomFromString(server); + + if ( !hszServer ) + { + return (wxConnectionBase*) NULL; + } + + + HSZ hszTopic = DDEAtomFromString(topic); + + if ( !hszTopic ) + { + DDEFreeString(hszServer); + return (wxConnectionBase*) NULL; + } + + + HCONV hConv = ::DdeConnect(DDEIdInst, hszServer, hszTopic, + (PCONVCONTEXT) NULL); + + DDEFreeString(hszServer); + DDEFreeString(hszTopic); + + if ( !hConv ) { - DDELogError(wxString::Format(_("Failed to create connection to server '%s' on topic '%s'"), - server.c_str(), topic.c_str())); + DDELogError( wxString::Format( + _("Failed to create connection to server '%s' on topic '%s'"), + server.c_str(), topic.c_str()) ); } else { @@ -451,7 +465,7 @@ wxConnectionBase *wxDDEClient::OnMakeConnection() wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv) { - wxDDEConnectionList::Node *node = m_connections.GetFirst(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); wxDDEConnection *found = NULL; while (node && !found) { @@ -466,19 +480,18 @@ wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv) // Only delete the entry in the map, not the actual connection bool wxDDEClient::DeleteConnection(WXHCONV conv) { - wxDDEConnectionList::Node *node = m_connections.GetFirst(); - bool found = false; - while (node && !found) + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); + while (node) { wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) { - found = true; - delete node; + m_connections.Erase(node); + return true; } else node = node->GetNext(); } - return found; + return false; } // ---------------------------------------------------------------------------- @@ -532,18 +545,21 @@ bool wxDDEConnection::Disconnect() return ok; } -bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat format) +bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat WXUNUSED(format)) { DWORD result; if (size < 0) { - size = wxStrlen(data) + 1; + size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL } - bool ok = DdeClientTransaction((LPBYTE)data, size, + bool ok = DdeClientTransaction((LPBYTE)data, + size, GetHConv(), NULL, - format, +// If the transaction specified by the wType parameter does not pass data or is XTYP_EXECUTE, +// wFmt should be zero. + 0, XTYP_EXECUTE, DDE_TIMEOUT, &result) != 0; @@ -580,9 +596,9 @@ wxChar *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat fo wxChar *data = GetBufferAtLeast( len ); wxASSERT_MSG(data != NULL, _T("Buffer too small in wxDDEConnection::Request") ); - DdeGetData(returned_data, (LPBYTE)data, len, 0); + (void) DdeGetData(returned_data, (LPBYTE)data, len, 0); - DdeFreeDataHandle(returned_data); + (void) DdeFreeDataHandle(returned_data); if (size) *size = (int)len; @@ -595,11 +611,12 @@ bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFo DWORD result; if (size < 0) { - size = wxStrlen(data) + 1; + size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL } HSZ item_atom = DDEGetAtom(item); - bool ok = DdeClientTransaction((LPBYTE)data, size, + bool ok = DdeClientTransaction((LPBYTE)data, + size, GetHConv(), item_atom, format, XTYP_POKE, @@ -659,14 +676,15 @@ bool wxDDEConnection::Advise(const wxString& item, { if (size < 0) { - size = wxStrlen(data) + 1; + size = (wxStrlen(data) + 1) * sizeof(wxChar); // includes final NUL } HSZ item_atom = DDEGetAtom(item); HSZ topic_atom = DDEGetAtom(m_topicName); m_sendingData = data; // mrf: potential for scope problems here? m_dataSize = size; - m_dataType = format; + // wxIPC_PRIVATE does not succeed, so use text instead + m_dataType = format == wxIPC_PRIVATE ? wxIPC_TEXT : format; bool ok = DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0; if ( !ok ) @@ -765,10 +783,11 @@ _DDECallback(WORD wType, DdeFreeDataHandle(hData); +// XTYP_EXECUTE cannot be used for arbitrary data, but only for text if ( connection->OnExecute(connection->m_topicName, data, (int)len, - (wxIPCFormat) wFmt) ) + wxIPC_TEXT ) ) { return (DDERETURN)(DWORD)DDE_FACK; } @@ -793,7 +812,7 @@ _DDECallback(WORD wType, if (data) { if (user_size < 0) - user_size = wxStrlen((wxChar*)data) + 1; + user_size = (wxStrlen((wxChar*)data) + 1) * sizeof(wxChar); // includes final NUL HDDEDATA handle = DdeCreateDataHandle(DDEIdInst, (LPBYTE)data, @@ -820,7 +839,7 @@ _DDECallback(WORD wType, wxChar *data = connection->GetBufferAtLeast( len ); wxASSERT_MSG(data != NULL, - _T("Buffer too small in _DDECallback (XTYP_EXECUTE)") ); + _T("Buffer too small in _DDECallback (XTYP_POKE)") ); DdeGetData(hData, (LPBYTE)data, len, 0); @@ -934,26 +953,27 @@ _DDECallback(WORD wType, // ---------------------------------------------------------------------------- // Atom table stuff -static HSZ DDEAddAtom(const wxString& string) +static HSZ DDEAddAtom(const wxString& str) { - HSZ atom = DDEAtomFromString(string); - wxAtomTable.Append(string, (wxObject *)atom); + HSZ atom = DDEAtomFromString(str); + wxAtomTable[str] = atom; return atom; } -static HSZ DDEGetAtom(const wxString& string) +static HSZ DDEGetAtom(const wxString& str) { - wxNode *node = wxAtomTable.Find(string); - if (node) - return (HSZ)node->GetData(); - else - { - DDEAddAtom(string); - return (HSZ)(wxAtomTable.Find(string)->GetData()); - } + wxAtomMap::iterator it = wxAtomTable.find(str); + + if (it != wxAtomTable.end()) + return it->second; + + return DDEAddAtom(str); } -// atom <-> strings +/* atom <-> strings +The returned handle has to be freed by the caller (using +(static) DDEFreeString). +*/ static HSZ DDEAtomFromString(const wxString& s) { wxASSERT_MSG( DDEIdInst, _T("DDE not initialized") ); @@ -973,12 +993,20 @@ static wxString DDEStringFromAtom(HSZ hsz) static const size_t len = 256; wxString s; - (void)DdeQueryString(DDEIdInst, hsz, s.GetWriteBuf(len), len, DDE_CP); - s.UngetWriteBuf(); + (void)DdeQueryString(DDEIdInst, hsz, wxStringBuffer(s, len), len, DDE_CP); return s; } +static void DDEFreeString(HSZ hsz) +{ + // DS: Failure to free a string handle might indicate there's + // some other severe error. + bool ok = (::DdeFreeStringHandle(DDEIdInst, hsz) != 0); + wxASSERT_MSG( ok, wxT("Failed to free DDE string handle") ); + wxUnusedVar(ok); +} + // ---------------------------------------------------------------------------- // error handling // ----------------------------------------------------------------------------