/////////////////////////////////////////////////////////////////////////////
-// Name: dde.cpp
+// Name: src/msw/dde.cpp
// Purpose: DDE classes
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
-// Copyright: (c) Julian Smart and Markus Holzem
-// Licence: wxWindows licence
+// Copyright: (c) Julian Smart
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation "dde.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include "wx/defs.h"
+ #pragma hdrstop
#endif
#if wxUSE_IPC
#ifndef WX_PRECOMP
-#include "wx/utils.h"
-#include "wx/app.h"
+ #include "wx/utils.h"
+ #include "wx/app.h"
+ #include "wx/hashmap.h"
+ #include "wx/module.h"
#endif
-#include "wx/msw/private.h"
#include "wx/dde.h"
+#include "wx/intl.h"
+#include "wx/buffer.h"
+#include "wx/strconv.h"
-#ifndef __TWIN32__
-#ifdef __GNUWIN32__
-#include "wx/msw/gnuwin32/extra.h"
-#endif
-#endif
+#include "wx/msw/private.h"
-#include <windows.h>
-#include <ddeml.h>
#include <string.h>
+#include <ddeml.h>
+
+// ----------------------------------------------------------------------------
+// macros and constants
+// ----------------------------------------------------------------------------
#ifdef __WIN32__
-#define _EXPORT /**/
+ #define _EXPORT
#else
-#define _EXPORT _export
+ #define _EXPORT _export
#endif
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
-IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
-IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
+#if wxUSE_UNICODE
+ #define DDE_CP CP_WINUNICODE
+#else
+ #define DDE_CP CP_WINANSI
#endif
+#define GetHConv() ((HCONV)m_hConv)
+
+// default timeout for DDE operations (5sec)
+#define DDE_TIMEOUT 5000
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
static wxDDEConnection *DDEFindConnection(HCONV hConv);
static void DDEDeleteConnection(HCONV hConv);
static wxDDEServer *DDEFindServer(const wxString& s);
-extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(
-WORD wType,
-WORD wFmt,
-HCONV hConv,
-HSZ hsz1,
-HSZ hsz2,
-HDDEDATA hData,
-DWORD lData1,
-DWORD lData2);
+extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(WORD wType,
+ WORD wFmt,
+ HCONV hConv,
+ HSZ hsz1,
+ HSZ hsz2,
+ HDDEDATA hData,
+ DWORD lData1,
+ DWORD lData2);
// Add topic name to atom table before using in conversations
static HSZ DDEAddAtom(const wxString& string);
static HSZ DDEGetAtom(const wxString& string);
-static void DDEPrintError(void);
+
+// 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);
+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"
+
+WX_DEFINE_LIST(wxDDEClientList)
+WX_DEFINE_LIST(wxDDEServerList)
+WX_DEFINE_LIST(wxDDEConnectionList)
-static wxList wxAtomTable(wxKEY_STRING);
-static wxList wxDDEClientObjects;
-static wxList wxDDEServerObjects;
+static wxDDEClientList wxDDEClientObjects;
+static wxDDEServerList wxDDEServerObjects;
-char *DDEDefaultIPCBuffer = NULL;
-int DDEDefaultIPCBufferSize = 0;
+static bool DDEInitialized = false;
-/*
- * Initialization
- *
- */
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
-static bool DDEInitialized = FALSE;
+// A module to allow DDE cleanup without calling these functions
+// from app.cpp or from the user's application.
-void wxDDEInitialize()
+class wxDDEModule : public wxModule
{
- if (DDEInitialized)
- return;
- DDEInitialized = TRUE;
+public:
+ wxDDEModule() {}
+ bool OnInit() { return true; }
+ void OnExit() { wxDDECleanUp(); }
- // Should insert filter flags
- DdeInitialize(&DDEIdInst, (PFNCALLBACK)MakeProcInstance(
- (FARPROC)_DDECallback, wxGetInstance()),
- APPCLASS_STANDARD,
- 0L);
-}
+private:
+ DECLARE_DYNAMIC_CLASS(wxDDEModule)
+};
-/*
- * CleanUp
- */
+// ----------------------------------------------------------------------------
+// wxWin macros
+// ----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
+IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
+IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
+IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// initialization and cleanup
+// ----------------------------------------------------------------------------
+
+extern void wxDDEInitialize()
+{
+ if ( !DDEInitialized )
+ {
+ // Should insert filter flags
+ PFNCALLBACK callback = (PFNCALLBACK)
+ MakeProcInstance((FARPROC)_DDECallback, wxGetInstance());
+ UINT rc = DdeInitialize(&DDEIdInst, callback, APPCLASS_STANDARD, 0L);
+ if ( rc != DMLERR_NO_ERROR )
+ {
+ DDELogError(wxT("Failed to initialize DDE"), rc);
+ }
+ else
+ {
+ DDEInitialized = true;
+ }
+ }
+}
void wxDDECleanUp()
{
- if (DDEIdInst != 0)
- {
- DdeUninitialize(DDEIdInst);
- DDEIdInst = 0;
- }
- if (DDEDefaultIPCBuffer)
- delete [] DDEDefaultIPCBuffer ;
+ // deleting them later won't work as DDE won't be initialized any more
+ wxASSERT_MSG( wxDDEServerObjects.empty() &&
+ wxDDEClientObjects.empty(),
+ wxT("all DDE objects should be deleted by now") );
+
+ wxAtomTable.clear();
+
+ if ( DDEIdInst != 0 )
+ {
+ DdeUninitialize(DDEIdInst);
+ DDEIdInst = 0;
+ }
}
+// ----------------------------------------------------------------------------
+// functions working with the global connection list(s)
+// ----------------------------------------------------------------------------
+
// 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 = wxDDEServerObjects.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();
-
- if (object->GetServiceName() == s)
- found = object;
- else node = node->Next();
- }
- return found;
+ 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->GetNext();
+ }
+ }
+
+ return found;
}
-/*
- * Server
- *
- */
+// ----------------------------------------------------------------------------
+// wxDDEServer
+// ----------------------------------------------------------------------------
-wxDDEServer::wxDDEServer(void)
+wxDDEServer::wxDDEServer()
{
- m_serviceName = "";
- wxDDEServerObjects.Append(this);
+ wxDDEInitialize();
+
+ wxDDEServerObjects.Append(this);
}
-bool wxDDEServer::Create(const wxString& server_name)
+bool wxDDEServer::Create(const wxString& server)
{
- m_serviceName = server_name;
- HSZ serviceName = DdeCreateStringHandle(DDEIdInst, (char*) (const char *)server_name, CP_WINANSI);
+ m_serviceName = server;
+
+ HSZ hsz = DDEAtomFromString(server);
+
+ if ( !hsz )
+ {
+ return false;
+ }
- if (DdeNameService(DDEIdInst, serviceName, (HSZ) NULL, DNS_REGISTER) == 0)
- {
- DDEPrintError();
- 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(void)
+wxDDEServer::~wxDDEServer()
{
- if (m_serviceName != "")
- {
- HSZ serviceName = DdeCreateStringHandle(DDEIdInst, (char*) (const char *)m_serviceName, CP_WINANSI);
- if (DdeNameService(DDEIdInst, serviceName, NULL, DNS_UNREGISTER) == 0)
+ if ( !m_serviceName.empty() )
{
- DDEPrintError();
+ HSZ hsz = DDEAtomFromString(m_serviceName);
+
+ if (hsz)
+ {
+ 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();
- while (node)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- wxNode *next = node->Next();
- connection->OnDisconnect(); // May delete the node implicitly
- node = next;
- }
+ wxDDEServerObjects.DeleteObject(this);
- // If any left after this, delete them
- node = m_connections.First();
- while (node)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- wxNode *next = node->Next();
- delete connection;
- node = next;
- }
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ while (node)
+ {
+ 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.GetFirst();
+ while (node)
+ {
+ wxDDEConnection *connection = node->GetData();
+ wxDDEConnectionList::compatibility_iterator next = node->GetNext();
+ delete connection;
+ node = next;
+ }
}
wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */)
{
- return new wxDDEConnection;
+ return new wxDDEConnection;
}
wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv)
{
- wxNode *node = m_connections.First();
- wxDDEConnection *found = NULL;
- while (node && !found)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- if (connection->m_hConv == conv)
- found = connection;
- else node = node->Next();
- }
- return found;
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ wxDDEConnection *found = NULL;
+ while (node && !found)
+ {
+ wxDDEConnection *connection = node->GetData();
+ if (connection->m_hConv == conv)
+ found = connection;
+ else node = node->GetNext();
+ }
+ return found;
}
// 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)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- if (connection->m_hConv == conv)
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ while (node)
{
- found = TRUE;
- delete node;
+ wxDDEConnection *connection = node->GetData();
+ if (connection->m_hConv == conv)
+ {
+ m_connections.Erase(node);
+ return true;
+ }
+ else
+ {
+ node = node->GetNext();
+ }
}
- else node = node->Next();
- }
- return found;
+ return false;
}
+// ----------------------------------------------------------------------------
+// wxDDEClient
+// ----------------------------------------------------------------------------
-/*
- * Client
- *
- */
-
-
-wxDDEClient::wxDDEClient(void)
+wxDDEClient::wxDDEClient()
{
- wxDDEClientObjects.Append(this);
+ wxDDEInitialize();
+
+ wxDDEClientObjects.Append(this);
}
-wxDDEClient::~wxDDEClient(void)
+wxDDEClient::~wxDDEClient()
{
- wxDDEClientObjects.DeleteObject(this);
- wxNode *node = m_connections.First();
- while (node)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
- node = m_connections.First();
- }
+ wxDDEClientObjects.DeleteObject(this);
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ while (node)
+ {
+ wxDDEConnection *connection = node->GetData();
+ delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
+ node = m_connections.GetFirst();
+ }
}
bool wxDDEClient::ValidHost(const wxString& /* host */)
{
- return TRUE;
+ return true;
}
-wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const wxString& server_name, const wxString& topic)
+wxConnectionBase *wxDDEClient::MakeConnection(const wxString& WXUNUSED(host),
+ const wxString& server,
+ const wxString& topic)
{
- HSZ serviceName = DdeCreateStringHandle(DDEIdInst, (char*) (const char *)server_name, CP_WINANSI);
- HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, (char*) (const char *)topic, CP_WINANSI);
+ HSZ hszServer = DDEAtomFromString(server);
+
+ if ( !hszServer )
+ {
+ return NULL;
+ }
+
+
+ HSZ hszTopic = DDEAtomFromString(topic);
+
+ if ( !hszTopic )
+ {
+ DDEFreeString(hszServer);
+ return NULL;
+ }
- HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL);
- if (hConv == (HCONV) NULL)
- return (wxConnectionBase*) NULL;
- else
- {
- wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
- if (connection)
+
+ HCONV hConv = ::DdeConnect(DDEIdInst, hszServer, hszTopic,
+ (PCONVCONTEXT) NULL);
+
+ DDEFreeString(hszServer);
+ DDEFreeString(hszTopic);
+
+
+ if ( !hConv )
{
- connection->m_hConv = (WXHCONV) hConv;
- connection->m_topicName = topic;
- connection->m_client = this;
- m_connections.Append(connection);
- return connection;
+ DDELogError( wxString::Format(
+ _("Failed to create connection to server '%s' on topic '%s'"),
+ server.c_str(), topic.c_str()) );
+ }
+ else
+ {
+ wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
+ if (connection)
+ {
+ connection->m_hConv = (WXHCONV) hConv;
+ connection->m_topicName = topic;
+ connection->m_client = this;
+ m_connections.Append(connection);
+ return connection;
+ }
}
- else return (wxConnectionBase*) NULL;
- }
+
+ return NULL;
}
-wxConnectionBase *wxDDEClient::OnMakeConnection(void)
+wxConnectionBase *wxDDEClient::OnMakeConnection()
{
- return new wxDDEConnection;
+ return new wxDDEConnection;
}
wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv)
{
- wxNode *node = m_connections.First();
- wxDDEConnection *found = NULL;
- while (node && !found)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- if (connection->m_hConv == conv)
- found = connection;
- else node = node->Next();
- }
- return found;
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ wxDDEConnection *found = NULL;
+ while (node && !found)
+ {
+ wxDDEConnection *connection = node->GetData();
+ if (connection->m_hConv == conv)
+ found = connection;
+ else node = node->GetNext();
+ }
+ return found;
}
// 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)
- {
- wxDDEConnection *connection = (wxDDEConnection *)node->Data();
- if (connection->m_hConv == conv)
+ wxDDEConnectionList::compatibility_iterator node = m_connections.GetFirst();
+ while (node)
{
- found = TRUE;
- delete node;
+ wxDDEConnection *connection = node->GetData();
+ if (connection->m_hConv == conv)
+ {
+ m_connections.Erase(node);
+ return true;
+ }
+ else node = node->GetNext();
}
- else node = node->Next();
- }
- return found;
+ return false;
}
-/*
- * Connection
- */
+// ----------------------------------------------------------------------------
+// wxDDEConnection
+// ----------------------------------------------------------------------------
-wxDDEConnection::wxDDEConnection(char *buffer, int size)
+wxDDEConnection::wxDDEConnection(void *buffer, size_t 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;
- m_topicName = "";
-
- m_client = NULL;
- m_server = NULL;
-
- m_hConv = 0;
- m_sendingData = NULL;
+ m_hConv = 0;
+ m_sendingData = NULL;
}
-wxDDEConnection::wxDDEConnection(void)
+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;
- m_topicName = "";
+ m_hConv = 0;
+ m_sendingData = NULL;
+ m_server = NULL;
+ m_client = NULL;
}
-wxDDEConnection::~wxDDEConnection(void)
+wxDDEConnection::~wxDDEConnection()
{
- if (m_server)
- m_server->GetConnections().DeleteObject(this);
- else
- m_client->GetConnections().DeleteObject(this);
+ Disconnect();
+ if (m_server)
+ m_server->GetConnections().DeleteObject(this);
+ else
+ m_client->GetConnections().DeleteObject(this);
}
// Calls that CLIENT can make
-bool wxDDEConnection::Disconnect(void)
+bool wxDDEConnection::Disconnect()
{
- DDEDeleteConnection((HCONV) m_hConv);
- return (DdeDisconnect((HCONV) m_hConv) != 0);
+ if ( !GetConnected() )
+ return true;
+
+ DDEDeleteConnection(GetHConv());
+
+ bool ok = DdeDisconnect(GetHConv()) != 0;
+ if ( !ok )
+ {
+ DDELogError(wxT("Failed to disconnect from DDE server gracefully"));
+ }
+
+ SetConnected( false ); // so we don't try and disconnect again
+
+ return ok;
}
-bool wxDDEConnection::Execute(char *data, int size, wxIPCFormat format)
+bool
+wxDDEConnection::DoExecute(const void *data, size_t size, wxIPCFormat format)
{
- DWORD result;
- if (size < 0)
- size = strlen(data);
+ wxCHECK_MSG( format == wxIPC_TEXT ||
+ format == wxIPC_UTF8TEXT ||
+ format == wxIPC_UNICODETEXT,
+ false,
+ wxT("wxDDEServer::Execute() supports only text data") );
+
+ wxMemoryBuffer buffer;
+ LPBYTE realData = NULL;
+ size_t realSize = 0;
+ wxMBConv *conv = NULL;
+
+ // Windows only supports either ANSI or UTF-16 format depending on the
+ // build, so we need to convert the data if it doesn't use it already
+#if wxUSE_UNICODE
+ if ( format == wxIPC_TEXT )
+ {
+ conv = &wxConvLibc;
+ }
+ else if ( format == wxIPC_UTF8TEXT )
+ {
+ conv = &wxConvUTF8;
+ }
+ else // no conversion necessary for wxIPC_UNICODETEXT
+ {
+ realData = (LPBYTE)data;
+ realSize = size;
+ }
+
+ if ( conv )
+ {
+ const char * const text = (const char *)data;
+ const size_t len = size/sizeof(char);
+
+ realSize = conv->ToWChar(NULL, 0, text, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+
+ realData = (LPBYTE)buffer.GetWriteBuf(realSize*sizeof(wchar_t));
+ if ( !realData )
+ return false;
+
+ realSize = conv->ToWChar((wchar_t *)realData, realSize, text, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+ }
+#else // !wxUSE_UNICODE
+ if ( format == wxIPC_UNICODETEXT )
+ {
+ conv = &wxConvLibc;
+ }
+ else if ( format == wxIPC_UTF8TEXT )
+ {
+ // we could implement this in theory but it's not obvious how to pass
+ // the format information and, basically, why bother -- just use
+ // Unicode build
+ wxFAIL_MSG( wxT("UTF-8 text not supported in ANSI build") );
- size ++;
+ return false;
+ }
+ else // don't convert wxIPC_TEXT
+ {
+ realData = (LPBYTE)data;
+ realSize = size;
+ }
- return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
- NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
+ if ( conv )
+ {
+ const wchar_t * const wtext = (const wchar_t *)data;
+ const size_t len = size/sizeof(wchar_t);
+
+ realSize = conv->FromWChar(NULL, 0, wtext, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+
+ realData = (LPBYTE)buffer.GetWriteBuf(realSize*sizeof(char));
+ if ( !realData )
+ return false;
+
+ realSize = conv->FromWChar((char*)realData, realSize, wtext, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+ }
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+ DWORD result;
+ bool ok = DdeClientTransaction(realData,
+ realSize*sizeof(wxChar),
+ GetHConv(),
+ NULL,
+ // MSDN: 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(wxT("DDE execute request failed"));
+ }
+
+ return ok;
}
-char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
+const void *wxDDEConnection::Request(const wxString& item, size_t *size, wxIPCFormat format)
{
- DWORD result;
- HSZ atom = DDEGetAtom(item);
+ DWORD result;
+
+ HSZ atom = DDEGetAtom(item);
+
+ HDDEDATA returned_data = DdeClientTransaction(NULL, 0,
+ GetHConv(),
+ atom, format,
+ XTYP_REQUEST,
+ DDE_TIMEOUT,
+ &result);
+ if ( !returned_data )
+ {
+ DDELogError(wxT("DDE data request failed"));
+
+ return NULL;
+ }
+
+ DWORD len = DdeGetData(returned_data, NULL, 0, 0);
- HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
- atom, format, XTYP_REQUEST, 5000, &result);
+ void *data = GetBufferAtLeast(len);
+ wxASSERT_MSG(data != NULL,
+ wxT("Buffer too small in wxDDEConnection::Request") );
+ (void) DdeGetData(returned_data, (LPBYTE)data, len, 0);
- DWORD len = DdeGetData(returned_data, (LPBYTE)(m_bufPtr), m_bufSize, 0);
+ (void) DdeFreeDataHandle(returned_data);
- DdeFreeDataHandle(returned_data);
+ if (size)
+ *size = (size_t)len;
- if (size) *size = (int)len;
- if (len > 0)
- {
- return m_bufPtr;
- }
- else return NULL;
+ return data;
}
-bool wxDDEConnection::Poke(const wxString& item, char *data, int size, wxIPCFormat format)
+bool wxDDEConnection::DoPoke(const wxString& item, const void *data, size_t size, wxIPCFormat format)
{
- DWORD result;
- if (size < 0)
- size = strlen(data);
-
- size ++;
+ DWORD result;
+
+ HSZ item_atom = DDEGetAtom(item);
+ bool ok = DdeClientTransaction((LPBYTE)data,
+ size,
+ GetHConv(),
+ item_atom, format,
+ XTYP_POKE,
+ DDE_TIMEOUT,
+ &result) != 0;
+ if ( !ok )
+ {
+ DDELogError(_("DDE poke request failed"));
+ }
- HSZ item_atom = DDEGetAtom(item);
- return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
- item_atom, format, XTYP_POKE, 5000, &result) ? TRUE : FALSE);
+ return ok;
}
bool wxDDEConnection::StartAdvise(const wxString& item)
{
- DWORD result;
- HSZ atom = DDEGetAtom(item);
+ DWORD result;
+ HSZ atom = DDEGetAtom(item);
+
+ bool ok = DdeClientTransaction(NULL, 0,
+ GetHConv(),
+ atom, CF_TEXT,
+ XTYP_ADVSTART,
+ DDE_TIMEOUT,
+ &result) != 0;
+ if ( !ok )
+ {
+ DDELogError(_("Failed to establish an advise loop with DDE server"));
+ }
- return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
- atom, CF_TEXT, XTYP_ADVSTART, 5000, &result) ? TRUE : FALSE);
+ return ok;
}
bool wxDDEConnection::StopAdvise(const wxString& item)
{
- DWORD result;
- HSZ atom = DDEGetAtom(item);
+ DWORD result;
+ HSZ atom = DDEGetAtom(item);
+
+ bool ok = DdeClientTransaction(NULL, 0,
+ GetHConv(),
+ atom, CF_TEXT,
+ XTYP_ADVSTOP,
+ DDE_TIMEOUT,
+ &result) != 0;
+ if ( !ok )
+ {
+ DDELogError(_("Failed to terminate the advise loop with DDE server"));
+ }
- return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
- atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE);
+ return ok;
}
// Calls that SERVER can make
-bool wxDDEConnection::Advise(const wxString& item, char *data, int size, wxIPCFormat format)
+bool wxDDEConnection::DoAdvise(const wxString& item,
+ const void *data,
+ size_t size,
+ wxIPCFormat format)
{
- if (size < 0)
- size = strlen(data);
-
- size ++;
-
- HSZ item_atom = DDEGetAtom(item);
- HSZ topic_atom = DDEGetAtom(m_topicName);
- m_sendingData = data;
- m_dataSize = size;
- m_dataType = format;
- return (DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0);
-}
+ HSZ item_atom = DDEGetAtom(item);
+ HSZ topic_atom = DDEGetAtom(m_topicName);
+ m_sendingData = data; // mrf: potential for scope problems here?
+ m_dataSize = size;
+ // 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 )
+ {
+ DDELogError(_("Failed to send DDE advise notification"));
+ }
-bool wxDDEConnection::OnDisconnect(void)
-{
- delete this;
- return TRUE;
+ return ok;
}
+// ----------------------------------------------------------------------------
+// _DDECallback
+// ----------------------------------------------------------------------------
#define DDERETURN HDDEDATA
-HDDEDATA EXPENTRY _EXPORT _DDECallback(
-WORD wType,
-WORD wFmt,
-HCONV hConv,
-HSZ hsz1,
-HSZ hsz2,
-HDDEDATA hData,
-DWORD /* lData1 */,
-DWORD /* lData2 */)
-{
- switch (wType)
- {
- case XTYP_CONNECT:
- {
- char topic_buf[100];
- char server_buf[100];
- DdeQueryString(DDEIdInst, hsz1, (LPSTR)topic_buf, sizeof(topic_buf),
- CP_WINANSI);
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)server_buf, sizeof(topic_buf),
- CP_WINANSI);
- wxDDEServer *server = DDEFindServer(server_buf);
- if (server)
- {
- wxDDEConnection *connection =
- (wxDDEConnection*) server->OnAcceptConnection(wxString(topic_buf));
- if (connection)
- {
- connection->m_server = server;
- server->GetConnections().Append(connection);
- connection->m_hConv = 0;
- connection->m_topicName = topic_buf;
- DDECurrentlyConnecting = connection;
- return (DDERETURN)TRUE;
- }
- }
- else return (DDERETURN)0;
- break;
- }
-
- case XTYP_CONNECT_CONFIRM:
+HDDEDATA EXPENTRY _EXPORT
+_DDECallback(WORD wType,
+ WORD wFmt,
+ HCONV hConv,
+ HSZ hsz1,
+ HSZ hsz2,
+ HDDEDATA hData,
+ DWORD WXUNUSED(lData1),
+ DWORD WXUNUSED(lData2))
+{
+ switch (wType)
{
- if (DDECurrentlyConnecting)
- {
- DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
- DDECurrentlyConnecting = NULL;
- return (DDERETURN)TRUE;
- }
- else return 0;
- break;
+ case XTYP_CONNECT:
+ {
+ wxString topic = DDEStringFromAtom(hsz1),
+ srv = DDEStringFromAtom(hsz2);
+ wxDDEServer *server = DDEFindServer(srv);
+ if (server)
+ {
+ wxDDEConnection *connection =
+ (wxDDEConnection*) server->OnAcceptConnection(topic);
+ if (connection)
+ {
+ connection->m_server = server;
+ server->GetConnections().Append(connection);
+ connection->m_hConv = 0;
+ connection->m_topicName = topic;
+ DDECurrentlyConnecting = connection;
+ return (DDERETURN)(DWORD)true;
+ }
+ }
+ break;
+ }
+
+ case XTYP_CONNECT_CONFIRM:
+ {
+ if (DDECurrentlyConnecting)
+ {
+ DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
+ DDECurrentlyConnecting = NULL;
+ return (DDERETURN)(DWORD)true;
+ }
+ break;
+ }
+
+ case XTYP_DISCONNECT:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+ if (connection)
+ {
+ connection->SetConnected( false );
+ if (connection->OnDisconnect())
+ {
+ DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
+ return (DDERETURN)(DWORD)true;
+ }
+ }
+ break;
+ }
+
+ case XTYP_EXECUTE:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+ void *data = connection->GetBufferAtLeast(len);
+ wxASSERT_MSG(data != NULL,
+ wxT("Buffer too small in _DDECallback (XTYP_EXECUTE)") );
+
+ DdeGetData(hData, (LPBYTE)data, len, 0);
+
+ DdeFreeDataHandle(hData);
+
+ // XTYP_EXECUTE can be used for text only and the text is
+ // always in ANSI format for ANSI build and Unicode format
+ // in Unicode build
+ #if wxUSE_UNICODE
+ wFmt = wxIPC_UNICODETEXT;
+ #else
+ wFmt = wxIPC_TEXT;
+ #endif
+
+ if ( connection->OnExecute(connection->m_topicName,
+ data,
+ (int)len,
+ (wxIPCFormat)wFmt) )
+ {
+ return (DDERETURN)(DWORD)DDE_FACK;
+ }
+ }
+
+ return (DDERETURN)DDE_FNOTPROCESSED;
+ }
+
+ case XTYP_REQUEST:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ wxString item_name = DDEStringFromAtom(hsz2);
+
+ size_t user_size = wxNO_LEN;
+ const void *data = connection->OnRequest(connection->m_topicName,
+ item_name,
+ &user_size,
+ (wxIPCFormat)wFmt);
+ if (data)
+ {
+ if (user_size == wxNO_LEN)
+ switch (wFmt)
+ {
+ case wxIPC_TEXT:
+ case wxIPC_UTF8TEXT:
+ user_size = strlen((const char*)data) + 1; // includes final NUL
+ break;
+ case wxIPC_UNICODETEXT:
+ user_size = (wcslen((const wchar_t*)data) + 1) * sizeof(wchar_t); // includes final NUL
+ break;
+ default:
+ user_size = 0;
+ }
+
+ HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
+ (LPBYTE)data,
+ user_size,
+ 0,
+ hsz2,
+ wFmt,
+ 0);
+ return (DDERETURN)handle;
+ }
+ }
+ break;
+ }
+
+ case XTYP_POKE:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ wxString item_name = DDEStringFromAtom(hsz2);
+
+ DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+ void *data = connection->GetBufferAtLeast(len);
+ wxASSERT_MSG(data != NULL,
+ wxT("Buffer too small in _DDECallback (XTYP_POKE)") );
+
+ DdeGetData(hData, (LPBYTE)data, len, 0);
+
+ DdeFreeDataHandle(hData);
+
+ connection->OnPoke(connection->m_topicName,
+ item_name,
+ data,
+ (int)len,
+ (wxIPCFormat) wFmt);
+
+ return (DDERETURN)DDE_FACK;
+ }
+ else
+ {
+ return (DDERETURN)DDE_FNOTPROCESSED;
+ }
+ }
+
+ case XTYP_ADVSTART:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ wxString item_name = DDEStringFromAtom(hsz2);
+
+ return (DDERETURN)connection->
+ OnStartAdvise(connection->m_topicName, item_name);
+ }
+
+ break;
+ }
+
+ case XTYP_ADVSTOP:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ wxString item_name = DDEStringFromAtom(hsz2);
+
+ return (DDERETURN)connection->
+ OnStopAdvise(connection->m_topicName, item_name);
+ }
+
+ break;
+ }
+
+ case XTYP_ADVREQ:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection && connection->m_sendingData)
+ {
+ HDDEDATA data = DdeCreateDataHandle
+ (
+ DDEIdInst,
+ (LPBYTE)connection->m_sendingData,
+ connection->m_dataSize,
+ 0,
+ hsz2,
+ connection->m_dataType,
+ 0
+ );
+
+ connection->m_sendingData = NULL;
+
+ return (DDERETURN)data;
+ }
+
+ break;
+ }
+
+ case XTYP_ADVDATA:
+ {
+ wxDDEConnection *connection = DDEFindConnection(hConv);
+
+ if (connection)
+ {
+ wxString item_name = DDEStringFromAtom(hsz2);
+
+ DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+ void *data = connection->GetBufferAtLeast(len);
+ wxASSERT_MSG(data != NULL,
+ wxT("Buffer too small in _DDECallback (XTYP_ADVDATA)") );
+
+ DdeGetData(hData, (LPBYTE)data, len, 0);
+
+ DdeFreeDataHandle(hData);
+ if ( connection->OnAdvise(connection->m_topicName,
+ item_name,
+ data,
+ (int)len,
+ (wxIPCFormat) wFmt) )
+ {
+ return (DDERETURN)(DWORD)DDE_FACK;
+ }
+ }
+
+ return (DDERETURN)DDE_FNOTPROCESSED;
+ }
}
- case XTYP_DISCONNECT:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
- if (connection && connection->OnDisconnect())
- {
- DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
- return (DDERETURN)TRUE;
- }
- else return (DDERETURN)0;
- break;
- }
+ return (DDERETURN)0;
+}
- case XTYP_EXECUTE:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
+// ----------------------------------------------------------------------------
+// DDE strings and atoms
+// ----------------------------------------------------------------------------
- if (connection)
- {
- DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
- DdeFreeDataHandle(hData);
- if (connection->OnExecute(connection->m_topicName, connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
- return (DDERETURN)DDE_FACK;
- else
- return (DDERETURN)DDE_FNOTPROCESSED;
- } else return (DDERETURN)DDE_FNOTPROCESSED;
- break;
- }
+// Atom table stuff
+static HSZ DDEAddAtom(const wxString& str)
+{
+ HSZ atom = DDEAtomFromString(str);
+ wxAtomTable[str] = atom;
+ return atom;
+}
- case XTYP_REQUEST:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
+static HSZ DDEGetAtom(const wxString& str)
+{
+ wxAtomMap::iterator it = wxAtomTable.find(str);
- if (connection)
- {
- char item_name[200];
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)item_name, sizeof(item_name),
- CP_WINANSI);
+ if (it != wxAtomTable.end())
+ return it->second;
- int user_size = -1;
- char *data = connection->OnRequest(connection->m_topicName, wxString(item_name), &user_size, (wxIPCFormat) wFmt);
- if (data)
- {
- if (user_size < 0) user_size = strlen(data);
+ return DDEAddAtom(str);
+}
- HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
- (LPBYTE)data, user_size + 1, 0, hsz2, wFmt, 0);
- return (DDERETURN)handle;
- } else return (DDERETURN)0;
- } else return (DDERETURN)0;
- break;
- }
+/* atom <-> strings
+The returned handle has to be freed by the caller (using
+(static) DDEFreeString).
+*/
+static HSZ DDEAtomFromString(const wxString& s)
+{
+ wxASSERT_MSG( DDEIdInst, wxT("DDE not initialized") );
- case XTYP_POKE:
+ HSZ hsz = DdeCreateStringHandle(DDEIdInst, (wxChar*)s.wx_str(), DDE_CP);
+ if ( !hsz )
{
- wxDDEConnection *connection = DDEFindConnection(hConv);
-
- if (connection)
- {
- char item_name[200];
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)item_name, sizeof(item_name),
- CP_WINANSI);
- DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
- DdeFreeDataHandle(hData);
- connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
- return (DDERETURN)DDE_FACK;
- } else return (DDERETURN)DDE_FNOTPROCESSED;
- break;
+ DDELogError(_("Failed to create DDE string"));
}
- case XTYP_ADVSTART:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
-
- if (connection)
- {
- char item_name[200];
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)item_name, sizeof(item_name),
- CP_WINANSI);
+ return hsz;
+}
- return (DDERETURN)connection->OnStartAdvise(connection->m_topicName, wxString(item_name));
- } else return (DDERETURN)0;
- break;
- }
+static wxString DDEStringFromAtom(HSZ hsz)
+{
+ // all DDE strings are normally limited to 255 bytes
+ static const size_t len = 256;
- case XTYP_ADVSTOP:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
+ wxString s;
+ (void)DdeQueryString(DDEIdInst, hsz, wxStringBuffer(s, len), len, DDE_CP);
- if (connection)
- {
- char item_name[200];
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)item_name, sizeof(item_name),
- CP_WINANSI);
- return (DDERETURN)connection->OnStopAdvise(connection->m_topicName, wxString(item_name));
- } else return (DDERETURN)0;
- break;
- }
+ return s;
+}
- case XTYP_ADVREQ:
- {
- wxDDEConnection *connection = DDEFindConnection(hConv);
+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);
+}
- if (connection && connection->m_sendingData)
- {
- HDDEDATA data = DdeCreateDataHandle(DDEIdInst,
- (LPBYTE)connection->m_sendingData,
- connection->m_dataSize, 0, hsz2, connection->m_dataType, 0);
- connection->m_sendingData = NULL;
- return (DDERETURN)data;
- } else return (DDERETURN)NULL;
- break;
- }
+// ----------------------------------------------------------------------------
+// error handling
+// ----------------------------------------------------------------------------
- case XTYP_ADVDATA:
+static void DDELogError(const wxString& s, UINT error)
+{
+ if ( !error )
{
- wxDDEConnection *connection = DDEFindConnection(hConv);
+ error = DdeGetLastError(DDEIdInst);
+ }
- if (connection)
- {
- char item_name[200];
- DdeQueryString(DDEIdInst, hsz2, (LPSTR)item_name, sizeof(item_name),
- CP_WINANSI);
+ wxLogError(s + wxT(": ") + DDEGetErrorMsg(error));
+}
- DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
- DdeFreeDataHandle(hData);
- if (connection->OnAdvise(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
- return (DDERETURN)DDE_FACK;
- else
- return (DDERETURN)DDE_FNOTPROCESSED;
- } else return (DDERETURN)DDE_FNOTPROCESSED;
- break;
+static wxString DDEGetErrorMsg(UINT error)
+{
+ wxString err;
+ switch ( error )
+ {
+ case DMLERR_NO_ERROR:
+ err = _("no DDE error.");
+ break;
+
+ case DMLERR_ADVACKTIMEOUT:
+ err = _("a request for a synchronous advise transaction has timed out.");
+ break;
+ case DMLERR_BUSY:
+ err = _("the response to the transaction caused the DDE_FBUSY bit to be set.");
+ break;
+ case DMLERR_DATAACKTIMEOUT:
+ 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,\nor an invalid instance identifier\nwas passed to a DDEML function.");
+ break;
+ case DMLERR_DLL_USAGE:
+ 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.");
+ break;
+ case DMLERR_INVALIDPARAMETER:
+ err = _("a parameter failed to be validated by the DDEML.");
+ break;
+ case DMLERR_LOW_MEMORY:
+ err = _("a DDEML application has created a prolonged race condition.");
+ break;
+ case DMLERR_MEMORY_ERROR:
+ err = _("a memory allocation failed.");
+ break;
+ case DMLERR_NO_CONV_ESTABLISHED:
+ err = _("a client's attempt to establish a conversation has failed.");
+ break;
+ case DMLERR_NOTPROCESSED:
+ err = _("a transaction failed.");
+ break;
+ case DMLERR_POKEACKTIMEOUT:
+ err = _("a request for a synchronous poke transaction has timed out.");
+ break;
+ case DMLERR_POSTMSG_FAILED:
+ err = _("an internal call to the PostMessage function has failed. ");
+ break;
+ case DMLERR_REENTRANCY:
+ err = _("reentrancy problem.");
+ break;
+ case DMLERR_SERVER_DIED:
+ 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.");
+ break;
+ case DMLERR_UNADVACKTIMEOUT:
+ 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.\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);
}
- }
- return 0;
-}
-// Atom table stuff
-static HSZ DDEAddAtom(const wxString& string)
-{
- HSZ atom = DdeCreateStringHandle(DDEIdInst, (char*) (const char *)string, CP_WINANSI);
- wxAtomTable.Append(string, (wxObject *)atom);
- return atom;
-}
-
-static HSZ DDEGetAtom(const wxString& string)
-{
- wxNode *node = wxAtomTable.Find(string);
- if (node)
- return (HSZ)node->Data();
- else
- {
- DDEAddAtom(string);
- return (HSZ)(wxAtomTable.Find(string)->Data());
- }
-}
-
-void DDEPrintError(void)
-{
- char *err = NULL;
- switch (DdeGetLastError(DDEIdInst))
- {
- case DMLERR_ADVACKTIMEOUT:
- err = "A request for a synchronous advise transaction has timed out.";
- break;
- case DMLERR_BUSY:
- err = "The response to the transaction caused the DDE_FBUSY bit to be set.";
- break;
- case DMLERR_DATAACKTIMEOUT:
- 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.";
- 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.";
- break;
- case DMLERR_EXECACKTIMEOUT:
- err = "A request for a synchronous execute transaction has timed out.";
- break;
- case DMLERR_INVALIDPARAMETER:
- err = "A parameter failed to be validated by the DDEML.";
- break;
- case DMLERR_LOW_MEMORY:
- err = "A DDEML application has created a prolonged race condition.";
- break;
- case DMLERR_MEMORY_ERROR:
- err = "A memory allocation failed.";
- break;
- case DMLERR_NO_CONV_ESTABLISHED:
- err = "A client's attempt to establish a conversation has failed.";
- break;
- case DMLERR_NOTPROCESSED:
- err = "A transaction failed.";
- break;
- case DMLERR_POKEACKTIMEOUT:
- err = "A request for a synchronous poke transaction has timed out.";
- break;
- case DMLERR_POSTMSG_FAILED:
- err = "An internal call to the PostMessage function has failed. ";
- break;
- case DMLERR_REENTRANCY:
- 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.";
- break;
- case DMLERR_SYS_ERROR:
- err = "An internal error has occurred in the DDEML.";
- break;
- case DMLERR_UNADVACKTIMEOUT:
- 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.";
- break;
- default:
- err = "Unrecognised error type.";
- break;
- }
- MessageBox((HWND) NULL, (LPCSTR)err, "DDE Error", MB_OK | MB_ICONINFORMATION);
+ return err;
}
#endif