]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dde.cpp
value of wxTE_PASSWORD changed to be different from wxCANCEL
[wxWidgets.git] / src / msw / dde.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
5bd3a2da 2// Name: msw/dde.cpp
2bda0e17
KB
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
5bd3a2da 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
5bd3a2da
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
5bd3a2da 21 #pragma implementation "dde.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
5bd3a2da 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
47d67540 31#if wxUSE_IPC
2bda0e17
KB
32
33#ifndef WX_PRECOMP
5bd3a2da
VZ
34 #include "wx/utils.h"
35 #include "wx/app.h"
2bda0e17
KB
36#endif
37
e2a6f233 38#include "wx/module.h"
2bda0e17 39#include "wx/dde.h"
56880523
BJ
40#include "wx/intl.h"
41
2bda0e17 42
03ab016d 43#include "wx/msw/private.h"
5bd3a2da
VZ
44
45#include <string.h>
03ab016d
JS
46#include <windows.h>
47#include <ddeml.h>
48
5bd3a2da
VZ
49#if defined(__TWIN32__) || defined(__GNUWIN32_OLD__)
50 #include "wx/msw/gnuwin32/extra.h"
65fd5cb0 51#endif
2bda0e17 52
5bd3a2da
VZ
53// ----------------------------------------------------------------------------
54// macros and constants
55// ----------------------------------------------------------------------------
2bda0e17
KB
56
57#ifdef __WIN32__
5bd3a2da 58 #define _EXPORT
2bda0e17 59#else
5bd3a2da 60 #define _EXPORT _export
2bda0e17
KB
61#endif
62
5bd3a2da
VZ
63#if wxUSE_UNICODE
64 #define DDE_CP CP_WINUNICODE
65#else
66 #define DDE_CP CP_WINANSI
67#endif
68
69#define GetHConv() ((HCONV)m_hConv)
70
71// default timeout for DDE operations (5sec)
72#define DDE_TIMEOUT 5000
73
74// ----------------------------------------------------------------------------
75// private functions
76// ----------------------------------------------------------------------------
2bda0e17
KB
77
78static wxDDEConnection *DDEFindConnection(HCONV hConv);
79static void DDEDeleteConnection(HCONV hConv);
80static wxDDEServer *DDEFindServer(const wxString& s);
81
5bd3a2da
VZ
82extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(WORD wType,
83 WORD wFmt,
84 HCONV hConv,
85 HSZ hsz1,
86 HSZ hsz2,
87 HDDEDATA hData,
88 DWORD lData1,
89 DWORD lData2);
2bda0e17
KB
90
91// Add topic name to atom table before using in conversations
92static HSZ DDEAddAtom(const wxString& string);
93static HSZ DDEGetAtom(const wxString& string);
5bd3a2da
VZ
94
95// string handles
96static HSZ DDEAtomFromString(const wxString& s);
97static wxString DDEStringFromAtom(HSZ hsz);
98
99// error handling
100static wxString DDEGetErrorMsg(UINT error);
101static void DDELogError(const wxString& s, UINT error = DMLERR_NO_ERROR);
102
103// ----------------------------------------------------------------------------
104// global variables
105// ----------------------------------------------------------------------------
2bda0e17
KB
106
107static DWORD DDEIdInst = 0L;
108static wxDDEConnection *DDECurrentlyConnecting = NULL;
109
110static wxList wxAtomTable(wxKEY_STRING);
111static wxList wxDDEClientObjects;
112static wxList wxDDEServerObjects;
113
114char *DDEDefaultIPCBuffer = NULL;
115int DDEDefaultIPCBufferSize = 0;
5bd3a2da 116static bool DDEInitialized = FALSE;
2bda0e17 117
5bd3a2da
VZ
118// ----------------------------------------------------------------------------
119// private classes
120// ----------------------------------------------------------------------------
2bda0e17 121
5bd3a2da
VZ
122// A module to allow DDE cleanup without calling these functions
123// from app.cpp or from the user's application.
2bda0e17 124
5bd3a2da 125class wxDDEModule : public wxModule
2bda0e17 126{
5bd3a2da
VZ
127public:
128 wxDDEModule() {}
129 bool OnInit() { return TRUE; }
130 void OnExit() { wxDDECleanUp(); }
2bda0e17 131
5bd3a2da
VZ
132private:
133 DECLARE_DYNAMIC_CLASS(wxDDEModule)
134};
2bda0e17 135
5bd3a2da
VZ
136// ----------------------------------------------------------------------------
137// wxWin macros
138// ----------------------------------------------------------------------------
2bda0e17 139
5bd3a2da
VZ
140IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
141IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
142IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
143IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
144
145// ============================================================================
146// implementation
147// ============================================================================
148
149// ----------------------------------------------------------------------------
150// initialization and cleanup
151// ----------------------------------------------------------------------------
152
153extern void wxDDEInitialize()
2bda0e17 154{
5bd3a2da
VZ
155 if ( !DDEInitialized )
156 {
157 // Should insert filter flags
158 PFNCALLBACK callback = (PFNCALLBACK)
159 MakeProcInstance((FARPROC)_DDECallback, wxGetInstance());
160 UINT rc = DdeInitialize(&DDEIdInst, callback, APPCLASS_STANDARD, 0L);
161 if ( rc != DMLERR_NO_ERROR )
162 {
163 DDELogError(_T("Failed to initialize DDE"), rc);
164 }
165 else
166 {
167 DDEInitialized = TRUE;
168 }
169 }
2bda0e17
KB
170}
171
5bd3a2da 172void wxDDECleanUp()
e2a6f233 173{
5bd3a2da
VZ
174 if ( DDEIdInst != 0 )
175 {
176 DdeUninitialize(DDEIdInst);
177 DDEIdInst = 0;
178 }
e2a6f233 179
5bd3a2da
VZ
180 delete [] DDEDefaultIPCBuffer;
181}
182
183// ----------------------------------------------------------------------------
184// functions working with the global connection list(s)
185// ----------------------------------------------------------------------------
e2a6f233 186
2bda0e17
KB
187// Global find connection
188static wxDDEConnection *DDEFindConnection(HCONV hConv)
189{
190 wxNode *node = wxDDEServerObjects.First();
191 wxDDEConnection *found = NULL;
192 while (node && !found)
193 {
194 wxDDEServer *object = (wxDDEServer *)node->Data();
195 found = object->FindConnection((WXHCONV) hConv);
196 node = node->Next();
197 }
198 if (found)
5bd3a2da 199 return found;
2bda0e17
KB
200
201 node = wxDDEClientObjects.First();
202 while (node && !found)
203 {
204 wxDDEClient *object = (wxDDEClient *)node->Data();
205 found = object->FindConnection((WXHCONV) hConv);
206 node = node->Next();
207 }
208 return found;
209}
210
211// Global delete connection
212static void DDEDeleteConnection(HCONV hConv)
213{
214 wxNode *node = wxDDEServerObjects.First();
215 bool found = FALSE;
216 while (node && !found)
217 {
218 wxDDEServer *object = (wxDDEServer *)node->Data();
219 found = object->DeleteConnection((WXHCONV) hConv);
220 node = node->Next();
221 }
222 if (found)
5bd3a2da 223 return;
2bda0e17 224
0d7ea902 225 node = wxDDEClientObjects.First();
2bda0e17
KB
226 while (node && !found)
227 {
228 wxDDEClient *object = (wxDDEClient *)node->Data();
229 found = object->DeleteConnection((WXHCONV) hConv);
230 node = node->Next();
231 }
232}
233
234// Find a server from a service name
235static wxDDEServer *DDEFindServer(const wxString& s)
236{
237 wxNode *node = wxDDEServerObjects.First();
238 wxDDEServer *found = NULL;
239 while (node && !found)
240 {
241 wxDDEServer *object = (wxDDEServer *)node->Data();
5bd3a2da 242
2bda0e17
KB
243 if (object->GetServiceName() == s)
244 found = object;
245 else node = node->Next();
246 }
247 return found;
248}
249
5bd3a2da
VZ
250// ----------------------------------------------------------------------------
251// wxDDEServer
252// ----------------------------------------------------------------------------
2bda0e17 253
5bd3a2da 254wxDDEServer::wxDDEServer()
2bda0e17 255{
5bd3a2da
VZ
256 wxDDEInitialize();
257
258 wxDDEServerObjects.Append(this);
2bda0e17
KB
259}
260
5bd3a2da 261bool wxDDEServer::Create(const wxString& server)
2bda0e17 262{
5bd3a2da 263 m_serviceName = server;
2bda0e17 264
5bd3a2da
VZ
265 if ( !DdeNameService(DDEIdInst, DDEAtomFromString(server), (HSZ)NULL, DNS_REGISTER) )
266 {
267 DDELogError(wxString::Format(_("Failed to register DDE server '%s'"),
268 server.c_str()));
269
270 return FALSE;
271 }
272
273 return TRUE;
2bda0e17
KB
274}
275
5bd3a2da 276wxDDEServer::~wxDDEServer()
2bda0e17 277{
5bd3a2da 278 if ( !!m_serviceName )
2bda0e17 279 {
5bd3a2da
VZ
280 if ( !DdeNameService(DDEIdInst, DDEAtomFromString(m_serviceName),
281 (HSZ)NULL, DNS_UNREGISTER) )
282 {
283 DDELogError(wxString::Format(_("Failed to unregister DDE server '%s'"),
284 m_serviceName.c_str()));
285 }
2bda0e17 286 }
2bda0e17 287
5bd3a2da 288 wxDDEServerObjects.DeleteObject(this);
2bda0e17 289
5bd3a2da
VZ
290 wxNode *node = m_connections.First();
291 while (node)
292 {
293 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
294 wxNode *next = node->Next();
295 connection->OnDisconnect(); // May delete the node implicitly
296 node = next;
297 }
298
299 // If any left after this, delete them
300 node = m_connections.First();
301 while (node)
302 {
303 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
304 wxNode *next = node->Next();
305 delete connection;
306 node = next;
307 }
2bda0e17
KB
308}
309
310wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */)
311{
5bd3a2da 312 return new wxDDEConnection;
2bda0e17
KB
313}
314
315wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv)
316{
5bd3a2da
VZ
317 wxNode *node = m_connections.First();
318 wxDDEConnection *found = NULL;
319 while (node && !found)
320 {
321 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
322 if (connection->m_hConv == conv)
323 found = connection;
324 else node = node->Next();
325 }
326 return found;
2bda0e17
KB
327}
328
329// Only delete the entry in the map, not the actual connection
330bool wxDDEServer::DeleteConnection(WXHCONV conv)
331{
5bd3a2da
VZ
332 wxNode *node = m_connections.First();
333 bool found = FALSE;
334 while (node && !found)
2bda0e17 335 {
5bd3a2da
VZ
336 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
337 if (connection->m_hConv == conv)
338 {
339 found = TRUE;
340 delete node;
341 }
342 else node = node->Next();
2bda0e17 343 }
5bd3a2da 344 return found;
2bda0e17
KB
345}
346
5bd3a2da
VZ
347// ----------------------------------------------------------------------------
348// wxDDEClient
349// ----------------------------------------------------------------------------
2bda0e17 350
5bd3a2da 351wxDDEClient::wxDDEClient()
2bda0e17 352{
5bd3a2da
VZ
353 wxDDEInitialize();
354
355 wxDDEClientObjects.Append(this);
2bda0e17
KB
356}
357
5bd3a2da 358wxDDEClient::~wxDDEClient()
2bda0e17 359{
5bd3a2da
VZ
360 wxDDEClientObjects.DeleteObject(this);
361 wxNode *node = m_connections.First();
362 while (node)
363 {
364 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
365 delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
366 node = m_connections.First();
367 }
2bda0e17
KB
368}
369
370bool wxDDEClient::ValidHost(const wxString& /* host */)
371{
5bd3a2da 372 return TRUE;
2bda0e17
KB
373}
374
5bd3a2da
VZ
375wxConnectionBase *wxDDEClient::MakeConnection(const wxString& WXUNUSED(host),
376 const wxString& server,
377 const wxString& topic)
2bda0e17 378{
5bd3a2da
VZ
379 HCONV hConv = DdeConnect(DDEIdInst, DDEAtomFromString(server), DDEAtomFromString(topic),
380 (PCONVCONTEXT)NULL);
381 if ( !hConv )
2bda0e17 382 {
5bd3a2da
VZ
383 DDELogError(wxString::Format(_("Failed to create connection to "
384 "server '%s' on topic '%s'"),
385 server.c_str(), topic.c_str()));
2bda0e17 386 }
5bd3a2da
VZ
387 else
388 {
389 wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
390 if (connection)
391 {
392 connection->m_hConv = (WXHCONV) hConv;
393 connection->m_topicName = topic;
394 connection->m_client = this;
395 m_connections.Append(connection);
396 return connection;
397 }
398 }
399
400 return (wxConnectionBase*) NULL;
2bda0e17
KB
401}
402
5bd3a2da 403wxConnectionBase *wxDDEClient::OnMakeConnection()
2bda0e17 404{
5bd3a2da 405 return new wxDDEConnection;
2bda0e17
KB
406}
407
408wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv)
409{
5bd3a2da
VZ
410 wxNode *node = m_connections.First();
411 wxDDEConnection *found = NULL;
412 while (node && !found)
413 {
414 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
415 if (connection->m_hConv == conv)
416 found = connection;
417 else node = node->Next();
418 }
419 return found;
2bda0e17
KB
420}
421
422// Only delete the entry in the map, not the actual connection
423bool wxDDEClient::DeleteConnection(WXHCONV conv)
424{
5bd3a2da
VZ
425 wxNode *node = m_connections.First();
426 bool found = FALSE;
427 while (node && !found)
2bda0e17 428 {
5bd3a2da
VZ
429 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
430 if (connection->m_hConv == conv)
431 {
432 found = TRUE;
433 delete node;
434 }
435 else node = node->Next();
2bda0e17 436 }
5bd3a2da 437 return found;
2bda0e17
KB
438}
439
5bd3a2da
VZ
440// ----------------------------------------------------------------------------
441// wxDDEConnection
442// ----------------------------------------------------------------------------
2bda0e17
KB
443
444wxDDEConnection::wxDDEConnection(char *buffer, int size)
445{
5bd3a2da
VZ
446 if (buffer == NULL)
447 {
448 if (DDEDefaultIPCBuffer == NULL)
449 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
450 m_bufPtr = DDEDefaultIPCBuffer;
451 m_bufSize = DDEDefaultIPCBufferSize;
452 }
453 else
454 {
455 m_bufPtr = buffer;
456 m_bufSize = size;
457 }
2bda0e17 458
5bd3a2da
VZ
459 m_client = NULL;
460 m_server = NULL;
2bda0e17 461
5bd3a2da
VZ
462 m_hConv = 0;
463 m_sendingData = NULL;
2bda0e17
KB
464}
465
5bd3a2da 466wxDDEConnection::wxDDEConnection()
2bda0e17 467{
5bd3a2da
VZ
468 m_hConv = 0;
469 m_sendingData = NULL;
470 m_server = NULL;
471 m_client = NULL;
472 if (DDEDefaultIPCBuffer == NULL)
473 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
2bda0e17 474
5bd3a2da
VZ
475 m_bufPtr = DDEDefaultIPCBuffer;
476 m_bufSize = DDEDefaultIPCBufferSize;
2bda0e17
KB
477}
478
5bd3a2da 479wxDDEConnection::~wxDDEConnection()
2bda0e17 480{
5bd3a2da
VZ
481 if (m_server)
482 m_server->GetConnections().DeleteObject(this);
483 else
484 m_client->GetConnections().DeleteObject(this);
2bda0e17
KB
485}
486
487// Calls that CLIENT can make
5bd3a2da 488bool wxDDEConnection::Disconnect()
2bda0e17 489{
5bd3a2da
VZ
490 DDEDeleteConnection(GetHConv());
491
492 bool ok = DdeDisconnect(GetHConv()) != 0;
493 if ( !ok )
494 {
495 DDELogError(_T("Failed to disconnect from DDE server gracefully"));
496 }
497
498 return ok;
2bda0e17
KB
499}
500
73974df1 501bool wxDDEConnection::Execute(const wxChar *data, int size, wxIPCFormat format)
2bda0e17 502{
5bd3a2da
VZ
503 DWORD result;
504 if (size < 0)
505 {
506 size = wxStrlen(data) + 1;
507 }
2bda0e17 508
5bd3a2da
VZ
509 bool ok = DdeClientTransaction((LPBYTE)data, size,
510 GetHConv(),
511 NULL,
512 format,
513 XTYP_EXECUTE,
514 DDE_TIMEOUT,
515 &result) != 0;
516 if ( !ok )
517 {
518 DDELogError(_T("DDE execute request failed"));
519 }
2bda0e17 520
5bd3a2da 521 return ok;
2bda0e17
KB
522}
523
0d2a2b60 524char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
2bda0e17 525{
5bd3a2da
VZ
526 DWORD result;
527 HSZ atom = DDEGetAtom(item);
528
529 HDDEDATA returned_data = DdeClientTransaction(NULL, 0,
530 GetHConv(),
531 atom, format,
532 XTYP_REQUEST,
533 DDE_TIMEOUT,
534 &result);
535 if ( !returned_data )
536 {
537 DDELogError(_T("DDE data request failed"));
538
539 return NULL;
540 }
2bda0e17 541
5bd3a2da 542 DWORD len = DdeGetData(returned_data, (LPBYTE)m_bufPtr, m_bufSize, 0);
2bda0e17 543
5bd3a2da 544 DdeFreeDataHandle(returned_data);
2bda0e17 545
5bd3a2da
VZ
546 if (size)
547 *size = (int)len;
2bda0e17 548
b3324be2 549 return m_bufPtr;
2bda0e17
KB
550}
551
837e5743 552bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
2bda0e17 553{
5bd3a2da
VZ
554 DWORD result;
555 if (size < 0)
556 {
557 size = wxStrlen(data) + 1;
558 }
2bda0e17 559
5bd3a2da
VZ
560 HSZ item_atom = DDEGetAtom(item);
561 bool ok = DdeClientTransaction((LPBYTE)data, size,
562 GetHConv(),
563 item_atom, format,
564 XTYP_POKE,
565 DDE_TIMEOUT,
566 &result) != 0;
567 if ( !ok )
568 {
569 DDELogError(_("DDE poke request failed"));
570 }
2bda0e17 571
5bd3a2da 572 return ok;
2bda0e17
KB
573}
574
575bool wxDDEConnection::StartAdvise(const wxString& item)
576{
5bd3a2da
VZ
577 DWORD result;
578 HSZ atom = DDEGetAtom(item);
2bda0e17 579
5bd3a2da
VZ
580 bool ok = DdeClientTransaction(NULL, 0,
581 GetHConv(),
582 atom, CF_TEXT,
583 XTYP_ADVSTART,
584 DDE_TIMEOUT,
585 &result) != 0;
586 if ( !ok )
587 {
588 DDELogError(_("Failed to establish an advise loop with DDE server"));
589 }
590
591 return ok;
2bda0e17
KB
592}
593
594bool wxDDEConnection::StopAdvise(const wxString& item)
595{
5bd3a2da
VZ
596 DWORD result;
597 HSZ atom = DDEGetAtom(item);
2bda0e17 598
5bd3a2da
VZ
599 bool ok = DdeClientTransaction(NULL, 0,
600 GetHConv(),
601 atom, CF_TEXT,
602 XTYP_ADVSTOP,
603 DDE_TIMEOUT,
604 &result) != 0;
605 if ( !ok )
606 {
607 DDELogError(_("Failed to terminate the advise loop with DDE server"));
608 }
609
610 return ok;
2bda0e17
KB
611}
612
613// Calls that SERVER can make
5bd3a2da
VZ
614bool wxDDEConnection::Advise(const wxString& item,
615 wxChar *data,
616 int size,
617 wxIPCFormat format)
2bda0e17 618{
5bd3a2da
VZ
619 if (size < 0)
620 {
621 size = wxStrlen(data) + 1;
622 }
2bda0e17 623
5bd3a2da
VZ
624 HSZ item_atom = DDEGetAtom(item);
625 HSZ topic_atom = DDEGetAtom(m_topicName);
626 m_sendingData = data;
627 m_dataSize = size;
628 m_dataType = format;
2bda0e17 629
5bd3a2da
VZ
630 bool ok = DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0;
631 if ( !ok )
632 {
633 DDELogError(_("Failed to send DDE advise notification"));
634 }
635
636 return ok;
2bda0e17
KB
637}
638
5bd3a2da 639bool wxDDEConnection::OnDisconnect()
2bda0e17 640{
5bd3a2da
VZ
641 delete this;
642 return TRUE;
2bda0e17
KB
643}
644
5bd3a2da
VZ
645// ----------------------------------------------------------------------------
646// _DDECallback
647// ----------------------------------------------------------------------------
2bda0e17
KB
648
649#define DDERETURN HDDEDATA
650
5bd3a2da
VZ
651HDDEDATA EXPENTRY _EXPORT
652_DDECallback(WORD wType,
653 WORD wFmt,
654 HCONV hConv,
655 HSZ hsz1,
656 HSZ hsz2,
657 HDDEDATA hData,
658 DWORD WXUNUSED(lData1),
659 DWORD WXUNUSED(lData2))
660{
661 switch (wType)
2bda0e17 662 {
5bd3a2da
VZ
663 case XTYP_CONNECT:
664 {
665 wxString topic = DDEStringFromAtom(hsz1),
666 srv = DDEStringFromAtom(hsz2);
667 wxDDEServer *server = DDEFindServer(srv);
668 if (server)
669 {
670 wxDDEConnection *connection =
671 (wxDDEConnection*) server->OnAcceptConnection(topic);
672 if (connection)
673 {
674 connection->m_server = server;
675 server->GetConnections().Append(connection);
676 connection->m_hConv = 0;
677 connection->m_topicName = topic;
678 DDECurrentlyConnecting = connection;
679 return (DDERETURN)(DWORD)TRUE;
680 }
681 }
682 break;
683 }
684
685 case XTYP_CONNECT_CONFIRM:
686 {
687 if (DDECurrentlyConnecting)
688 {
689 DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
690 DDECurrentlyConnecting = NULL;
691 return (DDERETURN)(DWORD)TRUE;
692 }
693 break;
694 }
695
696 case XTYP_DISCONNECT:
697 {
698 wxDDEConnection *connection = DDEFindConnection(hConv);
699 if (connection && connection->OnDisconnect())
700 {
701 DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
702 return (DDERETURN)(DWORD)TRUE;
703 }
704 break;
705 }
706
707 case XTYP_EXECUTE:
708 {
709 wxDDEConnection *connection = DDEFindConnection(hConv);
710
711 if (connection)
712 {
713 DWORD len = DdeGetData(hData,
714 (LPBYTE)connection->m_bufPtr,
715 connection->m_bufSize,
716 0);
717 DdeFreeDataHandle(hData);
718 if ( connection->OnExecute(connection->m_topicName,
719 connection->m_bufPtr,
720 (int)len,
721 (wxIPCFormat) wFmt) )
722 {
723 return (DDERETURN)(DWORD)DDE_FACK;
724 }
725 }
726
727 return (DDERETURN)DDE_FNOTPROCESSED;
728 }
729
730 case XTYP_REQUEST:
731 {
732 wxDDEConnection *connection = DDEFindConnection(hConv);
733
734 if (connection)
735 {
736 wxString item_name = DDEStringFromAtom(hsz2);
737
738 int user_size = -1;
739 char *data = connection->OnRequest(connection->m_topicName,
740 item_name,
741 &user_size,
742 (wxIPCFormat) wFmt);
743 if (data)
744 {
745 if (user_size < 0)
746 user_size = wxStrlen(data) + 1;
747
748 HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
749 (LPBYTE)data,
750 user_size,
751 0,
752 hsz2,
753 wFmt,
754 0);
755 return (DDERETURN)handle;
756 }
757 }
758 break;
759 }
760
761 case XTYP_POKE:
762 {
763 wxDDEConnection *connection = DDEFindConnection(hConv);
764
765 if (connection)
766 {
767 wxString item_name = DDEStringFromAtom(hsz2);
768
769 DWORD len = DdeGetData(hData,
770 (LPBYTE)connection->m_bufPtr,
771 connection->m_bufSize,
772 0);
773 DdeFreeDataHandle(hData);
774
775 connection->OnPoke(connection->m_topicName,
776 item_name,
777 connection->m_bufPtr,
778 (int)len,
779 (wxIPCFormat) wFmt);
780
781 return (DDERETURN)DDE_FACK;
782 }
783 else
784 {
785 return (DDERETURN)DDE_FNOTPROCESSED;
786 }
787 }
788
789 case XTYP_ADVSTART:
790 {
791 wxDDEConnection *connection = DDEFindConnection(hConv);
792
793 if (connection)
794 {
795 wxString item_name = DDEStringFromAtom(hsz2);
796
797 return (DDERETURN)connection->
798 OnStartAdvise(connection->m_topicName, item_name);
799 }
800
801 break;
802 }
803
804 case XTYP_ADVSTOP:
805 {
806 wxDDEConnection *connection = DDEFindConnection(hConv);
807
808 if (connection)
809 {
810 wxString item_name = DDEStringFromAtom(hsz2);
811
812 return (DDERETURN)connection->
813 OnStopAdvise(connection->m_topicName, item_name);
814 }
815
816 break;
817 }
818
819 case XTYP_ADVREQ:
820 {
821 wxDDEConnection *connection = DDEFindConnection(hConv);
822
823 if (connection && connection->m_sendingData)
824 {
825 HDDEDATA data = DdeCreateDataHandle
826 (
827 DDEIdInst,
828 (LPBYTE)connection->m_sendingData,
829 connection->m_dataSize,
830 0,
831 hsz2,
832 connection->m_dataType,
833 0
834 );
835
836 connection->m_sendingData = NULL;
837
838 return (DDERETURN)data;
839 }
840
841 break;
842 }
843
844 case XTYP_ADVDATA:
845 {
846 wxDDEConnection *connection = DDEFindConnection(hConv);
847
848 if (connection)
849 {
850 wxString item_name = DDEStringFromAtom(hsz2);
851
852 DWORD len = DdeGetData(hData,
853 (LPBYTE)connection->m_bufPtr,
854 connection->m_bufSize,
855 0);
856 DdeFreeDataHandle(hData);
857 if ( connection->OnAdvise(connection->m_topicName,
858 item_name,
859 connection->m_bufPtr,
860 (int)len,
861 (wxIPCFormat) wFmt) )
862 {
863 return (DDERETURN)(DWORD)DDE_FACK;
864 }
865 }
866
867 return (DDERETURN)DDE_FNOTPROCESSED;
868 }
2bda0e17
KB
869 }
870
5bd3a2da
VZ
871 return (DDERETURN)0;
872}
2bda0e17 873
5bd3a2da
VZ
874// ----------------------------------------------------------------------------
875// DDE strings and atoms
876// ----------------------------------------------------------------------------
2bda0e17 877
5bd3a2da
VZ
878// Atom table stuff
879static HSZ DDEAddAtom(const wxString& string)
880{
881 HSZ atom = DDEAtomFromString(string);
882 wxAtomTable.Append(string, (wxObject *)atom);
883 return atom;
884}
2bda0e17 885
5bd3a2da
VZ
886static HSZ DDEGetAtom(const wxString& string)
887{
888 wxNode *node = wxAtomTable.Find(string);
889 if (node)
890 return (HSZ)node->Data();
891 else
2bda0e17 892 {
5bd3a2da
VZ
893 DDEAddAtom(string);
894 return (HSZ)(wxAtomTable.Find(string)->Data());
2bda0e17 895 }
5bd3a2da 896}
2bda0e17 897
5bd3a2da
VZ
898// atom <-> strings
899static HSZ DDEAtomFromString(const wxString& s)
900{
901 wxASSERT_MSG( DDEIdInst, _T("DDE not initialized") );
902
56880523 903 HSZ hsz = DdeCreateStringHandle(DDEIdInst, (char*) s.c_str(), DDE_CP);
5bd3a2da 904 if ( !hsz )
2bda0e17 905 {
5bd3a2da 906 DDELogError(_("Failed to create DDE string"));
2bda0e17
KB
907 }
908
5bd3a2da
VZ
909 return hsz;
910}
2bda0e17 911
5bd3a2da
VZ
912static wxString DDEStringFromAtom(HSZ hsz)
913{
914 // all DDE strings are normally limited to 255 bytes
915 static const size_t len = 256;
2bda0e17 916
5bd3a2da
VZ
917 wxString s;
918 (void)DdeQueryString(DDEIdInst, hsz, s.GetWriteBuf(len), len, DDE_CP);
919 s.UngetWriteBuf();
2bda0e17 920
5bd3a2da
VZ
921 return s;
922}
2bda0e17 923
5bd3a2da
VZ
924// ----------------------------------------------------------------------------
925// error handling
926// ----------------------------------------------------------------------------
2bda0e17 927
5bd3a2da
VZ
928static void DDELogError(const wxString& s, UINT error)
929{
930 if ( !error )
2bda0e17 931 {
5bd3a2da 932 error = DdeGetLastError(DDEIdInst);
2bda0e17 933 }
2bda0e17 934
5bd3a2da 935 wxLogError(s + _T(": ") + DDEGetErrorMsg(error));
2bda0e17
KB
936}
937
5bd3a2da 938static wxString DDEGetErrorMsg(UINT error)
2bda0e17 939{
5bd3a2da
VZ
940 wxString err;
941 switch ( error )
942 {
943 case DMLERR_NO_ERROR:
944 err = _("no DDE error.");
945 break;
946
947 case DMLERR_ADVACKTIMEOUT:
948 err = _("a request for a synchronous advise transaction has timed out.");
949 break;
950 case DMLERR_BUSY:
951 err = _("the response to the transaction caused the DDE_FBUSY bit to be set.");
952 break;
953 case DMLERR_DATAACKTIMEOUT:
954 err = _("a request for a synchronous data transaction has timed out.");
955 break;
956 case DMLERR_DLL_NOT_INITIALIZED:
957 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.");
958 break;
959 case DMLERR_DLL_USAGE:
960 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.");
961 break;
962 case DMLERR_EXECACKTIMEOUT:
963 err = _("a request for a synchronous execute transaction has timed out.");
964 break;
965 case DMLERR_INVALIDPARAMETER:
966 err = _("a parameter failed to be validated by the DDEML.");
967 break;
968 case DMLERR_LOW_MEMORY:
969 err = _("a DDEML application has created a prolonged race condition.");
970 break;
971 case DMLERR_MEMORY_ERROR:
972 err = _("a memory allocation failed.");
973 break;
974 case DMLERR_NO_CONV_ESTABLISHED:
975 err = _("a client's attempt to establish a conversation has failed.");
976 break;
977 case DMLERR_NOTPROCESSED:
978 err = _("a transaction failed.");
979 break;
980 case DMLERR_POKEACKTIMEOUT:
981 err = _("a request for a synchronous poke transaction has timed out.");
982 break;
983 case DMLERR_POSTMSG_FAILED:
984 err = _("an internal call to the PostMessage function has failed. ");
985 break;
986 case DMLERR_REENTRANCY:
987 err = _("reentrancy problem.");
988 break;
989 case DMLERR_SERVER_DIED:
990 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.");
991 break;
992 case DMLERR_SYS_ERROR:
993 err = _("an internal error has occurred in the DDEML.");
994 break;
995 case DMLERR_UNADVACKTIMEOUT:
996 err = _("a request to end an advise transaction has timed out.");
997 break;
998 case DMLERR_UNFOUND_QUEUE_ID:
999 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.");
1000 break;
1001 default:
1002 err.Printf(_("Unknown DDE error %08x"), error);
1003 }
2bda0e17 1004
5bd3a2da 1005 return err;
2bda0e17
KB
1006}
1007
1008#endif
47d67540 1009 // wxUSE_IPC