]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/dde.cpp
Had missed one LPSTR.
[wxWidgets.git] / src / msw / dde.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: dde.cpp
3// Purpose: DDE classes
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "dde.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/defs.h"
25#endif
26
27#if wxUSE_IPC
28
29#ifndef WX_PRECOMP
30#include "wx/utils.h"
31#include "wx/app.h"
32#endif
33
34#include "wx/module.h"
35#include "wx/dde.h"
36
37#include "wx/msw/private.h"
38#include <windows.h>
39#include <ddeml.h>
40
41#ifndef __TWIN32__
42#ifdef __GNUWIN32__
43#include "wx/msw/gnuwin32/extra.h"
44#endif
45#endif
46
47#include <string.h>
48
49#ifdef __WIN32__
50#define _EXPORT /**/
51#else
52#define _EXPORT _export
53#endif
54
55#if !USE_SHARED_LIBRARY
56IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
57IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
58IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
59#endif
60
61static wxDDEConnection *DDEFindConnection(HCONV hConv);
62static void DDEDeleteConnection(HCONV hConv);
63static wxDDEServer *DDEFindServer(const wxString& s);
64
65extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(
66WORD wType,
67WORD wFmt,
68HCONV hConv,
69HSZ hsz1,
70HSZ hsz2,
71HDDEDATA hData,
72DWORD lData1,
73DWORD lData2);
74
75// Add topic name to atom table before using in conversations
76static HSZ DDEAddAtom(const wxString& string);
77static HSZ DDEGetAtom(const wxString& string);
78static void DDEPrintError(void);
79
80static DWORD DDEIdInst = 0L;
81static wxDDEConnection *DDECurrentlyConnecting = NULL;
82
83static wxList wxAtomTable(wxKEY_STRING);
84static wxList wxDDEClientObjects;
85static wxList wxDDEServerObjects;
86
87char *DDEDefaultIPCBuffer = NULL;
88int DDEDefaultIPCBufferSize = 0;
89
90/*
91 * Initialization
92 *
93 */
94
95static bool DDEInitialized = FALSE;
96
97void wxDDEInitialize()
98{
99 if (DDEInitialized)
100 return;
101 DDEInitialized = TRUE;
102
103 // Should insert filter flags
104 DdeInitialize(&DDEIdInst, (PFNCALLBACK)MakeProcInstance(
105 (FARPROC)_DDECallback, wxGetInstance()),
106 APPCLASS_STANDARD,
107 0L);
108}
109
110/*
111 * CleanUp
112 */
113
114void wxDDECleanUp()
115{
116 if (DDEIdInst != 0)
117 {
118 DdeUninitialize(DDEIdInst);
119 DDEIdInst = 0;
120 }
121 if (DDEDefaultIPCBuffer)
122 delete [] DDEDefaultIPCBuffer ;
123}
124
125// A module to allow DDE initialization/cleanup
126// without calling these functions from app.cpp or from
127// the user's application.
128
129class wxDDEModule: public wxModule
130{
131DECLARE_DYNAMIC_CLASS(wxDDEModule)
132public:
133 wxDDEModule() {}
134 bool OnInit() { wxDDEInitialize(); return TRUE; };
135 void OnExit() { wxDDECleanUp(); };
136};
137
138IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
139
140// Global find connection
141static wxDDEConnection *DDEFindConnection(HCONV hConv)
142{
143 wxNode *node = wxDDEServerObjects.First();
144 wxDDEConnection *found = NULL;
145 while (node && !found)
146 {
147 wxDDEServer *object = (wxDDEServer *)node->Data();
148 found = object->FindConnection((WXHCONV) hConv);
149 node = node->Next();
150 }
151 if (found)
152 return found;
153
154 node = wxDDEClientObjects.First();
155 while (node && !found)
156 {
157 wxDDEClient *object = (wxDDEClient *)node->Data();
158 found = object->FindConnection((WXHCONV) hConv);
159 node = node->Next();
160 }
161 return found;
162}
163
164// Global delete connection
165static void DDEDeleteConnection(HCONV hConv)
166{
167 wxNode *node = wxDDEServerObjects.First();
168 bool found = FALSE;
169 while (node && !found)
170 {
171 wxDDEServer *object = (wxDDEServer *)node->Data();
172 found = object->DeleteConnection((WXHCONV) hConv);
173 node = node->Next();
174 }
175 if (found)
176 return;
177
178 node = wxDDEServerObjects.First();
179 while (node && !found)
180 {
181 wxDDEClient *object = (wxDDEClient *)node->Data();
182 found = object->DeleteConnection((WXHCONV) hConv);
183 node = node->Next();
184 }
185}
186
187// Find a server from a service name
188static wxDDEServer *DDEFindServer(const wxString& s)
189{
190 wxNode *node = wxDDEServerObjects.First();
191 wxDDEServer *found = NULL;
192 while (node && !found)
193 {
194 wxDDEServer *object = (wxDDEServer *)node->Data();
195
196 if (object->GetServiceName() == s)
197 found = object;
198 else node = node->Next();
199 }
200 return found;
201}
202
203/*
204 * Server
205 *
206 */
207
208wxDDEServer::wxDDEServer(void)
209{
210 m_serviceName = "";
211 wxDDEServerObjects.Append(this);
212}
213
214bool wxDDEServer::Create(const wxString& server_name)
215{
216 m_serviceName = server_name;
217 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
218
219 if (DdeNameService(DDEIdInst, serviceName, (HSZ) NULL, DNS_REGISTER) == 0)
220 {
221 DDEPrintError();
222 return FALSE;
223 }
224 return TRUE;
225}
226
227wxDDEServer::~wxDDEServer(void)
228{
229 if (m_serviceName != _T(""))
230 {
231 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST m_serviceName, CP_WINANSI);
232 if (DdeNameService(DDEIdInst, serviceName, NULL, DNS_UNREGISTER) == 0)
233 {
234 DDEPrintError();
235 }
236 }
237 wxDDEServerObjects.DeleteObject(this);
238
239 wxNode *node = m_connections.First();
240 while (node)
241 {
242 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
243 wxNode *next = node->Next();
244 connection->OnDisconnect(); // May delete the node implicitly
245 node = next;
246 }
247
248 // If any left after this, delete them
249 node = m_connections.First();
250 while (node)
251 {
252 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
253 wxNode *next = node->Next();
254 delete connection;
255 node = next;
256 }
257}
258
259wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */)
260{
261 return new wxDDEConnection;
262}
263
264wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv)
265{
266 wxNode *node = m_connections.First();
267 wxDDEConnection *found = NULL;
268 while (node && !found)
269 {
270 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
271 if (connection->m_hConv == conv)
272 found = connection;
273 else node = node->Next();
274 }
275 return found;
276}
277
278// Only delete the entry in the map, not the actual connection
279bool wxDDEServer::DeleteConnection(WXHCONV conv)
280{
281 wxNode *node = m_connections.First();
282 bool found = FALSE;
283 while (node && !found)
284 {
285 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
286 if (connection->m_hConv == conv)
287 {
288 found = TRUE;
289 delete node;
290 }
291 else node = node->Next();
292 }
293 return found;
294}
295
296
297/*
298 * Client
299 *
300 */
301
302
303wxDDEClient::wxDDEClient(void)
304{
305 wxDDEClientObjects.Append(this);
306}
307
308wxDDEClient::~wxDDEClient(void)
309{
310 wxDDEClientObjects.DeleteObject(this);
311 wxNode *node = m_connections.First();
312 while (node)
313 {
314 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
315 delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
316 node = m_connections.First();
317 }
318}
319
320bool wxDDEClient::ValidHost(const wxString& /* host */)
321{
322 return TRUE;
323}
324
325wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const wxString& server_name, const wxString& topic)
326{
327 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
328 HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST topic, CP_WINANSI);
329
330 HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL);
331 if (hConv == (HCONV) NULL)
332 return (wxConnectionBase*) NULL;
333 else
334 {
335 wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
336 if (connection)
337 {
338 connection->m_hConv = (WXHCONV) hConv;
339 connection->m_topicName = topic;
340 connection->m_client = this;
341 m_connections.Append(connection);
342 return connection;
343 }
344 else return (wxConnectionBase*) NULL;
345 }
346}
347
348wxConnectionBase *wxDDEClient::OnMakeConnection(void)
349{
350 return new wxDDEConnection;
351}
352
353wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv)
354{
355 wxNode *node = m_connections.First();
356 wxDDEConnection *found = NULL;
357 while (node && !found)
358 {
359 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
360 if (connection->m_hConv == conv)
361 found = connection;
362 else node = node->Next();
363 }
364 return found;
365}
366
367// Only delete the entry in the map, not the actual connection
368bool wxDDEClient::DeleteConnection(WXHCONV conv)
369{
370 wxNode *node = m_connections.First();
371 bool found = FALSE;
372 while (node && !found)
373 {
374 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
375 if (connection->m_hConv == conv)
376 {
377 found = TRUE;
378 delete node;
379 }
380 else node = node->Next();
381 }
382 return found;
383}
384
385/*
386 * Connection
387 */
388
389wxDDEConnection::wxDDEConnection(char *buffer, int size)
390{
391 if (buffer == NULL)
392 {
393 if (DDEDefaultIPCBuffer == NULL)
394 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
395 m_bufPtr = DDEDefaultIPCBuffer;
396 m_bufSize = DDEDefaultIPCBufferSize;
397 }
398 else
399 {
400 m_bufPtr = buffer;
401 m_bufSize = size;
402 }
403
404 m_topicName = "";
405
406 m_client = NULL;
407 m_server = NULL;
408
409 m_hConv = 0;
410 m_sendingData = NULL;
411}
412
413wxDDEConnection::wxDDEConnection(void)
414{
415 m_hConv = 0;
416 m_sendingData = NULL;
417 m_server = NULL;
418 m_client = NULL;
419 if (DDEDefaultIPCBuffer == NULL)
420 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
421
422 m_bufPtr = DDEDefaultIPCBuffer;
423 m_bufSize = DDEDefaultIPCBufferSize;
424 m_topicName = "";
425}
426
427wxDDEConnection::~wxDDEConnection(void)
428{
429 if (m_server)
430 m_server->GetConnections().DeleteObject(this);
431 else
432 m_client->GetConnections().DeleteObject(this);
433}
434
435// Calls that CLIENT can make
436bool wxDDEConnection::Disconnect(void)
437{
438 DDEDeleteConnection((HCONV) m_hConv);
439 return (DdeDisconnect((HCONV) m_hConv) != 0);
440}
441
442bool wxDDEConnection::Execute(wxChar *data, int size, wxIPCFormat format)
443{
444 DWORD result;
445 if (size < 0)
446 size = wxStrlen(data);
447
448 size ++;
449
450 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
451 NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
452}
453
454char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
455{
456 DWORD result;
457 HSZ atom = DDEGetAtom(item);
458
459 HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
460 atom, format, XTYP_REQUEST, 5000, &result);
461
462 DWORD len = DdeGetData(returned_data, (LPBYTE)(m_bufPtr), m_bufSize, 0);
463
464 DdeFreeDataHandle(returned_data);
465
466 if (size) *size = (int)len;
467 if (len > 0)
468 {
469 return m_bufPtr;
470 }
471 else return NULL;
472}
473
474bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
475{
476 DWORD result;
477 if (size < 0)
478 size = wxStrlen(data);
479
480 size ++;
481
482 HSZ item_atom = DDEGetAtom(item);
483 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
484 item_atom, format, XTYP_POKE, 5000, &result) ? TRUE : FALSE);
485}
486
487bool wxDDEConnection::StartAdvise(const wxString& item)
488{
489 DWORD result;
490 HSZ atom = DDEGetAtom(item);
491
492 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
493 atom, CF_TEXT, XTYP_ADVSTART, 5000, &result) ? TRUE : FALSE);
494}
495
496bool wxDDEConnection::StopAdvise(const wxString& item)
497{
498 DWORD result;
499 HSZ atom = DDEGetAtom(item);
500
501 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
502 atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE);
503}
504
505// Calls that SERVER can make
506bool wxDDEConnection::Advise(const wxString& item, wxChar *data, int size, wxIPCFormat format)
507{
508 if (size < 0)
509 size = wxStrlen(data);
510
511 size ++;
512
513 HSZ item_atom = DDEGetAtom(item);
514 HSZ topic_atom = DDEGetAtom(m_topicName);
515 m_sendingData = data;
516 m_dataSize = size;
517 m_dataType = format;
518 return (DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0);
519}
520
521bool wxDDEConnection::OnDisconnect(void)
522{
523 delete this;
524 return TRUE;
525}
526
527
528#define DDERETURN HDDEDATA
529
530HDDEDATA EXPENTRY _EXPORT _DDECallback(
531WORD wType,
532WORD wFmt,
533HCONV hConv,
534HSZ hsz1,
535HSZ hsz2,
536HDDEDATA hData,
537DWORD /* lData1 */,
538DWORD /* lData2 */)
539{
540 switch (wType)
541 {
542 case XTYP_CONNECT:
543 {
544 wxChar topic_buf[100];
545 wxChar server_buf[100];
546 DdeQueryString(DDEIdInst, hsz1, (LPTSTR)topic_buf, WXSIZEOF(topic_buf),
547 CP_WINANSI);
548 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)server_buf, WXSIZEOF(topic_buf),
549 CP_WINANSI);
550 wxDDEServer *server = DDEFindServer(server_buf);
551 if (server)
552 {
553 wxDDEConnection *connection =
554 (wxDDEConnection*) server->OnAcceptConnection(wxString(topic_buf));
555 if (connection)
556 {
557 connection->m_server = server;
558 server->GetConnections().Append(connection);
559 connection->m_hConv = 0;
560 connection->m_topicName = topic_buf;
561 DDECurrentlyConnecting = connection;
562 return (DDERETURN)TRUE;
563 }
564 }
565 else return (DDERETURN)0;
566 break;
567 }
568
569 case XTYP_CONNECT_CONFIRM:
570 {
571 if (DDECurrentlyConnecting)
572 {
573 DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
574 DDECurrentlyConnecting = NULL;
575 return (DDERETURN)TRUE;
576 }
577 else return 0;
578 break;
579 }
580
581 case XTYP_DISCONNECT:
582 {
583 wxDDEConnection *connection = DDEFindConnection(hConv);
584 if (connection && connection->OnDisconnect())
585 {
586 DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
587 return (DDERETURN)TRUE;
588 }
589 else return (DDERETURN)0;
590 break;
591 }
592
593 case XTYP_EXECUTE:
594 {
595 wxDDEConnection *connection = DDEFindConnection(hConv);
596
597 if (connection)
598 {
599 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
600 DdeFreeDataHandle(hData);
601 if (connection->OnExecute(connection->m_topicName, connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
602 return (DDERETURN)DDE_FACK;
603 else
604 return (DDERETURN)DDE_FNOTPROCESSED;
605 } else return (DDERETURN)DDE_FNOTPROCESSED;
606 break;
607 }
608
609 case XTYP_REQUEST:
610 {
611 wxDDEConnection *connection = DDEFindConnection(hConv);
612
613 if (connection)
614 {
615 wxChar item_name[200];
616 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
617 CP_WINANSI);
618
619 int user_size = -1;
620 char *data = connection->OnRequest(connection->m_topicName, wxString(item_name), &user_size, (wxIPCFormat) wFmt);
621 if (data)
622 {
623 if (user_size < 0) user_size = strlen(data);
624
625 HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
626 (LPBYTE)data, user_size + 1, 0, hsz2, wFmt, 0);
627 return (DDERETURN)handle;
628 } else return (DDERETURN)0;
629 } else return (DDERETURN)0;
630 break;
631 }
632
633 case XTYP_POKE:
634 {
635 wxDDEConnection *connection = DDEFindConnection(hConv);
636
637 if (connection)
638 {
639 wxChar item_name[200];
640 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
641 CP_WINANSI);
642 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
643 DdeFreeDataHandle(hData);
644 connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
645 return (DDERETURN)DDE_FACK;
646 } else return (DDERETURN)DDE_FNOTPROCESSED;
647 break;
648 }
649
650 case XTYP_ADVSTART:
651 {
652 wxDDEConnection *connection = DDEFindConnection(hConv);
653
654 if (connection)
655 {
656 wxChar item_name[200];
657 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
658 CP_WINANSI);
659
660 return (DDERETURN)connection->OnStartAdvise(connection->m_topicName, wxString(item_name));
661 } else return (DDERETURN)0;
662 break;
663 }
664
665 case XTYP_ADVSTOP:
666 {
667 wxDDEConnection *connection = DDEFindConnection(hConv);
668
669 if (connection)
670 {
671 wxChar item_name[200];
672 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
673 CP_WINANSI);
674 return (DDERETURN)connection->OnStopAdvise(connection->m_topicName, wxString(item_name));
675 } else return (DDERETURN)0;
676 break;
677 }
678
679 case XTYP_ADVREQ:
680 {
681 wxDDEConnection *connection = DDEFindConnection(hConv);
682
683 if (connection && connection->m_sendingData)
684 {
685 HDDEDATA data = DdeCreateDataHandle(DDEIdInst,
686 (LPBYTE)connection->m_sendingData,
687 connection->m_dataSize, 0, hsz2, connection->m_dataType, 0);
688 connection->m_sendingData = NULL;
689 return (DDERETURN)data;
690 } else return (DDERETURN)NULL;
691 break;
692 }
693
694 case XTYP_ADVDATA:
695 {
696 wxDDEConnection *connection = DDEFindConnection(hConv);
697
698 if (connection)
699 {
700 wxChar item_name[200];
701 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
702 CP_WINANSI);
703
704 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
705 DdeFreeDataHandle(hData);
706 if (connection->OnAdvise(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
707 return (DDERETURN)DDE_FACK;
708 else
709 return (DDERETURN)DDE_FNOTPROCESSED;
710 } else return (DDERETURN)DDE_FNOTPROCESSED;
711 break;
712 }
713 }
714 return 0;
715}
716
717// Atom table stuff
718static HSZ DDEAddAtom(const wxString& string)
719{
720 HSZ atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST string, CP_WINANSI);
721 wxAtomTable.Append(string, (wxObject *)atom);
722 return atom;
723}
724
725static HSZ DDEGetAtom(const wxString& string)
726{
727 wxNode *node = wxAtomTable.Find(string);
728 if (node)
729 return (HSZ)node->Data();
730 else
731 {
732 DDEAddAtom(string);
733 return (HSZ)(wxAtomTable.Find(string)->Data());
734 }
735}
736
737void DDEPrintError(void)
738{
739 wxChar *err = NULL;
740 switch (DdeGetLastError(DDEIdInst))
741 {
742 case DMLERR_ADVACKTIMEOUT:
743 err = _T("A request for a synchronous advise transaction has timed out.");
744 break;
745 case DMLERR_BUSY:
746 err = _T("The response to the transaction caused the DDE_FBUSY bit to be set.");
747 break;
748 case DMLERR_DATAACKTIMEOUT:
749 err = _T("A request for a synchronous data transaction has timed out.");
750 break;
751 case DMLERR_DLL_NOT_INITIALIZED:
752 err = _T("A DDEML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DDEML function.");
753 break;
754 case DMLERR_DLL_USAGE:
755 err = _T("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.");
756 break;
757 case DMLERR_EXECACKTIMEOUT:
758 err = _T("A request for a synchronous execute transaction has timed out.");
759 break;
760 case DMLERR_INVALIDPARAMETER:
761 err = _T("A parameter failed to be validated by the DDEML.");
762 break;
763 case DMLERR_LOW_MEMORY:
764 err = _T("A DDEML application has created a prolonged race condition.");
765 break;
766 case DMLERR_MEMORY_ERROR:
767 err = _T("A memory allocation failed.");
768 break;
769 case DMLERR_NO_CONV_ESTABLISHED:
770 err = _T("A client's attempt to establish a conversation has failed.");
771 break;
772 case DMLERR_NOTPROCESSED:
773 err = _T("A transaction failed.");
774 break;
775 case DMLERR_POKEACKTIMEOUT:
776 err = _T("A request for a synchronous poke transaction has timed out.");
777 break;
778 case DMLERR_POSTMSG_FAILED:
779 err = _T("An internal call to the PostMessage function has failed. ");
780 break;
781 case DMLERR_REENTRANCY:
782 err = _T("Reentrancy problem.");
783 break;
784 case DMLERR_SERVER_DIED:
785 err = _T("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.");
786 break;
787 case DMLERR_SYS_ERROR:
788 err = _T("An internal error has occurred in the DDEML.");
789 break;
790 case DMLERR_UNADVACKTIMEOUT:
791 err = _T("A request to end an advise transaction has timed out.");
792 break;
793 case DMLERR_UNFOUND_QUEUE_ID:
794 err = _T("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.");
795 break;
796 default:
797 err = _T("Unrecognised error type.");
798 break;
799 }
800 MessageBox((HWND) NULL, (LPCTSTR)err, _T("DDE Error"), MB_OK | MB_ICONINFORMATION);
801}
802
803#endif
804 // wxUSE_IPC