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