X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/56880523be1dafe2e8a63407a06dd955329bc958..2b0246530d08cf7724d94c70d631c166f9717c2c:/src/msw/dde.cpp diff --git a/src/msw/dde.cpp b/src/msw/dde.cpp index 6968b94312..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,18 +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 - // ---------------------------------------------------------------------------- // macros and constants // ---------------------------------------------------------------------------- @@ -95,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); @@ -104,16 +96,22 @@ 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 wxAtomMap wxAtomTable; + +#include "wx/listimpl.cpp" -static wxList wxAtomTable(wxKEY_STRING); -static wxList wxDDEClientObjects; -static wxList wxDDEServerObjects; +WX_DEFINE_LIST(wxDDEClientList) +WX_DEFINE_LIST(wxDDEServerList) +WX_DEFINE_LIST(wxDDEConnectionList) -char *DDEDefaultIPCBuffer = NULL; -int DDEDefaultIPCBufferSize = 0; -static bool DDEInitialized = FALSE; +static wxDDEClientList wxDDEClientObjects; +static wxDDEServerList wxDDEServerObjects; + +static bool DDEInitialized = false; // ---------------------------------------------------------------------------- // private classes @@ -126,7 +124,7 @@ class wxDDEModule : public wxModule { public: wxDDEModule() {} - bool OnInit() { return TRUE; } + bool OnInit() { return true; } void OnExit() { wxDDECleanUp(); } private: @@ -164,20 +162,25 @@ extern void wxDDEInitialize() } else { - DDEInitialized = TRUE; + DDEInitialized = true; } } } void wxDDECleanUp() { + // 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") ); + + wxAtomTable.clear(); + if ( DDEIdInst != 0 ) { DdeUninitialize(DDEIdInst); DDEIdInst = 0; } - - delete [] DDEDefaultIPCBuffer; } // ---------------------------------------------------------------------------- @@ -187,64 +190,75 @@ void wxDDECleanUp() // Global find connection static wxDDEConnection *DDEFindConnection(HCONV hConv) { - wxNode *node = wxDDEServerObjects.First(); - wxDDEConnection *found = NULL; - while (node && !found) - { - wxDDEServer *object = (wxDDEServer *)node->Data(); - found = object->FindConnection((WXHCONV) hConv); - node = node->Next(); - } - if (found) - return found; - - node = wxDDEClientObjects.First(); - while (node && !found) - { - wxDDEClient *object = (wxDDEClient *)node->Data(); - found = object->FindConnection((WXHCONV) hConv); - node = node->Next(); - } - return found; + wxDDEServerList::compatibility_iterator serverNode = wxDDEServerObjects.GetFirst(); + wxDDEConnection *found = NULL; + while (serverNode && !found) + { + wxDDEServer *object = serverNode->GetData(); + found = object->FindConnection((WXHCONV) hConv); + serverNode = serverNode->GetNext(); + } + + if (found) + { + return found; + } + + wxDDEClientList::compatibility_iterator clientNode = wxDDEClientObjects.GetFirst(); + while (clientNode && !found) + { + wxDDEClient *object = clientNode->GetData(); + found = object->FindConnection((WXHCONV) hConv); + clientNode = clientNode->GetNext(); + } + return found; } // Global delete connection static void DDEDeleteConnection(HCONV hConv) { - wxNode *node = wxDDEServerObjects.First(); - bool found = FALSE; - while (node && !found) - { - wxDDEServer *object = (wxDDEServer *)node->Data(); - found = object->DeleteConnection((WXHCONV) hConv); - node = node->Next(); - } - if (found) - return; - - node = wxDDEClientObjects.First(); - while (node && !found) - { - wxDDEClient *object = (wxDDEClient *)node->Data(); - found = object->DeleteConnection((WXHCONV) hConv); - node = node->Next(); - } + wxDDEServerList::compatibility_iterator serverNode = wxDDEServerObjects.GetFirst(); + bool found = false; + while (serverNode && !found) + { + wxDDEServer *object = serverNode->GetData(); + found = object->DeleteConnection((WXHCONV) hConv); + serverNode = serverNode->GetNext(); + } + if (found) + { + return; + } + + wxDDEClientList::compatibility_iterator clientNode = wxDDEClientObjects.GetFirst(); + while (clientNode && !found) + { + wxDDEClient *object = clientNode->GetData(); + found = object->DeleteConnection((WXHCONV) hConv); + clientNode = clientNode->GetNext(); + } } // Find a server from a service name static wxDDEServer *DDEFindServer(const wxString& s) { - wxNode *node = wxDDEServerObjects.First(); - wxDDEServer *found = NULL; - while (node && !found) - { - wxDDEServer *object = (wxDDEServer *)node->Data(); + wxDDEServerList::compatibility_iterator node = wxDDEServerObjects.GetFirst(); + wxDDEServer *found = NULL; + while (node && !found) + { + wxDDEServer *object = node->GetData(); - if (object->GetServiceName() == s) - found = object; - else node = node->Next(); - } - return found; + if (object->GetServiceName() == s) + { + found = object; + } + else + { + node = node->GetNext(); + } + } + + return found; } // ---------------------------------------------------------------------------- @@ -262,46 +276,66 @@ bool wxDDEServer::Create(const wxString& server) { m_serviceName = server; - if ( !DdeNameService(DDEIdInst, DDEAtomFromString(server), (HSZ)NULL, DNS_REGISTER) ) + HSZ hsz = DDEAtomFromString(server); + + if ( !hsz ) + { + return false; + } + + + bool success = (DdeNameService(DDEIdInst, hsz, (HSZ) NULL, DNS_REGISTER) + != NULL); + + if (!success) { DDELogError(wxString::Format(_("Failed to register DDE server '%s'"), - server.c_str())); - - return FALSE; + server.c_str())); } - return TRUE; + 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); - wxNode *node = m_connections.First(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); while (node) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); - wxNode *next = node->Next(); + wxDDEConnection *connection = node->GetData(); + wxDDEConnectionList::compatibility_iterator next = node->GetNext(); + connection->SetConnected(false); connection->OnDisconnect(); // May delete the node implicitly node = next; } // If any left after this, delete them - node = m_connections.First(); + node = m_connections.GetFirst(); while (node) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); - wxNode *next = node->Next(); + wxDDEConnection *connection = node->GetData(); + wxDDEConnectionList::compatibility_iterator next = node->GetNext(); delete connection; node = next; } @@ -314,14 +348,14 @@ wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */) wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv) { - wxNode *node = m_connections.First(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); wxDDEConnection *found = NULL; while (node && !found) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); + wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) found = connection; - else node = node->Next(); + else node = node->GetNext(); } return found; } @@ -329,19 +363,21 @@ wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv) // Only delete the entry in the map, not the actual connection bool wxDDEServer::DeleteConnection(WXHCONV conv) { - wxNode *node = m_connections.First(); - bool found = FALSE; - while (node && !found) + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); + while (node) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); + wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) { - found = TRUE; - delete node; + m_connections.Erase(node); + return true; + } + else + { + node = node->GetNext(); } - else node = node->Next(); } - return found; + return false; } // ---------------------------------------------------------------------------- @@ -358,31 +394,53 @@ wxDDEClient::wxDDEClient() wxDDEClient::~wxDDEClient() { wxDDEClientObjects.DeleteObject(this); - wxNode *node = m_connections.First(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); while (node) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); + wxDDEConnection *connection = node->GetData(); delete connection; // Deletes the node implicitly (see ~wxDDEConnection) - node = m_connections.First(); + node = m_connections.GetFirst(); } } bool wxDDEClient::ValidHost(const wxString& /* host */) { - return TRUE; + return true; } 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 { @@ -407,14 +465,14 @@ wxConnectionBase *wxDDEClient::OnMakeConnection() wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv) { - wxNode *node = m_connections.First(); + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); wxDDEConnection *found = NULL; while (node && !found) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); + wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) found = connection; - else node = node->Next(); + else node = node->GetNext(); } return found; } @@ -422,40 +480,27 @@ wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv) // Only delete the entry in the map, not the actual connection bool wxDDEClient::DeleteConnection(WXHCONV conv) { - wxNode *node = m_connections.First(); - bool found = FALSE; - while (node && !found) + wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst(); + while (node) { - wxDDEConnection *connection = (wxDDEConnection *)node->Data(); + wxDDEConnection *connection = node->GetData(); if (connection->m_hConv == conv) { - found = TRUE; - delete node; + m_connections.Erase(node); + return true; } - else node = node->Next(); + else node = node->GetNext(); } - return found; + return false; } // ---------------------------------------------------------------------------- // wxDDEConnection // ---------------------------------------------------------------------------- -wxDDEConnection::wxDDEConnection(char *buffer, int size) +wxDDEConnection::wxDDEConnection(wxChar *buffer, int size) + : wxConnectionBase(buffer, size) { - if (buffer == NULL) - { - if (DDEDefaultIPCBuffer == NULL) - DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize]; - m_bufPtr = DDEDefaultIPCBuffer; - m_bufSize = DDEDefaultIPCBufferSize; - } - else - { - m_bufPtr = buffer; - m_bufSize = size; - } - m_client = NULL; m_server = NULL; @@ -464,20 +509,17 @@ wxDDEConnection::wxDDEConnection(char *buffer, int size) } wxDDEConnection::wxDDEConnection() + : wxConnectionBase() { m_hConv = 0; m_sendingData = NULL; m_server = NULL; m_client = NULL; - if (DDEDefaultIPCBuffer == NULL) - DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize]; - - m_bufPtr = DDEDefaultIPCBuffer; - m_bufSize = DDEDefaultIPCBufferSize; } wxDDEConnection::~wxDDEConnection() { + Disconnect(); if (m_server) m_server->GetConnections().DeleteObject(this); else @@ -487,6 +529,9 @@ wxDDEConnection::~wxDDEConnection() // Calls that CLIENT can make bool wxDDEConnection::Disconnect() { + if ( !GetConnected() ) + return true; + DDEDeleteConnection(GetHConv()); bool ok = DdeDisconnect(GetHConv()) != 0; @@ -495,24 +540,30 @@ bool wxDDEConnection::Disconnect() DDELogError(_T("Failed to disconnect from DDE server gracefully")); } + SetConnected( false ); // so we don't try and disconnect again + 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; + if ( !ok ) { DDELogError(_T("DDE execute request failed")); @@ -521,9 +572,10 @@ bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat format) return ok; } -char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format) +wxChar *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format) { DWORD result; + HSZ atom = DDEGetAtom(item); HDDEDATA returned_data = DdeClientTransaction(NULL, 0, @@ -539,14 +591,19 @@ char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat form return NULL; } - DWORD len = DdeGetData(returned_data, (LPBYTE)m_bufPtr, m_bufSize, 0); + DWORD len = DdeGetData(returned_data, NULL, 0, 0); - DdeFreeDataHandle(returned_data); + wxChar *data = GetBufferAtLeast( len ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in wxDDEConnection::Request") ); + (void) DdeGetData(returned_data, (LPBYTE)data, len, 0); + + (void) DdeFreeDataHandle(returned_data); if (size) *size = (int)len; - return m_bufPtr; + return data; } bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format) @@ -554,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, @@ -618,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; + 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 ) @@ -639,7 +698,7 @@ bool wxDDEConnection::Advise(const wxString& item, bool wxDDEConnection::OnDisconnect() { delete this; - return TRUE; + return true; } // ---------------------------------------------------------------------------- @@ -676,7 +735,7 @@ _DDECallback(WORD wType, connection->m_hConv = 0; connection->m_topicName = topic; DDECurrentlyConnecting = connection; - return (DDERETURN)(DWORD)TRUE; + return (DDERETURN)(DWORD)true; } } break; @@ -688,7 +747,7 @@ _DDECallback(WORD wType, { DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv; DDECurrentlyConnecting = NULL; - return (DDERETURN)(DWORD)TRUE; + return (DDERETURN)(DWORD)true; } break; } @@ -696,10 +755,14 @@ _DDECallback(WORD wType, case XTYP_DISCONNECT: { wxDDEConnection *connection = DDEFindConnection(hConv); - if (connection && connection->OnDisconnect()) + if (connection) { - DDEDeleteConnection(hConv); // Delete mapping: hConv => connection - return (DDERETURN)(DWORD)TRUE; + connection->SetConnected( false ); + if (connection->OnDisconnect()) + { + DDEDeleteConnection(hConv); // Delete mapping: hConv => connection + return (DDERETURN)(DWORD)true; + } } break; } @@ -710,15 +773,21 @@ _DDECallback(WORD wType, if (connection) { - DWORD len = DdeGetData(hData, - (LPBYTE)connection->m_bufPtr, - connection->m_bufSize, - 0); + DWORD len = DdeGetData(hData, NULL, 0, 0); + + wxChar *data = connection->GetBufferAtLeast( len ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in _DDECallback (XTYP_EXECUTE)") ); + + DdeGetData(hData, (LPBYTE)data, len, 0); + DdeFreeDataHandle(hData); + +// XTYP_EXECUTE cannot be used for arbitrary data, but only for text if ( connection->OnExecute(connection->m_topicName, - connection->m_bufPtr, + data, (int)len, - (wxIPCFormat) wFmt) ) + wxIPC_TEXT ) ) { return (DDERETURN)(DWORD)DDE_FACK; } @@ -736,14 +805,14 @@ _DDECallback(WORD wType, wxString item_name = DDEStringFromAtom(hsz2); int user_size = -1; - char *data = connection->OnRequest(connection->m_topicName, + wxChar *data = connection->OnRequest(connection->m_topicName, item_name, &user_size, (wxIPCFormat) wFmt); if (data) { if (user_size < 0) - user_size = wxStrlen(data) + 1; + user_size = (wxStrlen((wxChar*)data) + 1) * sizeof(wxChar); // includes final NUL HDDEDATA handle = DdeCreateDataHandle(DDEIdInst, (LPBYTE)data, @@ -766,15 +835,19 @@ _DDECallback(WORD wType, { wxString item_name = DDEStringFromAtom(hsz2); - DWORD len = DdeGetData(hData, - (LPBYTE)connection->m_bufPtr, - connection->m_bufSize, - 0); + DWORD len = DdeGetData(hData, NULL, 0, 0); + + wxChar *data = connection->GetBufferAtLeast( len ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in _DDECallback (XTYP_POKE)") ); + + DdeGetData(hData, (LPBYTE)data, len, 0); + DdeFreeDataHandle(hData); connection->OnPoke(connection->m_topicName, item_name, - connection->m_bufPtr, + data, (int)len, (wxIPCFormat) wFmt); @@ -849,14 +922,18 @@ _DDECallback(WORD wType, { wxString item_name = DDEStringFromAtom(hsz2); - DWORD len = DdeGetData(hData, - (LPBYTE)connection->m_bufPtr, - connection->m_bufSize, - 0); + DWORD len = DdeGetData(hData, NULL, 0, 0); + + wxChar *data = connection->GetBufferAtLeast( len ); + wxASSERT_MSG(data != NULL, + _T("Buffer too small in _DDECallback (XTYP_ADVDATA)") ); + + DdeGetData(hData, (LPBYTE)data, len, 0); + DdeFreeDataHandle(hData); if ( connection->OnAdvise(connection->m_topicName, item_name, - connection->m_bufPtr, + data, (int)len, (wxIPCFormat) wFmt) ) { @@ -876,31 +953,32 @@ _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->Data(); - else - { - DDEAddAtom(string); - return (HSZ)(wxAtomTable.Find(string)->Data()); - } + 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") ); - HSZ hsz = DdeCreateStringHandle(DDEIdInst, (char*) s.c_str(), DDE_CP); + HSZ hsz = DdeCreateStringHandle(DDEIdInst, (wxChar*) s.c_str(), DDE_CP); if ( !hsz ) { DDELogError(_("Failed to create DDE string")); @@ -915,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 // ---------------------------------------------------------------------------- @@ -954,10 +1040,10 @@ static wxString DDEGetErrorMsg(UINT error) err = _("a request for a synchronous data transaction has timed out."); break; case DMLERR_DLL_NOT_INITIALIZED: - err = _("a DDEML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DDEML function."); + err = _("a DDEML function was called without first calling the DdeInitialize function,\nor an invalid instance identifier\nwas passed to a DDEML function."); break; case DMLERR_DLL_USAGE: - err = _("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."); + err = _("an application initialized as APPCLASS_MONITOR has\nattempted to perform a DDE transaction,\nor an application initialized as APPCMD_CLIENTONLY has \nattempted to perform server transactions."); break; case DMLERR_EXECACKTIMEOUT: err = _("a request for a synchronous execute transaction has timed out."); @@ -987,7 +1073,7 @@ static wxString DDEGetErrorMsg(UINT error) err = _("reentrancy problem."); break; case DMLERR_SERVER_DIED: - err = _("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."); + err = _("a server-side transaction was attempted on a conversation\nthat was terminated by the client, or the server\nterminated before completing a transaction."); break; case DMLERR_SYS_ERROR: err = _("an internal error has occurred in the DDEML."); @@ -996,7 +1082,7 @@ static wxString DDEGetErrorMsg(UINT error) err = _("a request to end an advise transaction has timed out."); break; case DMLERR_UNFOUND_QUEUE_ID: - err = _("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."); + err = _("an invalid transaction identifier was passed to a DDEML function.\nOnce the application has returned from an XTYP_XACT_COMPLETE callback,\nthe transaction identifier for that callback is no longer valid."); break; default: err.Printf(_("Unknown DDE error %08x"), error);