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