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