ReactOS 0.4.17-dev-1321-g5c122a9
ddeclient.c
Go to the documentation of this file.
1/*
2 * DDEML library
3 *
4 * Copyright 1997 Alexandre Julliard
5 * Copyright 1997 Len White
6 * Copyright 1999 Keith Matthews
7 * Copyright 2000 Corel
8 * Copyright 2001 Eric Pouech
9 * Copyright 2004, 2005 Dmitry Timoshkov
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <user32.h>
27
29
30static LRESULT CALLBACK WDML_ClientProc(HWND, UINT, WPARAM, LPARAM); /* only for one client, not conv list */
31#ifdef __REACTOS__
32const char WDML_szClientConvClassA[] = "DDEMLAnsiClient";
33const WCHAR WDML_szClientConvClassW[] = L"DDEMLUnicodeClient";
34#else
35const char WDML_szClientConvClassA[] = "WineDdeClientA";
36const WCHAR WDML_szClientConvClassW[] = L"WineDdeClientW";
37#endif
38
39/******************************************************************************
40 * DdeConnectList [USER32.@] Establishes conversation with DDE servers
41 *
42 * PARAMS
43 * idInst [I] Instance identifier
44 * hszService [I] Handle to service name string
45 * hszTopic [I] Handle to topic name string
46 * hConvList [I] Handle to conversation list
47 * pCC [I] Pointer to structure with context data
48 *
49 * RETURNS
50 * Success: Handle to new conversation list
51 * Failure: 0
52 */
53HCONVLIST WINAPI DdeConnectList(DWORD idInst, HSZ hszService, HSZ hszTopic,
54 HCONVLIST hConvList, PCONVCONTEXT pCC)
55{
56 FIXME("(%ld,%p,%p,%p,%p): stub\n", idInst, hszService, hszTopic, hConvList, pCC);
57 return (HCONVLIST)1;
58}
59
60/*****************************************************************
61 * DdeQueryNextServer [USER32.@]
62 */
63HCONV WINAPI DdeQueryNextServer(HCONVLIST hConvList, HCONV hConvPrev)
64{
65 FIXME("(%p,%p): stub\n", hConvList, hConvPrev);
66 return 0;
67}
68
69/******************************************************************************
70 * DdeDisconnectList [USER32.@] Destroys list and terminates conversations
71 *
72 *
73 * PARAMS
74 * hConvList [I] Handle to conversation list
75 *
76 * RETURNS
77 * Success: TRUE
78 * Failure: FALSE
79 */
80BOOL WINAPI DdeDisconnectList(HCONVLIST hConvList)
81{
82 FIXME("(%p): stub\n", hConvList);
83 return TRUE;
84}
85
86/*****************************************************************
87 * DdeConnect (USER32.@)
88 */
89HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
90 PCONVCONTEXT pCC)
91{
92 HWND hwndClient;
94 WDML_CONV* pConv;
95 ATOM aSrv = 0, aTpc = 0;
96
97 TRACE("(0x%lx,%p,%p,%p)\n", idInst, hszService, hszTopic, pCC);
98
100 if (!pInstance)
101 return NULL;
102
103 /* make sure this conv is never created */
104 pConv = WDML_FindConv(pInstance, WDML_CLIENT_SIDE, hszService, hszTopic);
105 if (pConv != NULL)
106 {
107 ERR("This Conv already exists: (%p)\n", pConv);
108 return NULL;
109 }
110
111 /* we need to establish a conversation with
112 server, so create a window for it */
113
114 if (pInstance->unicode)
115 {
116 WNDCLASSEXW wndclass;
117
118 wndclass.cbSize = sizeof(wndclass);
119 wndclass.style = 0;
120 wndclass.lpfnWndProc = WDML_ClientProc;
121 wndclass.cbClsExtra = 0;
122 wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR);
123 wndclass.hInstance = 0;
124 wndclass.hIcon = 0;
125 wndclass.hCursor = 0;
126 wndclass.hbrBackground = 0;
127 wndclass.lpszMenuName = NULL;
129 wndclass.hIconSm = 0;
130
131 RegisterClassExW(&wndclass);
132
133 hwndClient = CreateWindowW(WDML_szClientConvClassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
134 }
135 else
136 {
137 WNDCLASSEXA wndclass;
138
139 wndclass.cbSize = sizeof(wndclass);
140 wndclass.style = 0;
141 wndclass.lpfnWndProc = WDML_ClientProc;
142 wndclass.cbClsExtra = 0;
143 wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR);
144 wndclass.hInstance = 0;
145 wndclass.hIcon = 0;
146 wndclass.hCursor = 0;
147 wndclass.hbrBackground = 0;
148 wndclass.lpszMenuName = NULL;
150 wndclass.hIconSm = 0;
151
152 RegisterClassExA(&wndclass);
153
154 hwndClient = CreateWindowA(WDML_szClientConvClassA, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
155 }
156
158
159 if (hszService)
160 {
161 aSrv = WDML_MakeAtomFromHsz(hszService);
162 if (!aSrv) goto theEnd;
163 }
164 if (hszTopic)
165 {
167 if (!aTpc) goto theEnd;
168 }
169
170 /* note: sent messages shall not use packing */
173
174 pInstance = WDML_GetInstance(idInst);
175 if (!pInstance)
176 {
177 goto theEnd;
178 }
179
180 /* At this point, Client WM_DDE_ACK should have saved hwndServer
181 for this instance id and hwndClient if server responds.
182 So get HCONV and return it. And add it to conv list */
183 pConv = WDML_GetConvFromWnd(hwndClient);
184 if (pConv == NULL || pConv->hwndServer == 0)
185 {
186 WARN("Done with INITIATE, but no Server window available\n");
187 pConv = NULL;
189 goto theEnd;
190 }
191 TRACE("Connected to Server window (%p)\n", pConv->hwndServer);
192 pConv->wConvst = XST_CONNECTED;
193
194 /* finish init of pConv */
195 if (pCC != NULL)
196 {
197 pConv->convContext = *pCC;
198 }
199 else
200 {
201 memset(&pConv->convContext, 0, sizeof(pConv->convContext));
202 pConv->convContext.cb = sizeof(pConv->convContext);
204 }
205
206 theEnd:
207
208 if (aSrv) GlobalDeleteAtom(aSrv);
209 if (aTpc) GlobalDeleteAtom(aTpc);
210 return (HCONV)pConv;
211}
212
213/*****************************************************************
214 * DdeReconnect (DDEML.37)
215 * DdeReconnect (USER32.@)
216 */
217HCONV WINAPI DdeReconnect(HCONV hConv)
218{
219 WDML_CONV* pConv;
220 WDML_CONV* pNewConv = NULL;
221 ATOM aSrv = 0, aTpc = 0;
222
223 TRACE("(%p)\n", hConv);
224
225 pConv = WDML_GetConv(hConv, FALSE);
226 if (pConv != NULL && (pConv->wStatus & ST_CLIENT))
227 {
228 BOOL ret;
229
230 /* to reestablish a connection, we have to make sure that:
231 * 1/ pConv is the conversation attached to the client window (it wouldn't be
232 * if a call to DdeReconnect would have already been done...)
233 * FIXME: is this really an error ???
234 * 2/ the pConv conversation had really been deconnected
235 */
236 if (pConv == WDML_GetConvFromWnd(pConv->hwndClient) &&
237 (pConv->wStatus & ST_TERMINATED) && !(pConv->wStatus & ST_CONNECTED))
238 {
239 HWND hwndClient = pConv->hwndClient;
240 HWND hwndServer = pConv->hwndServer;
241
243
244 aSrv = WDML_MakeAtomFromHsz(pConv->hszService);
245 aTpc = WDML_MakeAtomFromHsz(pConv->hszTopic);
246 if (!aSrv || !aTpc) goto theEnd;
247
248 /* note: sent messages shall not use packing */
249 ret = SendMessageW(hwndServer, WM_DDE_INITIATE, (WPARAM)hwndClient,
250 MAKELPARAM(aSrv, aTpc));
251
252 pConv = WDML_GetConv(hConv, FALSE);
253 if (pConv == NULL)
254 {
255 FIXME("Should fail reconnection\n");
256 goto theEnd;
257 }
258
259 if (ret && (pNewConv = WDML_GetConvFromWnd(pConv->hwndClient)) != NULL)
260 {
261 /* re-establish all links... */
262 WDML_LINK* pLink;
263
264 for (pLink = pConv->instance->links[WDML_CLIENT_SIDE]; pLink; pLink = pLink->next)
265 {
266 if (pLink->hConv == hConv)
267 {
268 /* try to reestablish the links... */
269 DdeClientTransaction(NULL, 0, (HCONV)pNewConv, pLink->hszItem, pLink->uFmt,
270 pLink->transactionType, 1000, NULL);
271 }
272 }
273 }
274 else
275 {
276 /* reset the conversation as it was */
278 }
279 }
280 }
281
282 theEnd:
283
284 if (aSrv) GlobalDeleteAtom(aSrv);
285 if (aTpc) GlobalDeleteAtom(aTpc);
286 return (HCONV)pNewConv;
287}
288
289/******************************************************************
290 * WDML_ClientQueueAdvise
291 *
292 * Creates and queue an WM_DDE_ADVISE transaction
293 */
294static WDML_XACT* WDML_ClientQueueAdvise(WDML_CONV* pConv, UINT wType, UINT wFmt, HSZ hszItem)
295{
296 DDEADVISE* pDdeAdvise;
297 WDML_XACT* pXAct;
298 ATOM atom;
299
300 TRACE("XTYP_ADVSTART (with%s data) transaction\n", (wType & XTYPF_NODATA) ? "out" : "");
301
302 atom = WDML_MakeAtomFromHsz(hszItem);
303 if (!atom) return NULL;
304
305 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, wFmt, hszItem);
306 if (!pXAct)
307 {
308 GlobalDeleteAtom(atom);
309 return NULL;
310 }
311
312 pXAct->wType = wType & ~0x0F;
313 pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(DDEADVISE));
314 /* FIXME: hMem is unfreed for now... should be deleted in server */
315
316 /* pack DdeAdvise */
317 pDdeAdvise = GlobalLock(pXAct->hMem);
318 pDdeAdvise->fAckReq = (wType & XTYPF_ACKREQ) != 0;
319 pDdeAdvise->fDeferUpd = (wType & XTYPF_NODATA) != 0;
320 pDdeAdvise->cfFormat = wFmt;
321 GlobalUnlock(pXAct->hMem);
322
323 pXAct->lParam = PackDDElParam(WM_DDE_ADVISE, (UINT_PTR)pXAct->hMem, atom);
324
325 return pXAct;
326}
327
328/******************************************************************
329 * WDML_HandleAdviseReply
330 *
331 * handles the reply to an advise request
332 */
334{
335 DDEACK ddeAck;
336 UINT_PTR uiLo, uiHi;
337 HSZ hsz;
338
339 if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
340 {
341 return WDML_QS_PASS;
342 }
343
344 UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
345 hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
346
347 if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
348 return WDML_QS_PASS;
349
350 GlobalDeleteAtom(uiHi);
351 FreeDDElParam(WM_DDE_ACK, msg->lParam);
352
353 if (ack) *ack = uiLo;
354 WDML_ExtractAck(uiLo, &ddeAck);
355
356 if (ddeAck.fAck)
357 {
358 WDML_LINK* pLink;
359
360 /* billx: first to see if the link is already created. */
361 pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
362 pXAct->hszItem, TRUE, pXAct->wFmt);
363 if (pLink != NULL)
364 {
365 /* we found a link, and only need to modify it in case it changes */
366 pLink->transactionType = pXAct->wType;
367 }
368 else
369 {
370 WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
371 pXAct->wType, pXAct->hszItem, pXAct->wFmt);
372 }
373 pXAct->hDdeData = (HDDEDATA)1;
374 }
375 else
376 {
377 TRACE("Returning FALSE on XTYP_ADVSTART - fAck was FALSE\n");
378 GlobalFree(pXAct->hMem);
379 pXAct->hDdeData = NULL;
380 }
381
382 return WDML_QS_HANDLED;
383}
384
385/******************************************************************
386 * WDML_ClientQueueUnadvise
387 *
388 * queues an unadvise transaction
389 */
390static WDML_XACT* WDML_ClientQueueUnadvise(WDML_CONV* pConv, UINT wFmt, HSZ hszItem)
391{
392 WDML_XACT* pXAct;
393 ATOM atom;
394
395 TRACE("XTYP_ADVSTOP transaction\n");
396
397 atom = WDML_MakeAtomFromHsz(hszItem);
398 if (!atom) return NULL;
399
400 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_UNADVISE, wFmt, hszItem);
401 if (!pXAct)
402 {
403 GlobalDeleteAtom(atom);
404 return NULL;
405 }
406
407 /* end advise loop: post WM_DDE_UNADVISE to server to terminate link
408 * on the specified item.
409 */
410 pXAct->lParam = PackDDElParam(WM_DDE_UNADVISE, wFmt, atom);
411 return pXAct;
412}
413
414/******************************************************************
415 * WDML_HandleUnadviseReply
416 *
417 *
418 */
420{
421 DDEACK ddeAck;
422 UINT_PTR uiLo, uiHi;
423 HSZ hsz;
424
425 if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
426 {
427 return WDML_QS_PASS;
428 }
429
430 UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
431 hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
432
433 if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
434 return WDML_QS_PASS;
435
436 FreeDDElParam(WM_DDE_ACK, msg->lParam);
437 GlobalDeleteAtom(uiHi);
438
439 if (ack) *ack = uiLo;
440 WDML_ExtractAck(uiLo, &ddeAck);
441
442 TRACE("WM_DDE_ACK received while waiting for a timeout\n");
443
444 if (!ddeAck.fAck)
445 {
446 TRACE("Returning FALSE on XTYP_ADVSTOP - fAck was FALSE\n");
447 pXAct->hDdeData = NULL;
448 }
449 else
450 {
451 /* billx: remove the link */
452 WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
453 pXAct->hszItem, pXAct->wFmt);
454 pXAct->hDdeData = (HDDEDATA)1;
455 }
456 return WDML_QS_HANDLED;
457}
458
459/******************************************************************
460 * WDML_ClientQueueRequest
461 *
462 *
463 */
464static WDML_XACT* WDML_ClientQueueRequest(WDML_CONV* pConv, UINT wFmt, HSZ hszItem)
465{
466 WDML_XACT* pXAct;
467 ATOM atom;
468
469 TRACE("XTYP_REQUEST transaction\n");
470
471 atom = WDML_MakeAtomFromHsz(hszItem);
472 if (!atom) return NULL;
473
474 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_REQUEST, wFmt, hszItem);
475 if (!pXAct)
476 {
477 GlobalDeleteAtom(atom);
478 return NULL;
479 }
480
481 pXAct->lParam = PackDDElParam(WM_DDE_REQUEST, wFmt, atom);
482
483 return pXAct;
484}
485
486/******************************************************************
487 * WDML_HandleRequestReply
488 *
489 *
490 */
492{
493 DDEACK ddeAck;
494 WINE_DDEHEAD wdh;
495 UINT_PTR uiLo, uiHi;
496 HSZ hsz;
497
498 if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
499 return WDML_QS_PASS;
500
501 switch (msg->message)
502 {
503 case WM_DDE_ACK:
504 UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
505 FreeDDElParam(WM_DDE_ACK, msg->lParam);
506 GlobalDeleteAtom(uiHi);
507 if (ack) *ack = uiLo;
508 WDML_ExtractAck(uiLo, &ddeAck);
509 pXAct->hDdeData = 0;
510 if (ddeAck.fAck)
511 ERR("Positive answer should appear in NACK for a request, assuming negative\n");
512 TRACE("Negative answer...\n");
513 break;
514
515 case WM_DDE_DATA:
516 UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi);
517 TRACE("Got the result (%08Ix)\n", uiLo);
518
519 hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
520
521 if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
522 return WDML_QS_PASS;
523
524 pXAct->hDdeData = WDML_Global2DataHandle(pConv, (HGLOBAL)uiLo, &wdh);
525 if (wdh.fRelease)
526 {
527 GlobalFree((HGLOBAL)uiLo);
528 }
529 if (wdh.fAckReq)
530 {
531 pConv->instance->lastError = DMLERR_MEMORY_ERROR;
532 }
533 else
534 {
535 GlobalDeleteAtom(uiHi);
536 FreeDDElParam(WM_DDE_ACK, msg->lParam);
537 }
538 break;
539
540 default:
541 FreeDDElParam(msg->message, msg->lParam);
542 return WDML_QS_PASS;
543 }
544
545 return WDML_QS_HANDLED;
546}
547
548/******************************************************************
549 * WDML_BuildExecuteCommand
550 *
551 * Creates a DDE block suitable for sending in WM_DDE_COMMAND
552 * It also takes care of string conversion between the two window procedures
553 */
555{
556 HGLOBAL hMem;
557 BOOL clientUnicode, serverUnicode;
558 DWORD memSize;
559
560 clientUnicode = pConv->instance->unicode;
561 TRACE("client %p uses unicode = %d\n", pConv->hwndClient, clientUnicode);
562 /* FIXME: how exactly Windows determines what to use for the server side? */
563 serverUnicode = IsWindowUnicode(pConv->hwndServer) && IsWindowUnicode(pConv->hwndClient);
564 TRACE("server %p uses unicode = %d\n", pConv->hwndServer, serverUnicode);
565
566 if (clientUnicode == serverUnicode)
567 {
568 memSize = cbData;
569 }
570 else
571 {
572 if (clientUnicode)
573 {
574 memSize = WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), NULL, 0, NULL, NULL);
575 }
576 else
577 {
578 memSize = MultiByteToWideChar( CP_ACP, 0, pData, cbData, NULL, 0) * sizeof(WCHAR);
579 }
580 }
581
582 hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, memSize);
583
584 if (hMem)
585 {
586 LPSTR pDst;
587
588 pDst = GlobalLock(hMem);
589 if (pDst)
590 {
591 if (clientUnicode == serverUnicode)
592 {
593 memcpy(pDst, pData, cbData);
594 }
595 else
596 {
597 if (clientUnicode)
598 {
599 WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), pDst, memSize, NULL, NULL);
600 }
601 else
602 {
603 MultiByteToWideChar( CP_ACP, 0, pData, cbData, (LPWSTR)pDst, memSize/sizeof(WCHAR));
604 }
605 }
606
607 GlobalUnlock(hMem);
608 }
609 else
610 {
611 GlobalFree(hMem);
612 hMem = 0;
613 }
614 }
615 return hMem;
616}
617
618/******************************************************************
619 * WDML_ClientQueueExecute
620 *
621 *
622 */
624{
625 WDML_XACT* pXAct;
626
627 TRACE("XTYP_EXECUTE transaction\n");
628
629 if (pData == NULL)
630 {
631 if (cbData == (DWORD)-1)
632 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
633 else
634 pConv->instance->lastError = DMLERR_MEMORY_ERROR;
635 return NULL;
636 }
637
638 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_EXECUTE, 0, 0);
639 if (!pXAct)
640 return NULL;
641
642 if (cbData == (DWORD)-1)
643 {
644 HDDEDATA hDdeData = pData;
645
646 pData = DdeAccessData(hDdeData, &cbData);
647 if (pData)
648 {
649 pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData);
650 DdeUnaccessData(hDdeData);
651 }
652 }
653 else
654 {
655 pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData);
656 }
657
658 pXAct->lParam = (LPARAM)pXAct->hMem;
659
660 return pXAct;
661}
662
663/******************************************************************
664 * WDML_HandleExecuteReply
665 *
666 *
667 */
669{
670 DDEACK ddeAck;
671 UINT_PTR uiLo, uiHi;
672
673 if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
674 {
675 return WDML_QS_PASS;
676 }
677
678 UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
679 FreeDDElParam(WM_DDE_ACK, msg->lParam);
680
681 if ((HANDLE)uiHi != pXAct->hMem)
682 {
683 return WDML_QS_PASS;
684 }
685
686 if (ack) *ack = uiLo;
687 WDML_ExtractAck(uiLo, &ddeAck);
688 pXAct->hDdeData = (HDDEDATA)(UINT_PTR)ddeAck.fAck;
689
690 TRACE("hDdeData = %p\n", pXAct->hDdeData);
691 pConv->instance->lastError = (pXAct->hDdeData != 0) ? DMLERR_NO_ERROR : DMLERR_NOTPROCESSED;
692
693 return WDML_QS_HANDLED;
694}
695
696/******************************************************************
697 * WDML_ClientQueuePoke
698 *
699 *
700 */
702 UINT wFmt, HSZ hszItem)
703{
705 WDML_XACT *pXAct;
706 DDEPOKE *ddePoke;
707 HGLOBAL hglobal;
708 ATOM atom;
709
710 TRACE("XTYP_POKE transaction\n");
711
712 atom = WDML_MakeAtomFromHsz(hszItem);
713 if (!atom) return NULL;
714
715 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_POKE, wFmt, hszItem);
716 if (!pXAct)
717 {
718 GlobalDeleteAtom(atom);
719 return NULL;
720 }
721
722 if (cbData == (DWORD)-1)
723 {
724 hglobal = pData;
725 dh = GlobalLock(hglobal);
726 cbData = GlobalSize(hglobal) - sizeof(DDE_DATAHANDLE_HEAD);
727 pData = dh + 1;
728 GlobalUnlock(hglobal);
729 }
730
732 ddePoke = GlobalLock(pXAct->hMem);
733 if (!ddePoke)
734 {
735 pConv->instance->lastError = DMLERR_MEMORY_ERROR;
736 return NULL;
737 }
738
739 ddePoke->unused = 0;
740 ddePoke->fRelease = TRUE;
741 ddePoke->cfFormat = wFmt;
742 memcpy(ddePoke->Value, pData, cbData);
743 GlobalUnlock(pXAct->hMem);
744
745 pXAct->lParam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)pXAct->hMem, atom);
746
747 return pXAct;
748}
749
750/******************************************************************
751 * WDML_HandlePokeReply
752 *
753 *
754 */
756{
757 UINT_PTR uiLo, uiHi;
758 HSZ hsz;
759
760 if (msg->message != WM_DDE_ACK && WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
761 {
762 return WDML_QS_PASS;
763 }
764
765 UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
766 hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
767 if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
768 {
769 return WDML_QS_PASS;
770 }
771 FreeDDElParam(WM_DDE_ACK, msg->lParam);
772 GlobalDeleteAtom(uiHi);
773
774 if (ack) *ack = uiLo;
775 pXAct->hMem = GlobalFree(pXAct->hMem);
776
777 pXAct->hDdeData = (HDDEDATA)TRUE;
778 return TRUE;
779}
780
781/******************************************************************
782 * WDML_ClientQueueTerminate
783 *
784 * Creates and queue an WM_DDE_TERMINATE transaction
785 */
787{
788 WDML_XACT* pXAct;
789
790 pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_TERMINATE, 0, 0);
791 if (!pXAct)
792 return NULL;
793
794 pXAct->lParam = 0;
795 pConv->wStatus &= ~ST_CONNECTED;
796
797 return pXAct;
798}
799
800/******************************************************************
801 * WDML_HandleTerminateReply
802 *
803 * handles the reply to a terminate request
804 */
806{
807 if (msg->message != WM_DDE_TERMINATE)
808 {
809 /* FIXME: should delete data passed here */
810 return WDML_QS_SWALLOWED;
811 }
812
813 if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
814 {
815 FIXME("hmmm shouldn't happen\n");
816 return WDML_QS_PASS;
817 }
818 if (!(pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS))
819 {
820 WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv,
821 0, 0, 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0);
822 }
824 return WDML_QS_HANDLED;
825}
826
827/******************************************************************
828 * WDML_HandleIncomingData
829 *
830 *
831 */
833{
834 UINT_PTR uiLo, uiHi;
835 HDDEDATA hDdeDataIn, hDdeDataOut;
836 WDML_LINK* pLink;
837 WINE_DDEHEAD wdh;
838 HSZ hsz;
839
840 TRACE("WM_DDE_DATA message received in the Client Proc!\n");
841 /* wParam -- sending window handle */
842 /* lParam -- hDdeData & item HSZ */
843
844 UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi);
845 hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
846
847 hDdeDataIn = WDML_Global2DataHandle(pConv, (HGLOBAL)uiLo, &wdh);
848
849 /* billx:
850 * For hot link, data should be passed to its callback with
851 * XTYP_ADVDATA and callback should return the proper status.
852 */
853 pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, hsz,
854 uiLo != 0, wdh.cfFormat);
855 if (!pLink)
856 {
857 WDML_DecHSZ(pConv->instance, hsz);
858 DdeFreeDataHandle(hDdeDataIn);
859 return WDML_QS_PASS;
860 }
861
862 if (hDdeDataIn != 0 && wdh.fAckReq)
863 {
864 WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA);
865 if (msg->lParam)
866 msg->lParam = 0;
867 }
868 else
869 {
870 GlobalDeleteAtom(uiHi);
871 }
872
873 hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_ADVDATA, pLink->uFmt, pLink->hConv,
874 pConv->hszTopic, pLink->hszItem, hDdeDataIn, 0, 0);
875
876 if (hDdeDataOut != (HDDEDATA)DDE_FACK || wdh.fRelease)
877 {
878 if (uiLo) GlobalFree((HANDLE)uiLo);
879 }
880
881 DdeFreeDataHandle(hDdeDataIn);
882
883 WDML_DecHSZ(pConv->instance, hsz);
884 if (msg->lParam)
885 FreeDDElParam(WM_DDE_DATA, msg->lParam);
886
887 return WDML_QS_HANDLED;
888}
889
890/******************************************************************
891 * WDML_HandleIncomingTerminate
892 *
893 *
894 */
896{
897 if (pConv->hwndServer != WIN_GetFullHandle((HWND)msg->wParam))
898 return WDML_QS_PASS;
899
900 pConv->wStatus |= ST_TERMINATED;
901 if (pConv->wStatus & ST_CONNECTED)
902 {
903 /* don't care about result code (if server exists or not) */
905 pConv->wStatus &= ~ST_CONNECTED;
906 }
907 /* have to keep connection around to allow reconnection */
908 return WDML_QS_HANDLED;
909}
910
911/******************************************************************
912 * WDML_HandleReply
913 *
914 * handles any incoming reply, and try to match to an already sent request
915 */
916static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd, DWORD *ack)
917{
918 WDML_XACT* pXAct = pConv->transactions;
920
921 if (pConv->transactions)
922 {
923 if (ack) *ack = DDE_FNOTPROCESSED;
924 /* first check message against a pending transaction, if any */
925 switch (pXAct->ddeMsg)
926 {
927 case WM_DDE_ADVISE:
928 qs = WDML_HandleAdviseReply(pConv, msg, pXAct, ack);
929 break;
930 case WM_DDE_UNADVISE:
931 qs = WDML_HandleUnadviseReply(pConv, msg, pXAct, ack);
932 break;
933 case WM_DDE_EXECUTE:
934 qs = WDML_HandleExecuteReply(pConv, msg, pXAct, ack);
935 break;
936 case WM_DDE_REQUEST:
937 qs = WDML_HandleRequestReply(pConv, msg, pXAct, ack);
938 break;
939 case WM_DDE_POKE:
940 qs = WDML_HandlePokeReply(pConv, msg, pXAct, ack);
941 break;
942 case WM_DDE_TERMINATE:
943 qs = WDML_HandleTerminateReply(pConv, msg);
944 break;
945 default:
946 qs = WDML_QS_ERROR;
947 FIXME("oooch\n");
948 }
949 }
950 else
951 {
952 qs = WDML_QS_PASS;
953 }
954
955 /* now check the results */
956 switch (qs)
957 {
958 case WDML_QS_ERROR:
960 *hdd = 0;
961 break;
962 case WDML_QS_HANDLED:
963 /* ok, we have resolved a pending transaction
964 * notify callback if asynchronous.
965 */
966 if (pXAct->dwTimeout == TIMEOUT_ASYNC && pXAct->ddeMsg != WM_DDE_TERMINATE)
967 {
969 (HCONV)pConv, pConv->hszTopic, pXAct->hszItem,
970 pXAct->hDdeData, MAKELONG(0, pXAct->xActID), 0 /* FIXME */);
971 qs = WDML_QS_PASS;
972 }
973 else
974 {
975 *hdd = pXAct->hDdeData;
976 }
977 break;
978 case WDML_QS_PASS:
979 /* no pending transaction found, try a warm/hot link or a termination request */
980 switch (msg->message)
981 {
982 case WM_DDE_DATA:
983 qs = WDML_HandleIncomingData(pConv, msg, hdd);
984 break;
985 case WM_DDE_TERMINATE:
986 qs = WDML_HandleIncomingTerminate(pConv, msg, hdd);
987 break;
988 case WM_DDE_ACK:
989 /* This happens at end of DdeClientTransaction XTYP_EXECUTE
990 * Without this assignment, DdeClientTransaction's return value is undefined
991 */
992 *hdd = (HDDEDATA)TRUE;
993 if (ack)
994 *ack = DDE_FACK;
995 break;
996 }
997 break;
998 case WDML_QS_BLOCK:
999 FIXME("shouldn't be used on client side\n");
1000 break;
1001 }
1002
1003 return qs;
1004}
1005
1006/******************************************************************
1007 * WDML_SyncWaitTransactionReply
1008 *
1009 * waits until an answer for a sent request is received
1010 * time out is also handled. only used for synchronous transactions
1011 */
1012static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, const WDML_XACT* pXAct, DWORD *ack)
1013{
1014 DWORD start, elapsed;
1015 DWORD err;
1016 WDML_CONV* pConv;
1017
1018 TRACE("Starting wait for a timeout of %ld ms\n", dwTimeout);
1019
1020 start = GetTickCount();
1021 while ((elapsed = GetTickCount() - start) < dwTimeout)
1022 {
1023 /* we cannot be in the crit sect all the time because when client and server run in a
1024 * single process they need to share the access to the internal data
1025 */
1027 dwTimeout - elapsed, QS_POSTMESSAGE) == WAIT_OBJECT_0)
1028 {
1029 MSG msg;
1030
1032 {
1033 HDDEDATA hdd = NULL;
1034
1035 pConv = WDML_GetConv(hConv, FALSE);
1036 if (pConv == NULL)
1037 {
1038 /* conversation no longer available... return failure */
1039 return 0;
1040 }
1041 if (msg.hwnd == pConv->hwndClient)
1042 {
1043 /* check that either pXAct has been processed or no more xActions are pending */
1044 BOOL ret = (pConv->transactions == pXAct);
1045 if (WDML_HandleReply(pConv, &msg, &hdd, ack) == WDML_QS_HANDLED)
1046 {
1047 TRACE("WDML_HandleReply returned WDML_QS_HANDLED\n");
1048 ret = TRUE;
1049 }
1050 else
1051 ret = (pConv->transactions == NULL || ret);
1052
1053 if (ret)
1054 {
1055 pConv->instance->lastError = hdd ? DMLERR_NO_ERROR : DMLERR_NOTPROCESSED;
1056 return hdd;
1057 }
1058 }
1059 else
1060 {
1062 }
1063 }
1064 }
1065 }
1066
1067 TRACE("Timeout !!\n");
1068
1069 pConv = WDML_GetConv(hConv, FALSE);
1070 if (pConv != NULL)
1071 {
1072 if (pConv->transactions)
1073 {
1074 switch (pConv->transactions->ddeMsg)
1075 {
1076 case WM_DDE_ADVISE: err = DMLERR_ADVACKTIMEOUT; break;
1079 case WM_DDE_POKE: err = DMLERR_POKEACKTIMEOUT; break;
1081 default: err = DMLERR_INVALIDPARAMETER; break;
1082 }
1083
1084 pConv->instance->lastError = err;
1085 }
1086 }
1087
1088 return 0;
1089}
1090
1091
1092/*****************************************************************
1093 * WDML_ClientHandle
1094 */
1095HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult)
1096{
1097 HDDEDATA hDdeData;
1098
1099 if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam))
1100 {
1101 WARN("Failed posting message %x to %p (error=0x%lx)\n",
1102 pXAct->ddeMsg, pConv->hwndServer, GetLastError());
1103 pConv->wStatus &= ~ST_CONNECTED;
1104 pConv->instance->lastError = DMLERR_POSTMSG_FAILED;
1105 return 0;
1106 }
1107 pXAct->dwTimeout = dwTimeout;
1108 /* FIXME: should set the app bits on *pdwResult */
1109
1110 if (dwTimeout == TIMEOUT_ASYNC)
1111 {
1112 if (pdwResult)
1113 *pdwResult = MAKELONG(0, pXAct->xActID);
1114
1115 hDdeData = (HDDEDATA)1;
1116 }
1117 else
1118 hDdeData = WDML_SyncWaitTransactionReply((HCONV)pConv, dwTimeout, pXAct, pdwResult);
1119
1120 return hDdeData;
1121}
1122
1123
1124/*****************************************************************
1125 * DdeClientTransaction (USER32.@)
1126 */
1127HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt,
1128 UINT wType, DWORD dwTimeout, LPDWORD pdwResult)
1129{
1130 WDML_CONV* pConv;
1131 WDML_XACT* pXAct;
1132 HDDEDATA hDdeData;
1133
1134 TRACE("(%p,%ld,%p,%p,%x,%x,%ld,%p)\n",
1135 pData, cbData, hConv, hszItem, wFmt, wType, dwTimeout, pdwResult);
1136
1137 if (hConv == 0)
1138 {
1139 WARN("Invalid conversation handle NULL\n");
1140 return 0;
1141 }
1142
1143 pConv = WDML_GetConv(hConv, TRUE);
1144 if (pConv == NULL)
1145 {
1146 /* cannot set error... cannot get back to DDE instance */
1147 return 0;
1148 }
1149
1150 switch (wType)
1151 {
1152 case XTYP_EXECUTE:
1153 /* Windows simply ignores hszItem and wFmt in this case */
1154 pXAct = WDML_ClientQueueExecute(pConv, pData, cbData);
1155 if (pXAct == NULL)
1156 return 0;
1157 break;
1158 case XTYP_POKE:
1159 if (!hszItem)
1160 {
1161 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1162 return 0;
1163 }
1164 pXAct = WDML_ClientQueuePoke(pConv, pData, cbData, wFmt, hszItem);
1165 break;
1168 case XTYP_ADVSTART:
1170 if (pData)
1171 {
1172 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1173 return 0;
1174 }
1175 pXAct = WDML_ClientQueueAdvise(pConv, wType, wFmt, hszItem);
1176 break;
1177 case XTYP_ADVSTOP:
1178 if (pData)
1179 {
1180 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1181 return 0;
1182 }
1183 pXAct = WDML_ClientQueueUnadvise(pConv, wFmt, hszItem);
1184 break;
1185 case XTYP_REQUEST:
1186 if (pData || !hszItem)
1187 {
1188 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1189 return 0;
1190 }
1191 pXAct = WDML_ClientQueueRequest(pConv, wFmt, hszItem);
1192 break;
1193 default:
1194 FIXME("Unknown transaction type %04x\n", wType);
1195 /* unknown transaction type */
1196 pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1197 return 0;
1198 }
1199
1200 if (pXAct == NULL)
1201 {
1202 pConv->instance->lastError = DMLERR_MEMORY_ERROR;
1203 return 0;
1204 }
1205
1206 WDML_QueueTransaction(pConv, pXAct);
1207
1208 TRACE("pConv->wStatus %04lx\n", pConv->wStatus);
1209
1210 if (pConv->wStatus & ST_BLOCKED)
1211 {
1212 TRACE("Transactions are blocked, add to the queue and exit\n");
1213 return (HDDEDATA)1;
1214 }
1215
1216 hDdeData = WDML_ClientHandle(pConv, pXAct, dwTimeout, pdwResult);
1217 if (dwTimeout != TIMEOUT_ASYNC)
1218 {
1219 WDML_UnQueueTransaction(pConv, pXAct);
1220 WDML_FreeTransaction(pConv->instance, pXAct, TRUE);
1221 }
1222
1223 return hDdeData;
1224}
1225
1226/*****************************************************************
1227 * DdeAbandonTransaction (USER32.@)
1228 */
1229BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction)
1230{
1232 WDML_CONV* pConv;
1233 WDML_XACT* pXAct;
1234
1235 if ((pInstance = WDML_GetInstance(idInst)))
1236 {
1237 if (hConv)
1238 {
1239 if ((pConv = WDML_GetConv(hConv, TRUE)) && pConv->instance == pInstance)
1240 {
1241
1242 pXAct = pConv->transactions;
1243 while (pXAct) {
1244 WDML_XACT *nextXAct = pXAct->next;
1245
1246 if (pXAct->dwTimeout == TIMEOUT_ASYNC &&
1247 (idTransaction == 0 || pXAct->xActID == idTransaction))
1248 {
1249 WDML_UnQueueTransaction(pConv, pXAct);
1251 }
1252 pXAct = nextXAct;
1253 }
1254 }
1255 }
1256 else
1257 {
1258 for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv; pConv = pConv->next)
1259 {
1260 if (!(pConv->wStatus & ST_CONNECTED)) continue;
1261 pXAct = pConv->transactions;
1262 while (pXAct) {
1263 WDML_XACT *nextXAct = pXAct->next;
1264
1265 if (pXAct->dwTimeout == TIMEOUT_ASYNC)
1266 {
1267 WDML_UnQueueTransaction(pConv, pXAct);
1269 }
1270 pXAct = nextXAct;
1271 }
1272 }
1273 }
1274 }
1275
1276 return TRUE;
1277}
1278
1279/******************************************************************
1280 * WDML_ClientProc
1281 *
1282 * Window Proc created on client side for each conversation
1283 */
1285{
1286 UINT uiLo, uiHi;
1287 WDML_CONV* pConv = NULL;
1288 HSZ hszSrv, hszTpc;
1289
1290 TRACE("%p %04x %08Ix %08Ix\n", hwnd, iMsg, wParam, lParam);
1291
1292 if (iMsg == WM_DDE_ACK &&
1293 /* in the initial WM_INITIATE sendmessage */
1294 ((pConv = WDML_GetConvFromWnd(hwnd)) == NULL || pConv->wStatus == XST_INIT1))
1295 {
1296 /* In response to WM_DDE_INITIATE, save server window */
1297 char buf[256];
1299
1300 /* note: sent messages do not need packing */
1301 uiLo = LOWORD(lParam);
1302 uiHi = HIWORD(lParam);
1303
1304 /* FIXME: convlist should be handled here */
1305 if (pConv)
1306 {
1307 /* we already have started the conv with a server, drop other replies */
1308 GlobalDeleteAtom(uiLo);
1309 GlobalDeleteAtom(uiHi);
1311 return 0;
1312 }
1313
1315
1316 hszSrv = WDML_MakeHszFromAtom(pInstance, uiLo);
1317 hszTpc = WDML_MakeHszFromAtom(pInstance, uiHi);
1318
1319 pConv = WDML_AddConv(pInstance, WDML_CLIENT_SIDE, hszSrv, hszTpc, hwnd, (HWND)wParam);
1320
1322 pConv->wStatus |= ST_CONNECTED;
1323 pConv->wConvst = XST_INIT1;
1324
1325 /* check if server is handled by DDEML */
1326 if ((GetClassNameA((HWND)wParam, buf, sizeof(buf)) &&
1328 (GetClassNameW((HWND)wParam, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) &&
1330 {
1331 pConv->wStatus |= ST_ISLOCAL;
1332 }
1333
1334 GlobalDeleteAtom(uiLo);
1335 GlobalDeleteAtom(uiHi);
1336
1337 /* accept conversation */
1338 return 1;
1339 }
1340
1341 if (iMsg >= WM_DDE_FIRST && iMsg <= WM_DDE_LAST)
1342 {
1343 pConv = WDML_GetConvFromWnd(hwnd);
1344
1345 if (pConv)
1346 {
1347 MSG msg;
1348 HDDEDATA hdd;
1349
1350 msg.hwnd = hwnd;
1351 msg.message = iMsg;
1352 msg.wParam = wParam;
1353 msg.lParam = lParam;
1354
1355 WDML_HandleReply(pConv, &msg, &hdd, NULL);
1356 }
1357
1358 return 0;
1359 }
1360
1363}
1364
1365/*****************************************************************
1366 * DdeDisconnect (USER32.@)
1367 */
1369{
1370 WDML_CONV* pConv;
1371 WDML_XACT* pXAct;
1372 BOOL ret = FALSE;
1373
1374 TRACE("(%p)\n", hConv);
1375
1376 if (hConv == 0)
1377 {
1378 WARN("DdeDisconnect(): hConv = 0\n");
1379 return FALSE;
1380 }
1381
1382 pConv = WDML_GetConv(hConv, TRUE);
1383 if (pConv != NULL)
1384 {
1385 if (pConv->wStatus & ST_CLIENT)
1386 {
1387 /* FIXME: should abandon all pending transactions */
1388 pXAct = WDML_ClientQueueTerminate(pConv);
1389 if (pXAct != NULL)
1390 {
1391 if (PostMessageW(pConv->hwndServer, pXAct->ddeMsg,
1392 (WPARAM)pConv->hwndClient, pXAct->lParam))
1393 {
1394 WDML_SyncWaitTransactionReply(hConv, 10000, pXAct, NULL);
1395 ret = TRUE;
1396 }
1397 else
1398 pConv->instance->lastError = DMLERR_POSTMSG_FAILED;
1399
1400 WDML_FreeTransaction(pConv->instance, pXAct, TRUE);
1401 /* still have to destroy data associated with conversation */
1403 }
1404 else
1405 {
1406 FIXME("Not implemented yet for a server side conversation\n");
1407 }
1408 }
1409 }
1410
1411 return ret;
1412}
1413
1414/*****************************************************************
1415 * DdeImpersonateClient (USER32.@)
1416 */
1418{
1419 WDML_CONV* pConv;
1420 BOOL ret = FALSE;
1421
1422 TRACE("(%p)\n", hConv);
1423
1424 pConv = WDML_GetConv(hConv, TRUE);
1425 if (pConv)
1426 {
1428 }
1429 return ret;
1430}
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define WM_DDE_REQUEST
Definition: dde.h:43
BOOL WINAPI UnpackDDElParam(UINT, LPARAM, PUINT_PTR, PUINT_PTR)
Definition: ddemisc.c:109
#define WM_DDE_DATA
Definition: dde.h:42
#define WM_DDE_POKE
Definition: dde.h:44
#define WM_DDE_FIRST
Definition: dde.h:47
#define WM_DDE_LAST
Definition: dde.h:46
BOOL WINAPI ImpersonateDdeClientWindow(HWND hWndClient, HWND hWndServer)
Definition: ddemisc.c:225
#define WM_DDE_ADVISE
Definition: dde.h:39
BOOL WINAPI FreeDDElParam(UINT, LPARAM)
Definition: ddemisc.c:151
#define WM_DDE_ACK
Definition: dde.h:41
#define WM_DDE_EXECUTE
Definition: dde.h:45
#define WM_DDE_INITIATE
Definition: dde.h:37
LPARAM WINAPI PackDDElParam(UINT, UINT_PTR, UINT_PTR)
Definition: ddemisc.c:67
#define WM_DDE_UNADVISE
Definition: dde.h:40
#define WM_DDE_TERMINATE
Definition: dde.h:38
void WDML_QueueTransaction(WDML_CONV *pConv, WDML_XACT *pXAct)
Definition: ddemisc.c:1941
WDML_INSTANCE * WDML_GetInstanceFromWnd(HWND hWnd)
Definition: ddemisc.c:1265
#define GWL_WDML_CONVERSATION
Definition: dde_private.h:263
WDML_CONV * WDML_AddConv(WDML_INSTANCE *pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer)
Definition: ddemisc.c:2016
static __inline void WDML_ExtractAck(WORD status, DDEACK *da)
Definition: dde_private.h:240
WDML_CONV * WDML_GetConv(HCONV hConv, BOOL checkConnected)
Definition: ddemisc.c:2239
BOOL WDML_PostAck(WDML_CONV *pConv, WDML_SIDE side, WORD appRetCode, BOOL fBusy, BOOL fAck, UINT_PTR pmt, LPARAM lParam, UINT oldMsg)
Definition: ddemisc.c:2284
HSZ WDML_MakeHszFromAtom(const WDML_INSTANCE *pInstance, ATOM atom)
Definition: ddemisc.c:346
void WDML_FreeTransaction(WDML_INSTANCE *pInstance, WDML_XACT *pXAct, BOOL doFreePmt)
Definition: ddemisc.c:1975
struct tagDDE_DATAHANDLE_HEAD DDE_DATAHANDLE_HEAD
void WDML_RemoveLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, HSZ hszItem, UINT wFmt)
Definition: ddemisc.c:1788
BOOL WDML_DecHSZ(WDML_INSTANCE *pInstance, HSZ hsz)
Definition: ddemisc.c:384
void WDML_RemoveConv(WDML_CONV *pConv, WDML_SIDE side)
Definition: ddemisc.c:2078
HDDEDATA WDML_InvokeCallback(WDML_INSTANCE *pInst, UINT uType, UINT uFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
Definition: ddemisc.c:1210
WDML_XACT * WDML_AllocTransaction(WDML_INSTANCE *pInstance, UINT ddeMsg, UINT wFmt, HSZ hszItem)
Definition: ddemisc.c:1908
ATOM WDML_MakeAtomFromHsz(HSZ hsz)
Definition: ddemisc.c:329
WDML_LINK * WDML_FindLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, HSZ hszItem, BOOL use_fmt, UINT uFmt)
Definition: ddemisc.c:1876
WDML_CONV * WDML_FindConv(WDML_INSTANCE *pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic)
Definition: ddemisc.c:2056
const char WDML_szServerConvClassA[]
Definition: ddeserver.c:35
BOOL WDML_UnQueueTransaction(WDML_CONV *pConv, WDML_XACT *pXAct)
Definition: ddemisc.c:1955
@ WDML_CLIENT_SIDE
Definition: dde_private.h:184
WDML_INSTANCE * WDML_GetInstance(DWORD InstId)
Definition: ddemisc.c:1234
HDDEDATA WDML_Global2DataHandle(WDML_CONV *pConv, HGLOBAL hMem, WINE_DDEHEAD *da)
Definition: ddemisc.c:1509
WDML_QUEUE_STATE
Definition: dde_private.h:187
@ WDML_QS_PASS
Definition: dde_private.h:188
@ WDML_QS_BLOCK
Definition: dde_private.h:188
@ WDML_QS_HANDLED
Definition: dde_private.h:188
@ WDML_QS_SWALLOWED
Definition: dde_private.h:188
@ WDML_QS_ERROR
Definition: dde_private.h:188
WDML_CONV * WDML_GetConvFromWnd(HWND hWnd)
Definition: ddemisc.c:2274
void WDML_AddLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, UINT wType, HSZ hszItem, UINT wFmt)
Definition: ddemisc.c:1763
#define GWL_WDML_INSTANCE
Definition: dde_private.h:262
const WCHAR WDML_szServerConvClassW[]
Definition: ddeserver.c:36
static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV *pConv, MSG *msg)
Definition: ddeclient.c:805
static WDML_QUEUE_STATE WDML_HandleIncomingTerminate(WDML_CONV *pConv, MSG *msg, HDDEDATA *hdd)
Definition: ddeclient.c:895
static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV *pConv, MSG *msg, WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:491
BOOL WINAPI DdeDisconnectList(HCONVLIST hConvList)
Definition: ddeclient.c:80
static LRESULT CALLBACK WDML_ClientProc(HWND, UINT, WPARAM, LPARAM)
Definition: ddeclient.c:1284
HCONV WINAPI DdeReconnect(HCONV hConv)
Definition: ddeclient.c:217
static WDML_XACT * WDML_ClientQueueRequest(WDML_CONV *pConv, UINT wFmt, HSZ hszItem)
Definition: ddeclient.c:464
BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction)
Definition: ddeclient.c:1229
static WDML_XACT * WDML_ClientQueueExecute(WDML_CONV *pConv, LPVOID pData, DWORD cbData)
Definition: ddeclient.c:623
const WCHAR WDML_szClientConvClassW[]
Definition: ddeclient.c:36
HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt, UINT wType, DWORD dwTimeout, LPDWORD pdwResult)
Definition: ddeclient.c:1127
BOOL WINAPI DdeImpersonateClient(HCONV hConv)
Definition: ddeclient.c:1417
static WDML_QUEUE_STATE WDML_HandleIncomingData(WDML_CONV *pConv, MSG *msg, HDDEDATA *hdd)
Definition: ddeclient.c:832
static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, const WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:1012
BOOL WINAPI DdeDisconnect(HCONV hConv)
Definition: ddeclient.c:1368
static WDML_XACT * WDML_ClientQueueUnadvise(WDML_CONV *pConv, UINT wFmt, HSZ hszItem)
Definition: ddeclient.c:390
static WDML_QUEUE_STATE WDML_HandlePokeReply(WDML_CONV *pConv, MSG *msg, WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:755
static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV *pConv, MSG *msg, HDDEDATA *hdd, DWORD *ack)
Definition: ddeclient.c:916
HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult)
Definition: ddeclient.c:1095
static WDML_XACT * WDML_ClientQueueAdvise(WDML_CONV *pConv, UINT wType, UINT wFmt, HSZ hszItem)
Definition: ddeclient.c:294
static WDML_XACT * WDML_ClientQueueTerminate(WDML_CONV *pConv)
Definition: ddeclient.c:786
static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV *pConv, LPCVOID pData, DWORD cbData)
Definition: ddeclient.c:554
HCONVLIST WINAPI DdeConnectList(DWORD idInst, HSZ hszService, HSZ hszTopic, HCONVLIST hConvList, PCONVCONTEXT pCC)
Definition: ddeclient.c:53
const char WDML_szClientConvClassA[]
Definition: ddeclient.c:35
static WDML_QUEUE_STATE WDML_HandleExecuteReply(WDML_CONV *pConv, MSG *msg, WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:668
HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic, PCONVCONTEXT pCC)
Definition: ddeclient.c:89
HCONV WINAPI DdeQueryNextServer(HCONVLIST hConvList, HCONV hConvPrev)
Definition: ddeclient.c:63
static WDML_QUEUE_STATE WDML_HandleAdviseReply(WDML_CONV *pConv, MSG *msg, WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:333
static WDML_XACT * WDML_ClientQueuePoke(WDML_CONV *pConv, LPVOID pData, DWORD cbData, UINT wFmt, HSZ hszItem)
Definition: ddeclient.c:701
static WDML_QUEUE_STATE WDML_HandleUnadviseReply(WDML_CONV *pConv, MSG *msg, WDML_XACT *pXAct, DWORD *ack)
Definition: ddeclient.c:419
#define XTYPF_NODATA
Definition: ddeml.h:171
#define DMLERR_UNADVACKTIMEOUT
Definition: ddeml.h:262
#define ST_CONNECTED
Definition: ddeml.h:80
#define ST_CLIENT
Definition: ddeml.h:84
#define XTYP_XACT_COMPLETE
Definition: ddeml.h:188
INT WINAPI DdeCmpStringHandles(HSZ, HSZ)
Definition: ddemisc.c:689
#define CBF_SKIP_DISCONNECTS
Definition: ddeml.h:114
#define DMLERR_POSTMSG_FAILED
Definition: ddeml.h:258
#define DMLERR_NO_ERROR
Definition: ddeml.h:242
#define XTYP_ADVSTART
Definition: ddeml.h:183
#define DDE_FACK
Definition: ddeml.h:216
#define XTYP_REQUEST
Definition: ddeml.h:191
#define XTYP_ADVSTOP
Definition: ddeml.h:184
#define DMLERR_MEMORY_ERROR
Definition: ddeml.h:254
#define ST_ISLOCAL
Definition: ddeml.h:82
#define DMLERR_NOTPROCESSED
Definition: ddeml.h:255
#define DMLERR_ADVACKTIMEOUT
Definition: ddeml.h:246
#define DDE_FNOTPROCESSED
Definition: ddeml.h:223
#define XTYP_DISCONNECT
Definition: ddeml.h:192
#define XTYP_POKE
Definition: ddeml.h:189
#define ST_ISSELF
Definition: ddeml.h:88
#define DMLERR_EXECACKTIMEOUT
Definition: ddeml.h:251
#define DMLERR_POKEACKTIMEOUT
Definition: ddeml.h:257
#define DMLERR_DATAACKTIMEOUT
Definition: ddeml.h:248
#define XST_CONNECTED
Definition: ddeml.h:64
#define ST_BLOCKED
Definition: ddeml.h:83
#define CP_WINANSI
Definition: ddeml.h:32
#define ST_TERMINATED
Definition: ddeml.h:85
#define TIMEOUT_ASYNC
Definition: ddeml.h:200
#define XTYP_EXECUTE
Definition: ddeml.h:185
#define CP_WINUNICODE
Definition: ddeml.h:33
#define DMLERR_NO_CONV_ESTABLISHED
Definition: ddeml.h:256
#define XTYPF_ACKREQ
Definition: ddeml.h:172
BOOL WINAPI DdeUnaccessData(HDDEDATA)
Definition: ddemisc.c:1452
LPBYTE WINAPI DdeAccessData(HDDEDATA, LPDWORD)
Definition: ddemisc.c:1427
#define XTYP_ADVDATA
Definition: ddeml.h:181
BOOL WINAPI DdeFreeDataHandle(HDDEDATA)
Definition: ddemisc.c:1466
#define DMLERR_INVALIDPARAMETER
Definition: ddeml.h:252
#define XST_INIT1
Definition: ddeml.h:65
WORD ATOM
Definition: dimm.idl:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CP_ACP
Definition: compat.h:109
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
ATOM WINAPI GlobalDeleteAtom(ATOM nAtom)
Definition: atom.c:444
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4171
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxWmiInstanceExternal * pInstance
Definition: fxwmiapi.cpp:117
GLuint start
Definition: gl.h:1545
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
unsigned int UINT
Definition: sysinfo.c:13
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
CONST void * LPCVOID
Definition: minwindef.h:164
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define LOWORD(l)
Definition: pedump.c:82
short WCHAR
Definition: pedump.c:58
#define WS_POPUP
Definition: pedump.c:616
_In_ UINT _In_ DWORD _Out_ DWORD * pdwResult
Definition: ntgdi.h:270
#define MAKELPARAM(l, h)
Definition: winuser.h:4116
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4469
int WINAPI GetClassNameA(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPSTR lpClassName, _In_ int nMaxCount)
#define HWND_BROADCAST
Definition: winuser.h:1215
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
LRESULT WINAPI SendMessageTimeoutW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM, _In_ UINT, _In_ UINT, _Out_opt_ PDWORD_PTR)
BOOL WINAPI IsWindowUnicode(_In_ HWND)
ATOM WINAPI RegisterClassExA(_In_ CONST WNDCLASSEXA *)
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define PM_REMOVE
Definition: winuser.h:1207
ATOM WINAPI RegisterClassExW(_In_ CONST WNDCLASSEXW *)
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4470
#define QS_POSTMESSAGE
Definition: winuser.h:888
#define SMTO_ABORTIFHUNG
Definition: winuser.h:1234
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
#define SetWindowLongPtrW
Definition: winuser.h:5512
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
static HSZ hszTopic
Definition: shlexec.c:148
#define TRACE(s)
Definition: solgame.cpp:4
Definition: dde.h:51
unsigned short fAck
Definition: dde.h:52
Definition: dde.h:65
short cfFormat
Definition: dde.h:67
unsigned short fAckReq
Definition: dde.h:66
unsigned short fDeferUpd
Definition: dde.h:66
Definition: dde.h:72
short cfFormat
Definition: dde.h:74
BYTE Value[1]
Definition: dde.h:75
unsigned short unused
Definition: dde.h:73
unsigned short fRelease
Definition: dde.h:73
unsigned short fRelease
Definition: dde_private.h:88
unsigned short fAckReq
Definition: dde_private.h:90
short cfFormat
Definition: dde_private.h:91
int cbClsExtra
Definition: winuser.h:3312
HINSTANCE hInstance
Definition: winuser.h:3314
HCURSOR hCursor
Definition: winuser.h:3316
LPCSTR lpszMenuName
Definition: winuser.h:3318
HICON hIconSm
Definition: winuser.h:3320
UINT style
Definition: winuser.h:3310
int cbWndExtra
Definition: winuser.h:3313
UINT cbSize
Definition: winuser.h:3309
WNDPROC lpfnWndProc
Definition: winuser.h:3311
LPCSTR lpszClassName
Definition: winuser.h:3319
HICON hIcon
Definition: winuser.h:3315
HBRUSH hbrBackground
Definition: winuser.h:3317
LPCWSTR lpszClassName
Definition: winuser.h:3334
LPCWSTR lpszMenuName
Definition: winuser.h:3333
HBRUSH hbrBackground
Definition: winuser.h:3332
WNDPROC lpfnWndProc
Definition: winuser.h:3326
UINT cbSize
Definition: winuser.h:3324
int cbWndExtra
Definition: winuser.h:3328
HCURSOR hCursor
Definition: winuser.h:3331
HICON hIconSm
Definition: winuser.h:3335
HINSTANCE hInstance
Definition: winuser.h:3329
UINT style
Definition: winuser.h:3325
int cbClsExtra
Definition: winuser.h:3327
HICON hIcon
Definition: winuser.h:3330
INT iCodePage
Definition: ddeml.h:310
struct tagWDML_CONV * next
Definition: dde_private.h:129
CONVCONTEXT convContext
Definition: dde_private.h:135
WDML_XACT * transactions
Definition: dde_private.h:138
struct tagWDML_INSTANCE * instance
Definition: dde_private.h:130
HDDEDATA hDdeData
Definition: dde_private.h:116
struct tagWDML_XACT * next
Definition: dde_private.h:113
DWORD dwTimeout
Definition: dde_private.h:117
LPARAM lParam
Definition: dde_private.h:124
HGLOBAL hMem
Definition: dde_private.h:123
PCBYTE PBYTE SIZE_T cbData
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWSTR
Definition: typedefs.h:56
uint32_t * LPDWORD
Definition: typedefs.h:59
char * LPSTR
Definition: typedefs.h:51
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define HIWORD(l)
Definition: typedefs.h:247
#define WIN_GetFullHandle(h)
Definition: user_x.h:108
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WAIT_OBJECT_0
Definition: winbase.h:383
#define GHND
Definition: winbase.h:321
#define GMEM_MOVEABLE
Definition: winbase.h:318
#define GMEM_DDESHARE
Definition: winbase.h:322
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define WINAPI
Definition: msvc.h:6