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