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