]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dde.cpp
Fixed core dump for when there is no image list on the TreeCtrl
[wxWidgets.git] / src / msw / dde.cpp
CommitLineData
2bda0e17
KB
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
47d67540 27#if wxUSE_IPC
2bda0e17
KB
28
29#ifndef WX_PRECOMP
30#include "wx/utils.h"
31#include "wx/app.h"
32#endif
33
e2a6f233 34#include "wx/module.h"
2bda0e17
KB
35#include "wx/dde.h"
36
03ab016d
JS
37#include "wx/msw/private.h"
38#include <windows.h>
39#include <ddeml.h>
40
57c208c5 41#ifndef __TWIN32__
2bda0e17
KB
42#ifdef __GNUWIN32__
43#include "wx/msw/gnuwin32/extra.h"
44#endif
57c208c5 45#endif
2bda0e17 46
2bda0e17
KB
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
e2a6f233
JS
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
2bda0e17
KB
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{
b3324be2 210 m_serviceName = "";
2bda0e17
KB
211 wxDDEServerObjects.Append(this);
212}
213
214bool wxDDEServer::Create(const wxString& server_name)
215{
b3324be2 216 m_serviceName = server_name;
837e5743 217 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
2bda0e17 218
57c208c5 219 if (DdeNameService(DDEIdInst, serviceName, (HSZ) NULL, DNS_REGISTER) == 0)
2bda0e17
KB
220 {
221 DDEPrintError();
222 return FALSE;
223 }
224 return TRUE;
225}
226
227wxDDEServer::~wxDDEServer(void)
228{
837e5743 229 if (m_serviceName != _T(""))
2bda0e17 230 {
837e5743 231 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST m_serviceName, CP_WINANSI);
2bda0e17
KB
232 if (DdeNameService(DDEIdInst, serviceName, NULL, DNS_UNREGISTER) == 0)
233 {
234 DDEPrintError();
235 }
236 }
237 wxDDEServerObjects.DeleteObject(this);
238
b3324be2 239 wxNode *node = m_connections.First();
2bda0e17
KB
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
b3324be2 249 node = m_connections.First();
2bda0e17
KB
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{
b3324be2 266 wxNode *node = m_connections.First();
2bda0e17
KB
267 wxDDEConnection *found = NULL;
268 while (node && !found)
269 {
270 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 271 if (connection->m_hConv == conv)
2bda0e17
KB
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{
b3324be2 281 wxNode *node = m_connections.First();
2bda0e17
KB
282 bool found = FALSE;
283 while (node && !found)
284 {
285 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 286 if (connection->m_hConv == conv)
2bda0e17
KB
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);
b3324be2 311 wxNode *node = m_connections.First();
2bda0e17
KB
312 while (node)
313 {
314 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
315 delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
b3324be2 316 node = m_connections.First();
2bda0e17
KB
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{
837e5743
OK
327 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
328 HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST topic, CP_WINANSI);
2bda0e17
KB
329
330 HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL);
57c208c5
JS
331 if (hConv == (HCONV) NULL)
332 return (wxConnectionBase*) NULL;
2bda0e17
KB
333 else
334 {
335 wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
336 if (connection)
337 {
b3324be2
JS
338 connection->m_hConv = (WXHCONV) hConv;
339 connection->m_topicName = topic;
340 connection->m_client = this;
341 m_connections.Append(connection);
2bda0e17
KB
342 return connection;
343 }
57c208c5 344 else return (wxConnectionBase*) NULL;
2bda0e17
KB
345 }
346}
347
348wxConnectionBase *wxDDEClient::OnMakeConnection(void)
349{
350 return new wxDDEConnection;
351}
352
353wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv)
354{
b3324be2 355 wxNode *node = m_connections.First();
2bda0e17
KB
356 wxDDEConnection *found = NULL;
357 while (node && !found)
358 {
359 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 360 if (connection->m_hConv == conv)
2bda0e17
KB
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{
b3324be2 370 wxNode *node = m_connections.First();
2bda0e17
KB
371 bool found = FALSE;
372 while (node && !found)
373 {
374 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 375 if (connection->m_hConv == conv)
2bda0e17
KB
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];
b3324be2
JS
395 m_bufPtr = DDEDefaultIPCBuffer;
396 m_bufSize = DDEDefaultIPCBufferSize;
2bda0e17
KB
397 }
398 else
399 {
b3324be2
JS
400 m_bufPtr = buffer;
401 m_bufSize = size;
2bda0e17
KB
402 }
403
b3324be2 404 m_topicName = "";
2bda0e17 405
b3324be2
JS
406 m_client = NULL;
407 m_server = NULL;
2bda0e17 408
b3324be2
JS
409 m_hConv = 0;
410 m_sendingData = NULL;
2bda0e17
KB
411}
412
413wxDDEConnection::wxDDEConnection(void)
414{
b3324be2
JS
415 m_hConv = 0;
416 m_sendingData = NULL;
417 m_server = NULL;
418 m_client = NULL;
2bda0e17
KB
419 if (DDEDefaultIPCBuffer == NULL)
420 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
421
b3324be2
JS
422 m_bufPtr = DDEDefaultIPCBuffer;
423 m_bufSize = DDEDefaultIPCBufferSize;
424 m_topicName = "";
2bda0e17
KB
425}
426
427wxDDEConnection::~wxDDEConnection(void)
428{
b3324be2
JS
429 if (m_server)
430 m_server->GetConnections().DeleteObject(this);
2bda0e17 431 else
b3324be2 432 m_client->GetConnections().DeleteObject(this);
2bda0e17
KB
433}
434
435// Calls that CLIENT can make
436bool wxDDEConnection::Disconnect(void)
437{
b3324be2
JS
438 DDEDeleteConnection((HCONV) m_hConv);
439 return (DdeDisconnect((HCONV) m_hConv) != 0);
2bda0e17
KB
440}
441
837e5743 442bool wxDDEConnection::Execute(wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
443{
444 DWORD result;
445 if (size < 0)
837e5743 446 size = wxStrlen(data);
2bda0e17
KB
447
448 size ++;
449
b3324be2 450 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
2bda0e17
KB
451 NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
452}
453
0d2a2b60 454char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
2bda0e17
KB
455{
456 DWORD result;
457 HSZ atom = DDEGetAtom(item);
458
b3324be2 459 HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
460 atom, format, XTYP_REQUEST, 5000, &result);
461
b3324be2 462 DWORD len = DdeGetData(returned_data, (LPBYTE)(m_bufPtr), m_bufSize, 0);
2bda0e17
KB
463
464 DdeFreeDataHandle(returned_data);
465
466 if (size) *size = (int)len;
467 if (len > 0)
468 {
b3324be2 469 return m_bufPtr;
2bda0e17
KB
470 }
471 else return NULL;
472}
473
837e5743 474bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
475{
476 DWORD result;
477 if (size < 0)
837e5743 478 size = wxStrlen(data);
2bda0e17
KB
479
480 size ++;
481
482 HSZ item_atom = DDEGetAtom(item);
b3324be2 483 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
2bda0e17
KB
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
b3324be2 492 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
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
b3324be2 501 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
502 atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE);
503}
504
505// Calls that SERVER can make
837e5743 506bool wxDDEConnection::Advise(const wxString& item, wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
507{
508 if (size < 0)
837e5743 509 size = wxStrlen(data);
2bda0e17
KB
510
511 size ++;
512
513 HSZ item_atom = DDEGetAtom(item);
b3324be2
JS
514 HSZ topic_atom = DDEGetAtom(m_topicName);
515 m_sendingData = data;
516 m_dataSize = size;
517 m_dataType = format;
2bda0e17
KB
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 {
837e5743
OK
544 wxChar topic_buf[100];
545 wxChar server_buf[100];
546 DdeQueryString(DDEIdInst, hsz1, (LPTSTR)topic_buf, WXSIZEOF(topic_buf),
2bda0e17 547 CP_WINANSI);
837e5743 548 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)server_buf, WXSIZEOF(topic_buf),
2bda0e17
KB
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 {
b3324be2 557 connection->m_server = server;
2bda0e17 558 server->GetConnections().Append(connection);
b3324be2
JS
559 connection->m_hConv = 0;
560 connection->m_topicName = topic_buf;
2bda0e17
KB
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 {
b3324be2 573 DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
2bda0e17
KB
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 {
b3324be2 599 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 600 DdeFreeDataHandle(hData);
0d2a2b60 601 if (connection->OnExecute(connection->m_topicName, connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
2bda0e17
KB
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 {
837e5743
OK
615 wxChar item_name[200];
616 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
617 CP_WINANSI);
618
619 int user_size = -1;
0d2a2b60 620 char *data = connection->OnRequest(connection->m_topicName, wxString(item_name), &user_size, (wxIPCFormat) wFmt);
2bda0e17
KB
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 {
837e5743
OK
639 wxChar item_name[200];
640 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17 641 CP_WINANSI);
b3324be2 642 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 643 DdeFreeDataHandle(hData);
0d2a2b60 644 connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
2bda0e17
KB
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 {
837e5743
OK
656 wxChar item_name[200];
657 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
658 CP_WINANSI);
659
b3324be2 660 return (DDERETURN)connection->OnStartAdvise(connection->m_topicName, wxString(item_name));
2bda0e17
KB
661 } else return (DDERETURN)0;
662 break;
663 }
664
665 case XTYP_ADVSTOP:
666 {
667 wxDDEConnection *connection = DDEFindConnection(hConv);
668
669 if (connection)
670 {
837e5743
OK
671 wxChar item_name[200];
672 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17 673 CP_WINANSI);
b3324be2 674 return (DDERETURN)connection->OnStopAdvise(connection->m_topicName, wxString(item_name));
2bda0e17
KB
675 } else return (DDERETURN)0;
676 break;
677 }
678
679 case XTYP_ADVREQ:
680 {
681 wxDDEConnection *connection = DDEFindConnection(hConv);
682
b3324be2 683 if (connection && connection->m_sendingData)
2bda0e17
KB
684 {
685 HDDEDATA data = DdeCreateDataHandle(DDEIdInst,
b3324be2
JS
686 (LPBYTE)connection->m_sendingData,
687 connection->m_dataSize, 0, hsz2, connection->m_dataType, 0);
688 connection->m_sendingData = NULL;
2bda0e17
KB
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 {
837e5743
OK
700 wxChar item_name[200];
701 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
702 CP_WINANSI);
703
b3324be2 704 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 705 DdeFreeDataHandle(hData);
0d2a2b60 706 if (connection->OnAdvise(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
2bda0e17
KB
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{
837e5743 720 HSZ atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST string, CP_WINANSI);
2bda0e17
KB
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{
837e5743 739 wxChar *err = NULL;
2bda0e17
KB
740 switch (DdeGetLastError(DDEIdInst))
741 {
742 case DMLERR_ADVACKTIMEOUT:
837e5743 743 err = _T("A request for a synchronous advise transaction has timed out.");
2bda0e17
KB
744 break;
745 case DMLERR_BUSY:
837e5743 746 err = _T("The response to the transaction caused the DDE_FBUSY bit to be set.");
2bda0e17
KB
747 break;
748 case DMLERR_DATAACKTIMEOUT:
837e5743 749 err = _T("A request for a synchronous data transaction has timed out.");
2bda0e17
KB
750 break;
751 case DMLERR_DLL_NOT_INITIALIZED:
837e5743 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.");
2bda0e17
KB
753 break;
754 case DMLERR_DLL_USAGE:
837e5743 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.");
2bda0e17
KB
756 break;
757 case DMLERR_EXECACKTIMEOUT:
837e5743 758 err = _T("A request for a synchronous execute transaction has timed out.");
2bda0e17
KB
759 break;
760 case DMLERR_INVALIDPARAMETER:
837e5743 761 err = _T("A parameter failed to be validated by the DDEML.");
2bda0e17
KB
762 break;
763 case DMLERR_LOW_MEMORY:
837e5743 764 err = _T("A DDEML application has created a prolonged race condition.");
2bda0e17
KB
765 break;
766 case DMLERR_MEMORY_ERROR:
837e5743 767 err = _T("A memory allocation failed.");
2bda0e17
KB
768 break;
769 case DMLERR_NO_CONV_ESTABLISHED:
837e5743 770 err = _T("A client's attempt to establish a conversation has failed.");
2bda0e17
KB
771 break;
772 case DMLERR_NOTPROCESSED:
837e5743 773 err = _T("A transaction failed.");
2bda0e17
KB
774 break;
775 case DMLERR_POKEACKTIMEOUT:
837e5743 776 err = _T("A request for a synchronous poke transaction has timed out.");
2bda0e17
KB
777 break;
778 case DMLERR_POSTMSG_FAILED:
837e5743 779 err = _T("An internal call to the PostMessage function has failed. ");
2bda0e17
KB
780 break;
781 case DMLERR_REENTRANCY:
837e5743 782 err = _T("Reentrancy problem.");
2bda0e17
KB
783 break;
784 case DMLERR_SERVER_DIED:
837e5743 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.");
2bda0e17
KB
786 break;
787 case DMLERR_SYS_ERROR:
837e5743 788 err = _T("An internal error has occurred in the DDEML.");
2bda0e17
KB
789 break;
790 case DMLERR_UNADVACKTIMEOUT:
837e5743 791 err = _T("A request to end an advise transaction has timed out.");
2bda0e17
KB
792 break;
793 case DMLERR_UNFOUND_QUEUE_ID:
837e5743 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.");
2bda0e17
KB
795 break;
796 default:
837e5743 797 err = _T("Unrecognised error type.");
2bda0e17
KB
798 break;
799 }
837e5743 800 MessageBox((HWND) NULL, (LPCTSTR)err, _T("DDE Error"), MB_OK | MB_ICONINFORMATION);
2bda0e17
KB
801}
802
803#endif
47d67540 804 // wxUSE_IPC