ReactOS  0.4.14-dev-50-g13bb5e2
ddemisc.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 2003, 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 
28 #include "dde_private.h"
29 
31 
32 /* convert between ATOM and HSZ avoiding compiler warnings */
33 #define ATOM2HSZ(atom) ((HSZ) (ULONG_PTR)(atom))
34 #define HSZ2ATOM(hsz) ((ATOM) (ULONG_PTR)(hsz))
35 
37 static LONG WDML_MaxInstanceID = 0; /* OK for present, have to worry about wrap-around later */
38 const WCHAR WDML_szEventClass[] = L"DDEMLEvent";
39 
40 /* protection for instance list */
43 {
44  0, 0, &WDML_CritSect,
46  0, 0, { (DWORD_PTR)(__FILE__ ": WDML_CritSect") }
47 };
48 static CRITICAL_SECTION WDML_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
49 
50 /* ================================================================
51  *
52  * Pure DDE (non DDEML) management
53  *
54  * ================================================================ */
55 
56 
57 /*****************************************************************
58  * PackDDElParam (USER32.@)
59  *
60  * RETURNS
61  * the packed lParam
62  */
64 {
65  HGLOBAL hMem;
67 
68  switch (msg)
69  {
70  case WM_DDE_ACK:
71  case WM_DDE_ADVISE:
72  case WM_DDE_DATA:
73  case WM_DDE_POKE:
74  if (!(hMem = GlobalAlloc(GMEM_DDESHARE, sizeof(UINT_PTR) * 2)))
75  {
76  ERR("GlobalAlloc failed\n");
77  return 0;
78  }
79  if (!(params = GlobalLock(hMem)))
80  {
81  ERR("GlobalLock failed (%p)\n", hMem);
82  return 0;
83  }
84  params[0] = uiLo;
85  params[1] = uiHi;
86  GlobalUnlock(hMem);
87  return (LPARAM)hMem;
88 
89  case WM_DDE_EXECUTE:
90  return uiHi;
91 
92  default:
93  return MAKELONG(uiLo, uiHi);
94  }
95 }
96 
97 
98 /*****************************************************************
99  * UnpackDDElParam (USER32.@)
100  *
101  * RETURNS
102  * success: nonzero
103  * failure: zero
104  */
106  PUINT_PTR uiLo, PUINT_PTR uiHi)
107 {
108  UINT_PTR *params;
109 
110  switch (msg)
111  {
112  case WM_DDE_ACK:
113  case WM_DDE_ADVISE:
114  case WM_DDE_DATA:
115  case WM_DDE_POKE:
116  if (!lParam || !(params = GlobalLock((HGLOBAL)lParam)))
117  {
118  if (uiLo) *uiLo = 0;
119  if (uiHi) *uiHi = 0;
120  return FALSE;
121  }
122  if (uiLo) *uiLo = params[0];
123  if (uiHi) *uiHi = params[1];
125  return TRUE;
126 
127  case WM_DDE_EXECUTE:
128  if (uiLo) *uiLo = 0;
129  if (uiHi) *uiHi = lParam;
130  return TRUE;
131 
132  default:
133  if (uiLo) *uiLo = LOWORD(lParam);
134  if (uiHi) *uiHi = HIWORD(lParam);
135  return TRUE;
136  }
137 }
138 
139 
140 /*****************************************************************
141  * FreeDDElParam (USER32.@)
142  *
143  * RETURNS
144  * success: nonzero
145  * failure: zero
146  */
148 {
149  switch (msg)
150  {
151  case WM_DDE_ACK:
152  case WM_DDE_ADVISE:
153  case WM_DDE_DATA:
154  case WM_DDE_POKE:
155  /* first check if it's a global handle */
156  if (!GlobalHandle( (LPVOID)lParam )) return TRUE;
157  return !GlobalFree( (HGLOBAL)lParam );
158 
159  default:
160  return TRUE;
161  }
162 }
163 
164 
165 /*****************************************************************
166  * ReuseDDElParam (USER32.@)
167  *
168  * RETURNS
169  * the packed lParam
170  */
172  UINT_PTR uiLo, UINT_PTR uiHi)
173 {
174  UINT_PTR *params;
175 
176  switch (msgIn)
177  {
178  case WM_DDE_ACK:
179  case WM_DDE_ADVISE:
180  case WM_DDE_DATA:
181  case WM_DDE_POKE:
182  switch(msgOut)
183  {
184  case WM_DDE_ACK:
185  case WM_DDE_ADVISE:
186  case WM_DDE_DATA:
187  case WM_DDE_POKE:
188  if (!lParam) return 0;
189  if (!(params = GlobalLock( (HGLOBAL)lParam )))
190  {
191  ERR("GlobalLock failed\n");
192  return 0;
193  }
194  params[0] = uiLo;
195  params[1] = uiHi;
196  TRACE("Reusing pack %08lx %08lx\n", uiLo, uiHi);
198  return lParam;
199 
200  case WM_DDE_EXECUTE:
201  FreeDDElParam( msgIn, lParam );
202  return uiHi;
203 
204  default:
205  FreeDDElParam( msgIn, lParam );
206  return MAKELPARAM(uiLo, uiHi);
207  }
208 
209  default:
210  return PackDDElParam( msgOut, uiLo, uiHi );
211  }
212 }
213 
214 /*****************************************************************
215  * ImpersonateDdeClientWindow (USER32.@)
216  *
217  * PARAMS
218  * hWndClient [I] handle to DDE client window
219  * hWndServer [I] handle to DDE server window
220  */
222 {
223  FIXME("(%p %p): stub\n", hWndClient, hWndServer);
224  return FALSE;
225 }
226 
227 /*****************************************************************
228  * DdeSetQualityOfService (USER32.@)
229  */
230 
233 {
234  FIXME("(%p %p %p): stub\n", hwndClient, pqosNew, pqosPrev);
235  return TRUE;
236 }
237 
238 /* ================================================================
239  *
240  * WDML Error management
241  *
242  * ================================================================ */
243 
244 /******************************************************************************
245  * DdeGetLastError [USER32.@] Gets most recent error code
246  *
247  * PARAMS
248  * idInst [I] Instance identifier
249  *
250  * RETURNS
251  * Last error code
252  */
254 {
256  WDML_INSTANCE* pInstance;
257 
258  /* First check instance
259  */
260  pInstance = WDML_GetInstance(idInst);
261  if (pInstance == NULL)
262  {
264  }
265  else
266  {
267  error_code = pInstance->lastError;
268  pInstance->lastError = 0;
269  }
270 
271  return error_code;
272 }
273 
274 /******************************************************************
275  * WDML_SetAllLastError
276  *
277  *
278  */
279 static void WDML_SetAllLastError(DWORD lastError)
280 {
281  DWORD threadID;
282  WDML_INSTANCE* pInstance;
283  threadID = GetCurrentThreadId();
284  pInstance = WDML_InstanceList;
285  while (pInstance)
286  {
287  if (pInstance->threadID == threadID)
288  pInstance->lastError = lastError;
289  pInstance = pInstance->next;
290  }
291 }
292 
293 /* ================================================================
294  *
295  * String management
296  *
297  * ================================================================ */
298 
299 
300 /******************************************************************
301  * WDML_FindNode
302  *
303  *
304  */
305 static HSZNode* WDML_FindNode(WDML_INSTANCE* pInstance, HSZ hsz)
306 {
307  HSZNode* pNode;
308 
309  if (pInstance == NULL) return NULL;
310 
311  for (pNode = pInstance->nodeList; pNode != NULL; pNode = pNode->next)
312  {
313  if (pNode->hsz == hsz) break;
314  }
315  if (!pNode) WARN("HSZ %p not found\n", hsz);
316  return pNode;
317 }
318 
319 /******************************************************************
320  * WDML_MakeAtomFromHsz
321  *
322  * Creates a global atom from an existing HSZ
323  * Generally used before sending an HSZ as an atom to a remote app
324  */
326 {
327  WCHAR nameBuffer[MAX_BUFFER_LEN];
328 
329  if (GetAtomNameW(HSZ2ATOM(hsz), nameBuffer, MAX_BUFFER_LEN))
330  return GlobalAddAtomW(nameBuffer);
331  WARN("HSZ %p not found\n", hsz);
332  return 0;
333 }
334 
335 /******************************************************************
336  * WDML_MakeHszFromAtom
337  *
338  * Creates a HSZ from an existing global atom
339  * Generally used while receiving a global atom and transforming it
340  * into an HSZ
341  */
342 HSZ WDML_MakeHszFromAtom(const WDML_INSTANCE* pInstance, ATOM atom)
343 {
344  WCHAR nameBuffer[MAX_BUFFER_LEN];
345 
346  if (!atom) return NULL;
347 
348  if (GlobalGetAtomNameW(atom, nameBuffer, MAX_BUFFER_LEN))
349  {
350  TRACE("%x => %s\n", atom, debugstr_w(nameBuffer));
351  return DdeCreateStringHandleW(pInstance->instanceID, nameBuffer, CP_WINUNICODE);
352  }
353  WARN("ATOM 0x%x not found\n", atom);
354  return 0;
355 }
356 
357 /******************************************************************
358  * WDML_IncHSZ
359  *
360  *
361  */
362 BOOL WDML_IncHSZ(WDML_INSTANCE* pInstance, HSZ hsz)
363 {
364  HSZNode* pNode;
365 
366  pNode = WDML_FindNode(pInstance, hsz);
367  if (!pNode) return FALSE;
368 
369  pNode->refCount++;
370  return TRUE;
371 }
372 
373 /******************************************************************************
374  * WDML_DecHSZ (INTERNAL)
375  *
376  * Decrease the ref count of an HSZ. If it reaches 0, the node is removed from the list
377  * of HSZ nodes
378  * Returns -1 is the HSZ isn't found, otherwise it's the current (after --) of the ref count
379  */
380 BOOL WDML_DecHSZ(WDML_INSTANCE* pInstance, HSZ hsz)
381 {
382  HSZNode* pPrev = NULL;
383  HSZNode* pCurrent;
384 
385  for (pCurrent = pInstance->nodeList; pCurrent != NULL; pCurrent = (pPrev = pCurrent)->next)
386  {
387  /* If we found the node we were looking for and its ref count is one,
388  * we can remove it
389  */
390  if (pCurrent->hsz == hsz)
391  {
392  if (--pCurrent->refCount == 0)
393  {
394  if (pCurrent == pInstance->nodeList)
395  {
396  pInstance->nodeList = pCurrent->next;
397  }
398  else
399  {
400  pPrev->next = pCurrent->next;
401  }
402  HeapFree(GetProcessHeap(), 0, pCurrent);
403  DeleteAtom(HSZ2ATOM(hsz));
404  }
405  return TRUE;
406  }
407  }
408  WARN("HSZ %p not found\n", hsz);
409 
410  return FALSE;
411 }
412 
413 /******************************************************************************
414  * WDML_FreeAllHSZ (INTERNAL)
415  *
416  * Frees up all the strings still allocated in the list and
417  * remove all the nodes from the list of HSZ nodes.
418  */
419 static void WDML_FreeAllHSZ(WDML_INSTANCE* pInstance)
420 {
421  /* Free any strings created in this instance.
422  */
423  while (pInstance->nodeList != NULL)
424  {
425  DdeFreeStringHandle(pInstance->instanceID, pInstance->nodeList->hsz);
426  }
427 }
428 
429 /******************************************************************************
430  * InsertHSZNode (INTERNAL)
431  *
432  * Insert a node to the head of the list.
433  */
434 static void WDML_InsertHSZNode(WDML_INSTANCE* pInstance, HSZ hsz)
435 {
436  if (hsz != 0)
437  {
438  HSZNode* pNew = NULL;
439  /* Create a new node for this HSZ.
440  */
441  pNew = HeapAlloc(GetProcessHeap(), 0, sizeof(HSZNode));
442  if (pNew != NULL)
443  {
444  pNew->hsz = hsz;
445  pNew->next = pInstance->nodeList;
446  pNew->refCount = 1;
447  pInstance->nodeList = pNew;
448  }
449  else
450  {
451  ERR("Primary HSZ Node allocation failed - out of memory\n");
452  }
453  }
454 }
455 
456 /******************************************************************
457  * WDML_QueryString
458  *
459  *
460  */
461 static int WDML_QueryString(WDML_INSTANCE* pInstance, HSZ hsz, LPVOID ptr, DWORD cchMax,
462  int codepage)
463 {
464  WCHAR pString[MAX_BUFFER_LEN];
465  int ret;
466  /* If psz is null, we have to return only the length
467  * of the string.
468  */
469  if (ptr == NULL)
470  {
471  ptr = pString;
473  }
474 
475  /* if there is no input windows returns a NULL string */
476  if (hsz == NULL)
477  {
478  CHAR *t_ptr = ptr;
479  *t_ptr = '\0';
480  return 1;
481  }
482 
483  switch (codepage)
484  {
485  case CP_WINANSI:
486  ret = GetAtomNameA(HSZ2ATOM(hsz), ptr, cchMax);
487  break;
488  case CP_WINUNICODE:
489  ret = GetAtomNameW(HSZ2ATOM(hsz), ptr, cchMax);
490  break;
491  default:
492  ERR("Unknown code page %d\n", codepage);
493  ret = 0;
494  }
495  return ret;
496 }
497 
498 /*****************************************************************
499  * DdeQueryStringA [USER32.@]
500  */
501 DWORD WINAPI DdeQueryStringA(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, INT iCodePage)
502 {
503  DWORD ret = 0;
504  WDML_INSTANCE* pInstance;
505 
506  TRACE("(%d, %p, %p, %d, %d)\n", idInst, hsz, psz, cchMax, iCodePage);
507 
508  /* First check instance
509  */
510  pInstance = WDML_GetInstance(idInst);
511  if (pInstance != NULL)
512  {
513  if (iCodePage == 0) iCodePage = CP_WINANSI;
514  ret = WDML_QueryString(pInstance, hsz, psz, cchMax, iCodePage);
515  }
516 
517  TRACE("returning %d (%s)\n", ret, debugstr_a(psz));
518  return ret;
519 }
520 
521 /*****************************************************************
522  * DdeQueryStringW [USER32.@]
523  */
524 
525 DWORD WINAPI DdeQueryStringW(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, INT iCodePage)
526 {
527  DWORD ret = 0;
528  WDML_INSTANCE* pInstance;
529 
530  TRACE("(%d, %p, %p, %d, %d)\n", idInst, hsz, psz, cchMax, iCodePage);
531 
532  /* First check instance
533  */
534  pInstance = WDML_GetInstance(idInst);
535  if (pInstance != NULL)
536  {
537  if (iCodePage == 0) iCodePage = CP_WINUNICODE;
538  ret = WDML_QueryString(pInstance, hsz, psz, cchMax, iCodePage);
539  }
540 
541  TRACE("returning %d (%s)\n", ret, debugstr_w(psz));
542  return ret;
543 }
544 
545 /******************************************************************
546  * DML_CreateString
547  *
548  *
549  */
550 static HSZ WDML_CreateString(WDML_INSTANCE* pInstance, LPCVOID ptr, int codepage)
551 {
552  HSZ hsz;
553 
554  switch (codepage)
555  {
556  case CP_WINANSI:
557  hsz = ATOM2HSZ(AddAtomA(ptr));
558  TRACE("added atom %s with HSZ %p,\n", debugstr_a(ptr), hsz);
559  break;
560  case CP_WINUNICODE:
561  hsz = ATOM2HSZ(AddAtomW(ptr));
562  TRACE("added atom %s with HSZ %p,\n", debugstr_w(ptr), hsz);
563  break;
564  default:
565  ERR("Unknown code page %d\n", codepage);
566  return 0;
567  }
568  WDML_InsertHSZNode(pInstance, hsz);
569  return hsz;
570 }
571 
572 /*****************************************************************
573  * DdeCreateStringHandleA [USER32.@]
574  *
575  * See DdeCreateStringHandleW.
576  */
578 {
579  HSZ hsz = 0;
580  WDML_INSTANCE* pInstance;
581 
582  TRACE("(%d,%s,%d)\n", idInst, debugstr_a(psz), codepage);
583 
584  pInstance = WDML_GetInstance(idInst);
585  if (pInstance == NULL)
587  else
588  {
589  if (codepage == 0) codepage = CP_WINANSI;
590  hsz = WDML_CreateString(pInstance, psz, codepage);
591  }
592 
593  return hsz;
594 }
595 
596 
597 /******************************************************************************
598  * DdeCreateStringHandleW [USER32.@] Creates handle to identify string
599  *
600  * PARAMS
601  * idInst [I] Instance identifier
602  * psz [I] Pointer to string
603  * codepage [I] Code page identifier
604  * RETURNS
605  * Success: String handle
606  * Failure: 0
607  */
609 {
610  WDML_INSTANCE* pInstance;
611  HSZ hsz = 0;
612 
613  pInstance = WDML_GetInstance(idInst);
614  if (pInstance == NULL)
616  else
617  {
618  if (codepage == 0) codepage = CP_WINUNICODE;
619  hsz = WDML_CreateString(pInstance, psz, codepage);
620  }
621 
622  return hsz;
623 }
624 
625 /*****************************************************************
626  * DdeFreeStringHandle (USER32.@)
627  * RETURNS
628  * success: nonzero
629  * fail: zero
630  */
632 {
633  WDML_INSTANCE* pInstance;
634  BOOL ret = FALSE;
635 
636  TRACE("(%d,%p):\n", idInst, hsz);
637 
638  /* First check instance
639  */
640  pInstance = WDML_GetInstance(idInst);
641  if (pInstance)
642  ret = WDML_DecHSZ(pInstance, hsz);
643 
644  return ret;
645 }
646 
647 /*****************************************************************
648  * DdeKeepStringHandle (USER32.@)
649  *
650  * RETURNS
651  * success: nonzero
652  * fail: zero
653  */
655 {
656  WDML_INSTANCE* pInstance;
657  BOOL ret = FALSE;
658 
659  TRACE("(%d,%p):\n", idInst, hsz);
660 
661  /* First check instance
662  */
663  pInstance = WDML_GetInstance(idInst);
664  if (pInstance)
665  ret = WDML_IncHSZ(pInstance, hsz);
666 
667  return ret;
668 }
669 
670 /*****************************************************************
671  * DdeCmpStringHandles (USER32.@)
672  *
673  * Compares the value of two string handles. This comparison is
674  * not case sensitive.
675  *
676  * PARAMS
677  * hsz1 [I] Handle to the first string
678  * hsz2 [I] Handle to the second string
679  *
680  * RETURNS
681  * -1 The value of hsz1 is zero or less than hsz2
682  * 0 The values of hsz 1 and 2 are the same or both zero.
683  * 1 The value of hsz2 is zero of less than hsz1
684  */
685 INT WINAPI DdeCmpStringHandles(HSZ hsz1, HSZ hsz2)
686 {
687  WCHAR psz1[MAX_BUFFER_LEN];
688  WCHAR psz2[MAX_BUFFER_LEN];
689  int ret = 0;
690  int ret1, ret2;
691 
692  ret1 = GetAtomNameW(HSZ2ATOM(hsz1), psz1, MAX_BUFFER_LEN);
693  ret2 = GetAtomNameW(HSZ2ATOM(hsz2), psz2, MAX_BUFFER_LEN);
694 
695  TRACE("(%p<%s> %p<%s>);\n", hsz1, debugstr_w(psz1), hsz2, debugstr_w(psz2));
696 
697  /* Make sure we found both strings. */
698  if (ret1 == 0 && ret2 == 0)
699  {
700  /* If both are not found, return both "zero strings". */
701  ret = 0;
702  }
703  else if (ret1 == 0)
704  {
705  /* If hsz1 is a not found, return hsz1 is "zero string". */
706  ret = -1;
707  }
708  else if (ret2 == 0)
709  {
710  /* If hsz2 is a not found, return hsz2 is "zero string". */
711  ret = 1;
712  }
713  else
714  {
715  /* Compare the two strings we got (case insensitive). */
716  ret = lstrcmpiW(psz1, psz2);
717  /* Since strcmp returns any number smaller than
718  * 0 when the first string is found to be less than
719  * the second one we must make sure we are returning
720  * the proper values.
721  */
722  if (ret < 0)
723  {
724  ret = -1;
725  }
726  else if (ret > 0)
727  {
728  ret = 1;
729  }
730  }
731 
732  return ret;
733 }
734 
735 /* ================================================================
736  *
737  * Instance management
738  *
739  * ================================================================ */
740 
741 /******************************************************************************
742  * IncrementInstanceId
743  *
744  * generic routine to increment the max instance Id and allocate a new application instance
745  */
747 {
749 
750  pInstance->instanceID = id;
751  TRACE("New instance id %d allocated\n", id);
752 }
753 
754 /******************************************************************
755  * WDML_EventProc
756  *
757  *
758  */
760 {
761  WDML_INSTANCE* pInstance;
762  HSZ hsz1, hsz2;
763 
764  switch (uMsg)
765  {
766  case WM_WDML_REGISTER:
767  pInstance = WDML_GetInstanceFromWnd(hwndEvent);
768  /* try calling the Callback */
769  if (pInstance && !(pInstance->CBFflags & CBF_SKIP_REGISTRATIONS))
770  {
771  hsz1 = WDML_MakeHszFromAtom(pInstance, wParam);
772  hsz2 = WDML_MakeHszFromAtom(pInstance, lParam);
773  WDML_InvokeCallback(pInstance, XTYP_REGISTER, 0, 0, hsz1, hsz2, 0, 0, 0);
774  WDML_DecHSZ(pInstance, hsz1);
775  WDML_DecHSZ(pInstance, hsz2);
776  }
777  break;
778 
779  case WM_WDML_UNREGISTER:
780  pInstance = WDML_GetInstanceFromWnd(hwndEvent);
781  if (pInstance && !(pInstance->CBFflags & CBF_SKIP_UNREGISTRATIONS))
782  {
783  hsz1 = WDML_MakeHszFromAtom(pInstance, wParam);
784  hsz2 = WDML_MakeHszFromAtom(pInstance, lParam);
785  WDML_InvokeCallback(pInstance, XTYP_UNREGISTER, 0, 0, hsz1, hsz2, 0, 0, 0);
786  WDML_DecHSZ(pInstance, hsz1);
787  WDML_DecHSZ(pInstance, hsz2);
788  }
789  break;
790 
792  pInstance = WDML_GetInstanceFromWnd(hwndEvent);
793  if (pInstance && !(pInstance->CBFflags & CBF_SKIP_CONNECT_CONFIRMS))
794  {
795  WDML_CONV* pConv;
796  /* confirm connection...
797  * lookup for this conv handle
798  */
801  for (pConv = pInstance->convs[WDML_SERVER_SIDE]; pConv != NULL; pConv = pConv->next)
802  {
803  if (pConv->hwndClient == client && pConv->hwndServer == server)
804  break;
805  }
806  if (pConv)
807  {
808  pConv->wStatus |= ST_ISLOCAL;
809 
810  WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv,
811  pConv->hszTopic, pConv->hszService, 0, 0,
812  (pConv->wStatus & ST_ISSELF) ? 1 : 0);
813  }
814  }
815  break;
816  default:
817  return DefWindowProcW(hwndEvent, uMsg, wParam, lParam);
818  }
819  return 0;
820 }
821 
822 /******************************************************************
823  * WDML_Initialize
824  *
825  *
826  */
827 static UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
828  DWORD afCmd, DWORD ulRes, BOOL bUnicode)
829 {
830  WDML_INSTANCE* pInstance;
831  WDML_INSTANCE* reference_inst;
832  UINT ret;
833  WNDCLASSEXW wndclass;
834 
835  TRACE("(%p,%p,0x%x,%d,0x%x)\n",
836  pidInst, pfnCallback, afCmd, ulRes, bUnicode);
837 
838  if (ulRes)
839  {
840  ERR("Reserved value not zero? What does this mean?\n");
841  /* trap this and no more until we know more */
842  return DMLERR_NO_ERROR;
843  }
844 
845  /* grab enough heap for one control struct - not really necessary for re-initialise
846  * but allows us to use same validation routines */
847  pInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_INSTANCE));
848  if (pInstance == NULL)
849  {
850  /* catastrophe !! warn user & abort */
851  ERR("Instance create failed - out of memory\n");
852  return DMLERR_SYS_ERROR;
853  }
854  pInstance->next = NULL;
855  pInstance->monitor = (afCmd | APPCLASS_MONITOR);
856 
857  /* messy bit, spec implies that 'Client Only' can be set in 2 different ways, catch 1 here */
858 
859  pInstance->clientOnly = afCmd & APPCMD_CLIENTONLY;
860  pInstance->instanceID = *pidInst; /* May need to add calling proc Id */
861  pInstance->threadID = GetCurrentThreadId();
862  pInstance->callback = *pfnCallback;
863  pInstance->unicode = bUnicode;
864  pInstance->nodeList = NULL; /* node will be added later */
865  pInstance->monitorFlags = afCmd & MF_MASK;
866  pInstance->wStatus = 0;
867  pInstance->lastError = DMLERR_NO_ERROR;
868  pInstance->servers = NULL;
869  pInstance->convs[0] = NULL;
870  pInstance->convs[1] = NULL;
871  pInstance->links[0] = NULL;
872  pInstance->links[1] = NULL;
873 
874  /* isolate CBF flags in one go, expect this will go the way of all attempts to be clever !! */
875 
876  pInstance->CBFflags = afCmd^((afCmd&MF_MASK)|((afCmd&APPCMD_MASK)|(afCmd&APPCLASS_MASK)));
877 
878  if (!pInstance->clientOnly)
879  {
880  /* Check for other way of setting Client-only !! */
881  pInstance->clientOnly =
883  }
884 
885  TRACE("instance created - checking validity\n");
886 
887  if (*pidInst == 0)
888  {
889  /* Initialisation of new Instance Identifier */
890  TRACE("new instance, callback %p flags %X\n",pfnCallback,afCmd);
891 
893 
894  if (WDML_InstanceList == NULL)
895  {
896  /* can't be another instance in this case, assign to the base pointer */
897  WDML_InstanceList = pInstance;
898 
899  /* since first must force filter of XTYP_CONNECT and XTYP_WILDCONNECT for
900  * present
901  * ------------------------------- NOTE NOTE NOTE --------------------------
902  *
903  * the manual is not clear if this condition
904  * applies to the first call to DdeInitialize from an application, or the
905  * first call for a given callback !!!
906  */
907 
908  pInstance->CBFflags = pInstance->CBFflags|APPCMD_FILTERINITS;
909  TRACE("First application instance detected OK\n");
910  /* allocate new instance ID */
911  WDML_IncrementInstanceId(pInstance);
912  }
913  else
914  {
915  /* really need to chain the new one in to the latest here, but after checking conditions
916  * such as trying to start a conversation from an application trying to monitor */
917  reference_inst = WDML_InstanceList;
918  TRACE("Subsequent application instance - starting checks\n");
919  while (reference_inst->next != NULL)
920  {
921  /*
922  * This set of tests will work if application uses same instance Id
923  * at application level once allocated - which is what manual implies
924  * should happen. If someone tries to be
925  * clever (lazy ?) it will fail to pick up that later calls are for
926  * the same application - should we trust them ?
927  */
928  if (pInstance->instanceID == reference_inst->instanceID)
929  {
930  /* Check 1 - must be same Client-only state */
931 
932  if (pInstance->clientOnly != reference_inst->clientOnly)
933  {
935  goto theError;
936  }
937 
938  /* Check 2 - cannot use 'Monitor' with any non-monitor modes */
939 
940  if (pInstance->monitor != reference_inst->monitor)
941  {
943  goto theError;
944  }
945 
946  /* Check 3 - must supply different callback address */
947 
948  if (pInstance->callback == reference_inst->callback)
949  {
951  goto theError;
952  }
953  }
954  reference_inst = reference_inst->next;
955  }
956  /* All cleared, add to chain */
957 
958  TRACE("Application Instance checks finished\n");
959  WDML_IncrementInstanceId(pInstance);
960  reference_inst->next = pInstance;
961  }
963 
964  *pidInst = pInstance->instanceID;
965 
966  /* for deadlock issues, windows must always be created when outside the critical section */
967  wndclass.cbSize = sizeof(wndclass);
968  wndclass.style = 0;
969  wndclass.lpfnWndProc = WDML_EventProc;
970  wndclass.cbClsExtra = 0;
971  wndclass.cbWndExtra = sizeof(ULONG_PTR);
972  wndclass.hInstance = 0;
973  wndclass.hIcon = 0;
974  wndclass.hCursor = 0;
975  wndclass.hbrBackground = 0;
976  wndclass.lpszMenuName = NULL;
977  wndclass.lpszClassName = WDML_szEventClass;
978  wndclass.hIconSm = 0;
979 
980  RegisterClassExW(&wndclass);
981 
983  WS_POPUP, 0, 0, 0, 0,
984  0, 0, 0, 0);
985 
986  SetWindowLongPtrW(pInstance->hwndEvent, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance);
987 
988  TRACE("New application instance processing finished OK\n");
989  }
990  else
991  {
992  /* Reinitialisation situation --- FIX */
993  TRACE("reinitialisation of (%p,%p,0x%x,%d): stub\n", pidInst, pfnCallback, afCmd, ulRes);
994 
996 
997  if (WDML_InstanceList == NULL)
998  {
1000  goto theError;
1001  }
1002  /* can't reinitialise if we have initialised nothing !! */
1003  reference_inst = WDML_InstanceList;
1004  /* must first check if we have been given a valid instance to re-initialise !! how do we do that ? */
1005  /*
1006  * MS allows initialisation without specifying a callback, should we allow addition of the
1007  * callback by a later call to initialise ? - if so this lot will have to change
1008  */
1009  while (reference_inst->next != NULL)
1010  {
1011  if (*pidInst == reference_inst->instanceID && pfnCallback == reference_inst->callback)
1012  {
1013  /* Check 1 - cannot change client-only mode if set via APPCMD_CLIENTONLY */
1014 
1015  if (reference_inst->clientOnly)
1016  {
1017  if ((reference_inst->CBFflags & CBF_FAIL_ALLSVRXACTIONS) != CBF_FAIL_ALLSVRXACTIONS)
1018  {
1019  /* i.e. Was set to Client-only and through APPCMD_CLIENTONLY */
1020 
1021  if (!(afCmd & APPCMD_CLIENTONLY))
1022  {
1024  goto theError;
1025  }
1026  }
1027  }
1028  /* Check 2 - cannot change monitor modes */
1029 
1030  if (pInstance->monitor != reference_inst->monitor)
1031  {
1033  goto theError;
1034  }
1035 
1036  /* Check 3 - trying to set Client-only via APPCMD when not set so previously */
1037 
1038  if ((afCmd&APPCMD_CLIENTONLY) && !reference_inst->clientOnly)
1039  {
1041  goto theError;
1042  }
1043  break;
1044  }
1045  reference_inst = reference_inst->next;
1046  }
1047  if (reference_inst->next == NULL)
1048  {
1050  goto theError;
1051  }
1052  /* All checked - change relevant flags */
1053 
1054  reference_inst->CBFflags = pInstance->CBFflags;
1055  reference_inst->clientOnly = pInstance->clientOnly;
1056  reference_inst->monitorFlags = pInstance->monitorFlags;
1057 
1058  HeapFree(GetProcessHeap(), 0, pInstance); /* finished - release heap space used as work store */
1059 
1061  }
1062 
1063  return DMLERR_NO_ERROR;
1064  theError:
1065  HeapFree(GetProcessHeap(), 0, pInstance);
1067  return ret;
1068 }
1069 
1070 /******************************************************************************
1071  * DdeInitializeA (USER32.@)
1072  *
1073  * See DdeInitializeW.
1074  */
1076  DWORD afCmd, DWORD ulRes)
1077 {
1078  return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, FALSE);
1079 }
1080 
1081 /******************************************************************************
1082  * DdeInitializeW [USER32.@]
1083  * Registers an application with the DDEML
1084  *
1085  * PARAMS
1086  * pidInst [I] Pointer to instance identifier
1087  * pfnCallback [I] Pointer to callback function
1088  * afCmd [I] Set of command and filter flags
1089  * ulRes [I] Reserved
1090  *
1091  * RETURNS
1092  * Success: DMLERR_NO_ERROR
1093  * Failure: DMLERR_DLL_USAGE, DMLERR_INVALIDPARAMETER, DMLERR_SYS_ERROR
1094  */
1096  DWORD afCmd, DWORD ulRes)
1097 {
1098  return WDML_Initialize(pidInst, pfnCallback, afCmd, ulRes, TRUE);
1099 }
1100 
1101 /*****************************************************************
1102  * DdeUninitialize [USER32.@] Frees DDEML resources
1103  *
1104  * PARAMS
1105  * idInst [I] Instance identifier
1106  *
1107  * RETURNS
1108  * Success: TRUE
1109  * Failure: FALSE
1110  */
1111 
1113 {
1114  /* Stage one - check if we have a handle for this instance
1115  */
1116  WDML_INSTANCE* pInstance;
1117  WDML_CONV* pConv;
1118  WDML_CONV* pConvNext;
1119 
1120  TRACE("(%d)\n", idInst);
1121 
1122  /* First check instance
1123  */
1124  pInstance = WDML_GetInstance(idInst);
1125  if (pInstance == NULL)
1126  {
1127  /*
1128  * Needs something here to record NOT_INITIALIZED ready for DdeGetLastError
1129  */
1130  return FALSE;
1131  }
1132 
1133  /* first terminate all conversations client side
1134  * this shall close existing links...
1135  */
1136  for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv != NULL; pConv = pConvNext)
1137  {
1138  pConvNext = pConv->next;
1139  DdeDisconnect((HCONV)pConv);
1140  }
1141  if (pInstance->convs[WDML_CLIENT_SIDE])
1142  FIXME("still pending conversations\n");
1143 
1144  /* then unregister all known service names */
1145  DdeNameService(idInst, 0, 0, DNS_UNREGISTER);
1146 
1147  /* Free the nodes that were not freed by this instance
1148  * and remove the nodes from the list of HSZ nodes.
1149  */
1150  WDML_FreeAllHSZ(pInstance);
1151 
1152  DestroyWindow(pInstance->hwndEvent);
1153 
1154  /* OK now delete the instance handle itself */
1155 
1156  if (WDML_InstanceList == pInstance)
1157  {
1158  /* special case - the first/only entry */
1159  WDML_InstanceList = pInstance->next;
1160  }
1161  else
1162  {
1163  /* general case, remove entry */
1164  WDML_INSTANCE* inst;
1165 
1166  for (inst = WDML_InstanceList; inst->next != pInstance; inst = inst->next);
1167  inst->next = pInstance->next;
1168  }
1169  /* release the heap entry
1170  */
1171  HeapFree(GetProcessHeap(), 0, pInstance);
1172 
1173  return TRUE;
1174 }
1175 
1176 /******************************************************************
1177  * WDML_NotifyThreadExit
1178  *
1179  *
1180  */
1182 {
1183  WDML_INSTANCE* pInstance;
1186 
1188  for (pInstance = WDML_InstanceList; pInstance != NULL; pInstance = next)
1189  {
1190  next = pInstance->next;
1191  if (pInstance->threadID == tid)
1192  {
1194  DdeUninitialize(pInstance->instanceID);
1196  }
1197  }
1199 }
1200 
1201 /******************************************************************
1202  * WDML_InvokeCallback
1203  *
1204  *
1205  */
1206 HDDEDATA WDML_InvokeCallback(WDML_INSTANCE* pInstance, UINT uType, UINT uFmt, HCONV hConv,
1207  HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
1208  ULONG_PTR dwData1, ULONG_PTR dwData2)
1209 {
1210  HDDEDATA ret;
1211 
1212  if (pInstance == NULL)
1213  return NULL;
1214 
1215  TRACE("invoking CB[%p] (%x %x %p %p %p %p %lx %lx)\n",
1216  pInstance->callback, uType, uFmt,
1217  hConv, hsz1, hsz2, hdata, dwData1, dwData2);
1218  ret = pInstance->callback(uType, uFmt, hConv, hsz1, hsz2, hdata, dwData1, dwData2);
1219  TRACE("done => %p\n", ret);
1220  return ret;
1221 }
1222 
1223 /*****************************************************************************
1224  * WDML_GetInstance
1225  *
1226  * generic routine to return a pointer to the relevant DDE_HANDLE_ENTRY
1227  * for an instance Id, or NULL if the entry does not exist
1228  *
1229  */
1231 {
1232  WDML_INSTANCE* pInstance;
1233 
1235 
1236  for (pInstance = WDML_InstanceList; pInstance != NULL; pInstance = pInstance->next)
1237  {
1238  if (pInstance->instanceID == instId)
1239  {
1240  if (GetCurrentThreadId() != pInstance->threadID)
1241  {
1242  FIXME("Tried to get instance from wrong thread\n");
1243  continue;
1244  }
1245  break;
1246  }
1247  }
1248 
1250 
1251  if (!pInstance)
1252  WARN("Instance entry missing for id %04x\n", instId);
1253  return pInstance;
1254 }
1255 
1256 /******************************************************************
1257  * WDML_GetInstanceFromWnd
1258  *
1259  *
1260  */
1262 {
1264 }
1265 
1266 /* ================================================================
1267  *
1268  * Data handle management
1269  *
1270  * ================================================================ */
1271 
1272 /*****************************************************************
1273  * DdeCreateDataHandle (USER32.@)
1274  */
1275 HDDEDATA WINAPI DdeCreateDataHandle(DWORD idInst, LPBYTE pSrc, DWORD cb, DWORD cbOff,
1276  HSZ hszItem, UINT wFmt, UINT afCmd)
1277 {
1278 
1279  /* Other than check for validity we will ignore for now idInst, hszItem.
1280  * The purpose of these arguments still need to be investigated.
1281  */
1282 
1283  WDML_INSTANCE* pInstance;
1284  HGLOBAL hMem;
1285  LPBYTE pByte;
1286  DDE_DATAHANDLE_HEAD* pDdh;
1287  WCHAR psz[MAX_BUFFER_LEN];
1288 
1289  pInstance = WDML_GetInstance(idInst);
1290  if (pInstance == NULL)
1291  {
1293  return NULL;
1294  }
1295 
1296  if (!GetAtomNameW(HSZ2ATOM(hszItem), psz, MAX_BUFFER_LEN))
1297  {
1298  psz[0] = HSZ2ATOM(hszItem);
1299  psz[1] = 0;
1300  }
1301 
1302  TRACE("(%d,%p,cb %d, cbOff %d,%p <%s>,fmt %04x,%x)\n",
1303  idInst, pSrc, cb, cbOff, hszItem, debugstr_w(psz), wFmt, afCmd);
1304 
1305  if (afCmd != 0 && afCmd != HDATA_APPOWNED)
1306  return 0;
1307 
1308  /* we use the first 4 bytes to store the size */
1309  if (!(hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cb + cbOff + sizeof(DDE_DATAHANDLE_HEAD))))
1310  {
1311  ERR("GlobalAlloc failed\n");
1312  return 0;
1313  }
1314 
1315  pDdh = GlobalLock(hMem);
1316  if (!pDdh)
1317  {
1318  GlobalFree(hMem);
1319  return 0;
1320  }
1321 
1322  pDdh->cfFormat = wFmt;
1323  pDdh->bAppOwned = (afCmd == HDATA_APPOWNED);
1324 
1325  pByte = (LPBYTE)(pDdh + 1);
1326  if (pSrc)
1327  {
1328  memcpy(pByte, pSrc + cbOff, cb);
1329  }
1330  GlobalUnlock(hMem);
1331 
1332  TRACE("=> %p\n", hMem);
1333  return hMem;
1334 }
1335 
1336 /*****************************************************************
1337  *
1338  * DdeAddData (USER32.@)
1339  */
1340 HDDEDATA WINAPI DdeAddData(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
1341 {
1342  DWORD old_sz, new_sz;
1343  LPBYTE pDst;
1344 
1345  TRACE("(%p,%p,cb %d, cbOff %d)\n", hData, pSrc, cb, cbOff);
1346 
1347  pDst = DdeAccessData(hData, &old_sz);
1348  if (!pDst) return 0;
1349 
1350  new_sz = cb + cbOff;
1351  if (new_sz > old_sz)
1352  {
1353  DdeUnaccessData(hData);
1354  hData = GlobalReAlloc(hData, new_sz + sizeof(DDE_DATAHANDLE_HEAD),
1356  pDst = DdeAccessData(hData, &old_sz);
1357  }
1358 
1359  if (!pDst) return 0;
1360 
1361  memcpy(pDst + cbOff, pSrc, cb);
1362  DdeUnaccessData(hData);
1363  return hData;
1364 }
1365 
1366 /******************************************************************************
1367  * DdeGetData [USER32.@] Copies data from DDE object to local buffer
1368  *
1369  *
1370  * PARAMS
1371  * hData [I] Handle to DDE object
1372  * pDst [I] Pointer to destination buffer
1373  * cbMax [I] Amount of data to copy
1374  * cbOff [I] Offset to beginning of data
1375  *
1376  * RETURNS
1377  * Size of memory object associated with handle
1378  */
1379 DWORD WINAPI DdeGetData(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
1380 {
1381  DWORD dwSize, dwRet;
1382  LPBYTE pByte;
1383 
1384  TRACE("(%p,%p,%d,%d)\n", hData, pDst, cbMax, cbOff);
1385 
1386  pByte = DdeAccessData(hData, &dwSize);
1387 
1388  if (pByte)
1389  {
1390  if (!pDst)
1391  {
1392  dwRet = dwSize;
1393  }
1394  else if (cbOff + cbMax < dwSize)
1395  {
1396  dwRet = cbMax;
1397  }
1398  else if (cbOff < dwSize)
1399  {
1400  dwRet = dwSize - cbOff;
1401  }
1402  else
1403  {
1404  dwRet = 0;
1405  }
1406  if (pDst && dwRet != 0)
1407  {
1408  memcpy(pDst, pByte + cbOff, dwRet);
1409  }
1410  DdeUnaccessData(hData);
1411  }
1412  else
1413  {
1414  dwRet = 0;
1415  }
1416  return dwRet;
1417 }
1418 
1419 /*****************************************************************
1420  * DdeAccessData (USER32.@)
1421  */
1422 LPBYTE WINAPI DdeAccessData(HDDEDATA hData, LPDWORD pcbDataSize)
1423 {
1424  HGLOBAL hMem = hData;
1425  DDE_DATAHANDLE_HEAD* pDdh;
1426 
1427  TRACE("(%p,%p)\n", hData, pcbDataSize);
1428 
1429  pDdh = GlobalLock(hMem);
1430  if (pDdh == NULL)
1431  {
1432  ERR("Failed on GlobalLock(%p)\n", hMem);
1433  return 0;
1434  }
1435 
1436  if (pcbDataSize != NULL)
1437  {
1438  *pcbDataSize = GlobalSize(hMem) - sizeof(DDE_DATAHANDLE_HEAD);
1439  }
1440  TRACE("=> %p (%lu) fmt %04x\n", pDdh + 1, GlobalSize(hMem) - sizeof(DDE_DATAHANDLE_HEAD), pDdh->cfFormat);
1441  return (LPBYTE)(pDdh + 1);
1442 }
1443 
1444 /*****************************************************************
1445  * DdeUnaccessData (USER32.@)
1446  */
1447 BOOL WINAPI DdeUnaccessData(HDDEDATA hData)
1448 {
1449  HGLOBAL hMem = hData;
1450 
1451  TRACE("(%p)\n", hData);
1452 
1453  GlobalUnlock(hMem);
1454 
1455  return TRUE;
1456 }
1457 
1458 /*****************************************************************
1459  * DdeFreeDataHandle (USER32.@)
1460  */
1462 {
1463  TRACE("(%p)\n", hData);
1464 
1465  /* 1 is the handle value returned by an asynchronous operation. */
1466  if (hData == (HDDEDATA)1)
1467  return TRUE;
1468 
1469  return GlobalFree(hData) == 0;
1470 }
1471 
1472 /******************************************************************
1473  * WDML_IsAppOwned
1474  *
1475  *
1476  */
1477 BOOL WDML_IsAppOwned(HDDEDATA hData)
1478 {
1479  DDE_DATAHANDLE_HEAD* pDdh;
1480  BOOL ret = FALSE;
1481 
1482  pDdh = GlobalLock(hData);
1483  if (pDdh != NULL)
1484  {
1485  ret = pDdh->bAppOwned;
1486  GlobalUnlock(hData);
1487  }
1488  return ret;
1489 }
1490 
1491 /* ================================================================
1492  *
1493  * Global <=> Data handle management
1494  *
1495  * ================================================================ */
1496 
1497 /* Note: we use a DDEDATA, but layout of DDEDATA, DDEADVISE and DDEPOKE structures is similar:
1498  * offset size
1499  * (bytes) (bits) comment
1500  * 0 16 bit fields for options (release, ackreq, response...)
1501  * 2 16 clipboard format
1502  * 4 ? data to be used
1503  */
1505 {
1506  DDEDATA* pDd;
1507  HDDEDATA ret = 0;
1508  DWORD size;
1509 
1510  if (hMem)
1511  {
1512  pDd = GlobalLock(hMem);
1513  size = GlobalSize(hMem) - sizeof(WINE_DDEHEAD);
1514  if (pDd)
1515  {
1516  if (p) memcpy(p, pDd, sizeof(WINE_DDEHEAD));
1517  switch (pDd->cfFormat)
1518  {
1519  default:
1520  FIXME("Unsupported format (%04x) for data %p, passing raw information\n",
1521  pDd->cfFormat, hMem);
1522  /* fall through */
1523  case 0:
1524  case CF_TEXT:
1525  ret = DdeCreateDataHandle(pConv->instance->instanceID, pDd->Value, size, 0, 0, pDd->cfFormat, 0);
1526  break;
1527  case CF_BITMAP:
1528  if (size >= sizeof(BITMAP))
1529  {
1530  BITMAP* bmp = (BITMAP*)pDd->Value;
1531  int count = bmp->bmWidthBytes * bmp->bmHeight * bmp->bmPlanes;
1532  if (size >= sizeof(BITMAP) + count)
1533  {
1534  HBITMAP hbmp;
1535 
1536  if ((hbmp = CreateBitmap(bmp->bmWidth, bmp->bmHeight,
1537  bmp->bmPlanes, bmp->bmBitsPixel,
1538  pDd->Value + sizeof(BITMAP))))
1539  {
1540  ret = DdeCreateDataHandle(pConv->instance->instanceID, (LPBYTE)&hbmp, sizeof(hbmp),
1541  0, 0, CF_BITMAP, 0);
1542  }
1543  else ERR("Can't create bmp\n");
1544  }
1545  else
1546  {
1547  ERR("Wrong count: %u / %d\n", size, count);
1548  }
1549  } else ERR("No bitmap header\n");
1550  break;
1551  }
1552  GlobalUnlock(hMem);
1553  }
1554  }
1555  return ret;
1556 }
1557 
1558 /******************************************************************
1559  * WDML_DataHandle2Global
1560  *
1561  *
1562  */
1563 HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease,
1564  BOOL fDeferUpd, BOOL fAckReq)
1565 {
1566  DDE_DATAHANDLE_HEAD* pDdh;
1567  DWORD dwSize;
1568  HGLOBAL hMem = 0;
1569 
1570  dwSize = GlobalSize(hDdeData) - sizeof(DDE_DATAHANDLE_HEAD);
1571  pDdh = GlobalLock(hDdeData);
1572  if (dwSize && pDdh)
1573  {
1574  WINE_DDEHEAD* wdh = NULL;
1575 
1576  switch (pDdh->cfFormat)
1577  {
1578  default:
1579  FIXME("Unsupported format (%04x) for data %p, passing raw information\n",
1580  pDdh->cfFormat, hDdeData);
1581  /* fall through */
1582  case 0:
1583  case CF_TEXT:
1585  if (hMem && (wdh = GlobalLock(hMem)))
1586  {
1587  memcpy(wdh + 1, pDdh + 1, dwSize);
1588  }
1589  break;
1590  case CF_BITMAP:
1591  if (dwSize >= sizeof(HBITMAP))
1592  {
1593  BITMAP bmp;
1594  DWORD count;
1595  HBITMAP hbmp = *(HBITMAP*)(pDdh + 1);
1596 
1597  if (GetObjectW(hbmp, sizeof(bmp), &bmp))
1598  {
1599  count = bmp.bmWidthBytes * bmp.bmHeight;
1601  sizeof(WINE_DDEHEAD) + sizeof(bmp) + count);
1602  if (hMem && (wdh = GlobalLock(hMem)))
1603  {
1604  memcpy(wdh + 1, &bmp, sizeof(bmp));
1605  GetBitmapBits(hbmp, count, ((char*)(wdh + 1)) + sizeof(bmp));
1606  }
1607  }
1608  }
1609  break;
1610  }
1611  if (wdh)
1612  {
1613  wdh->unused = 0;
1614  wdh->fResponse = fResponse;
1615  wdh->fRelease = fRelease;
1616  wdh->fDeferUpd = fDeferUpd;
1617  wdh->fAckReq = fAckReq;
1618  wdh->cfFormat = pDdh->cfFormat;
1619  GlobalUnlock(hMem);
1620  }
1621  GlobalUnlock(hDdeData);
1622  }
1623 
1624  return hMem;
1625 }
1626 
1627 /* ================================================================
1628  *
1629  * Server management
1630  *
1631  * ================================================================ */
1632 
1633 /******************************************************************
1634  * WDML_AddServer
1635  *
1636  *
1637  */
1638 WDML_SERVER* WDML_AddServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic)
1639 {
1640  static const WCHAR fmtW[] = {'%','s','(','0','x','%','*','x',')',0};
1641  WDML_SERVER* pServer;
1642  WCHAR buf1[256];
1643  WCHAR buf2[256];
1644 
1645  pServer = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_SERVER));
1646  if (pServer == NULL) return NULL;
1647 
1648  pServer->hszService = hszService;
1649  WDML_IncHSZ(pInstance, hszService);
1650 
1651  DdeQueryStringW(pInstance->instanceID, hszService, buf1, 256, CP_WINUNICODE);
1652  snprintfW(buf2, 256, fmtW, buf1, 2*sizeof(ULONG_PTR), GetCurrentProcessId());
1653  pServer->hszServiceSpec = DdeCreateStringHandleW(pInstance->instanceID, buf2, CP_WINUNICODE);
1654 
1655  pServer->atomService = WDML_MakeAtomFromHsz(pServer->hszService);
1657 
1658  pServer->filterOn = TRUE;
1659 
1660  pServer->next = pInstance->servers;
1661  pInstance->servers = pServer;
1662  return pServer;
1663 }
1664 
1665 /******************************************************************
1666  * WDML_RemoveServer
1667  *
1668  *
1669  */
1670 void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic)
1671 {
1672  WDML_SERVER* pPrev = NULL;
1673  WDML_SERVER* pServer = NULL;
1674  WDML_CONV* pConv;
1675  WDML_CONV* pConvNext;
1676 
1677  pServer = pInstance->servers;
1678 
1679  while (pServer != NULL)
1680  {
1681  if (DdeCmpStringHandles(pServer->hszService, hszService) == 0)
1682  {
1684  pServer->atomService, pServer->atomServiceSpec);
1685  /* terminate all conversations for given topic */
1686  for (pConv = pInstance->convs[WDML_SERVER_SIDE]; pConv != NULL; pConv = pConvNext)
1687  {
1688  pConvNext = pConv->next;
1689  if (DdeCmpStringHandles(pConv->hszService, hszService) == 0)
1690  {
1691  HWND client = pConv->hwndClient, server = pConv->hwndServer;
1693  /* don't care about return code (whether client window is present or not) */
1695  }
1696  }
1697  if (pServer == pInstance->servers)
1698  {
1699  pInstance->servers = pServer->next;
1700  }
1701  else
1702  {
1703  pPrev->next = pServer->next;
1704  }
1705 
1706  DestroyWindow(pServer->hwndServer);
1707  WDML_DecHSZ(pInstance, pServer->hszServiceSpec);
1708  WDML_DecHSZ(pInstance, pServer->hszService);
1709 
1710  GlobalDeleteAtom(pServer->atomService);
1712 
1713  HeapFree(GetProcessHeap(), 0, pServer);
1714  break;
1715  }
1716 
1717  pPrev = pServer;
1718  pServer = pServer->next;
1719  }
1720 }
1721 
1722 /*****************************************************************************
1723  * WDML_FindServer
1724  *
1725  * generic routine to return a pointer to the relevant ServiceNode
1726  * for a given service name, or NULL if the entry does not exist
1727  *
1728  */
1729 WDML_SERVER* WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic)
1730 {
1731  WDML_SERVER* pServer;
1732 
1733  for (pServer = pInstance->servers; pServer != NULL; pServer = pServer->next)
1734  {
1735  if (hszService == pServer->hszService)
1736  {
1737  return pServer;
1738  }
1739  }
1740  TRACE("Service name missing\n");
1741  return NULL;
1742 }
1743 
1744 /* ================================================================
1745  *
1746  * Link (hot & warm) management
1747  *
1748  * ================================================================ */
1749 
1750 /******************************************************************
1751  * WDML_AddLink
1752  *
1753  *
1754  */
1755 void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
1756  UINT wType, HSZ hszItem, UINT wFmt)
1757 {
1758  WDML_LINK* pLink;
1759 
1760  pLink = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_LINK));
1761  if (pLink == NULL)
1762  {
1763  ERR("OOM\n");
1764  return;
1765  }
1766 
1767  pLink->hConv = hConv;
1768  pLink->transactionType = wType;
1769  WDML_IncHSZ(pInstance, pLink->hszItem = hszItem);
1770  pLink->uFmt = wFmt;
1771  pLink->next = pInstance->links[side];
1772  pInstance->links[side] = pLink;
1773 }
1774 
1775 /******************************************************************
1776  * WDML_RemoveLink
1777  *
1778  *
1779  */
1780 void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
1781  HSZ hszItem, UINT uFmt)
1782 {
1783  WDML_LINK* pPrev = NULL;
1784  WDML_LINK* pCurrent = NULL;
1785 
1786  pCurrent = pInstance->links[side];
1787 
1788  while (pCurrent != NULL)
1789  {
1790  if (pCurrent->hConv == hConv &&
1791  DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 &&
1792  pCurrent->uFmt == uFmt)
1793  {
1794  if (pCurrent == pInstance->links[side])
1795  {
1796  pInstance->links[side] = pCurrent->next;
1797  }
1798  else
1799  {
1800  pPrev->next = pCurrent->next;
1801  }
1802 
1803  WDML_DecHSZ(pInstance, pCurrent->hszItem);
1804  HeapFree(GetProcessHeap(), 0, pCurrent);
1805  break;
1806  }
1807 
1808  pPrev = pCurrent;
1809  pCurrent = pCurrent->next;
1810  }
1811 }
1812 
1813 /* this function is called to remove all links related to the conv.
1814  It should be called from both client and server when terminating
1815  the conversation.
1816 */
1817 /******************************************************************
1818  * WDML_RemoveAllLinks
1819  *
1820  *
1821  */
1822 static void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE side)
1823 {
1824  WDML_LINK* pPrev = NULL;
1825  WDML_LINK* pCurrent = NULL;
1826  WDML_LINK* pNext = NULL;
1827 
1828  pCurrent = pInstance->links[side];
1829 
1830  while (pCurrent != NULL)
1831  {
1832  if (pCurrent->hConv == (HCONV)pConv)
1833  {
1834  if (pCurrent == pInstance->links[side])
1835  {
1836  pInstance->links[side] = pCurrent->next;
1837  pNext = pCurrent->next;
1838  }
1839  else
1840  {
1841  pPrev->next = pCurrent->next;
1842  pNext = pCurrent->next;
1843  }
1844 
1845  WDML_DecHSZ(pInstance, pCurrent->hszItem);
1846 
1847  HeapFree(GetProcessHeap(), 0, pCurrent);
1848  pCurrent = NULL;
1849  }
1850 
1851  if (pCurrent)
1852  {
1853  pPrev = pCurrent;
1854  pCurrent = pCurrent->next;
1855  }
1856  else
1857  {
1858  pCurrent = pNext;
1859  }
1860  }
1861 }
1862 
1863 /******************************************************************
1864  * WDML_FindLink
1865  *
1866  *
1867  */
1868 WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
1869  HSZ hszItem, BOOL use_fmt, UINT uFmt)
1870 {
1871  WDML_LINK* pCurrent;
1872 
1873  for (pCurrent = pInstance->links[side]; pCurrent != NULL; pCurrent = pCurrent->next)
1874  {
1875  /* we don't need to check for transaction type as it can be altered */
1876 
1877  if (pCurrent->hConv == hConv &&
1878  DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 &&
1879  (!use_fmt || pCurrent->uFmt == uFmt))
1880  {
1881  break;
1882  }
1883 
1884  }
1885 
1886  return pCurrent;
1887 }
1888 
1889 /* ================================================================
1890  *
1891  * Transaction management
1892  *
1893  * ================================================================ */
1894 
1895 /******************************************************************
1896  * WDML_AllocTransaction
1897  *
1898  * Alloc a transaction structure for handling the message ddeMsg
1899  */
1901  UINT wFmt, HSZ hszItem)
1902 {
1903  WDML_XACT* pXAct;
1904  static WORD tid = 1; /* FIXME: wrap around */
1905 
1906  pXAct = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_XACT));
1907  if (!pXAct)
1908  {
1909  pInstance->lastError = DMLERR_MEMORY_ERROR;
1910  return NULL;
1911  }
1912 
1913  pXAct->xActID = tid++;
1914  pXAct->ddeMsg = ddeMsg;
1915  pXAct->hDdeData = 0;
1916  pXAct->hUser = 0;
1917  pXAct->next = NULL;
1918  pXAct->wType = 0;
1919  pXAct->wFmt = wFmt;
1920  if ((pXAct->hszItem = hszItem)) WDML_IncHSZ(pInstance, pXAct->hszItem);
1921  pXAct->atom = 0;
1922  pXAct->hMem = 0;
1923  pXAct->lParam = 0;
1924 
1925  return pXAct;
1926 }
1927 
1928 /******************************************************************
1929  * WDML_QueueTransaction
1930  *
1931  * Adds a transaction to the list of transaction
1932  */
1934 {
1935  WDML_XACT** pt;
1936 
1937  /* advance to last in queue */
1938  for (pt = &pConv->transactions; *pt != NULL; pt = &(*pt)->next);
1939  *pt = pXAct;
1940 }
1941 
1942 /******************************************************************
1943  * WDML_UnQueueTransaction
1944  *
1945  *
1946  */
1948 {
1949  WDML_XACT** pt;
1950 
1951  for (pt = &pConv->transactions; *pt; pt = &(*pt)->next)
1952  {
1953  if (*pt == pXAct)
1954  {
1955  *pt = pXAct->next;
1956  return TRUE;
1957  }
1958  }
1959  return FALSE;
1960 }
1961 
1962 /******************************************************************
1963  * WDML_FreeTransaction
1964  *
1965  *
1966  */
1967 void WDML_FreeTransaction(WDML_INSTANCE* pInstance, WDML_XACT* pXAct, BOOL doFreePmt)
1968 {
1969  /* free pmt(s) in pXAct too. check against one for not deleting TRUE return values */
1970  if (doFreePmt && (ULONG_PTR)pXAct->hMem > 1)
1971  {
1972  GlobalFree(pXAct->hMem);
1973  }
1974  if (pXAct->hszItem) WDML_DecHSZ(pInstance, pXAct->hszItem);
1975 
1976  HeapFree(GetProcessHeap(), 0, pXAct);
1977 }
1978 
1979 /******************************************************************
1980  * WDML_FindTransaction
1981  *
1982  *
1983  */
1985 {
1986  WDML_XACT* pXAct;
1987 
1988  tid = HIWORD(tid);
1989  for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next)
1990  {
1991  if (pXAct->xActID == tid)
1992  break;
1993  }
1994  return pXAct;
1995 }
1996 
1997 /* ================================================================
1998  *
1999  * Conversation management
2000  *
2001  * ================================================================ */
2002 
2003 /******************************************************************
2004  * WDML_AddConv
2005  *
2006  *
2007  */
2009  HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer)
2010 {
2011  WDML_CONV* pConv;
2012 
2013  /* no conversation yet, add it */
2014  pConv = HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_CONV));
2015  if (!pConv) return NULL;
2016 
2017  pConv->instance = pInstance;
2018  WDML_IncHSZ(pInstance, pConv->hszService = hszService);
2019  WDML_IncHSZ(pInstance, pConv->hszTopic = hszTopic);
2020  pConv->magic = WDML_CONV_MAGIC;
2021  pConv->hwndServer = hwndServer;
2022  pConv->hwndClient = hwndClient;
2023  pConv->transactions = NULL;
2024  pConv->hUser = 0;
2025  pConv->wStatus = (side == WDML_CLIENT_SIDE) ? ST_CLIENT : 0L;
2026  pConv->wStatus |= pInstance->wStatus;
2027  /* check if both side of the conversation are of the same instance */
2028  if (GetWindowThreadProcessId(hwndClient, NULL) == GetWindowThreadProcessId(hwndServer, NULL) &&
2029  WDML_GetInstanceFromWnd(hwndClient) == WDML_GetInstanceFromWnd(hwndServer))
2030  {
2031  pConv->wStatus |= ST_ISSELF;
2032  }
2033  pConv->wConvst = XST_NULL;
2034 
2035  pConv->next = pInstance->convs[side];
2036  pInstance->convs[side] = pConv;
2037 
2038  TRACE("pConv->wStatus %04x pInstance(%p)\n", pConv->wStatus, pInstance);
2039 
2040  return pConv;
2041 }
2042 
2043 /******************************************************************
2044  * WDML_FindConv
2045  *
2046  *
2047  */
2049  HSZ hszService, HSZ hszTopic)
2050 {
2051  WDML_CONV* pCurrent;
2052 
2053  for (pCurrent = pInstance->convs[side]; pCurrent != NULL; pCurrent = pCurrent->next)
2054  {
2055  if (DdeCmpStringHandles(pCurrent->hszService, hszService) == 0 &&
2056  DdeCmpStringHandles(pCurrent->hszTopic, hszTopic) == 0)
2057  {
2058  return pCurrent;
2059  }
2060 
2061  }
2062  return NULL;
2063 }
2064 
2065 /******************************************************************
2066  * WDML_RemoveConv
2067  *
2068  *
2069  */
2071 {
2072  WDML_CONV* pPrev = NULL;
2073  WDML_CONV* pCurrent;
2074  WDML_XACT* pXAct;
2075  WDML_XACT* pXActNext;
2076  HWND hWnd;
2077 
2078  if (!pRef)
2079  return;
2080 
2081  /* remove any pending transaction */
2082  for (pXAct = pRef->transactions; pXAct != NULL; pXAct = pXActNext)
2083  {
2084  pXActNext = pXAct->next;
2085  WDML_FreeTransaction(pRef->instance, pXAct, TRUE);
2086  }
2087 
2088  WDML_RemoveAllLinks(pRef->instance, pRef, side);
2089 
2090  /* FIXME: should we keep the window around ? it seems so (at least on client side
2091  * to let QueryConvInfo work after conv termination, but also to implement
2092  * DdeReconnect...
2093  */
2094  /* destroy conversation window, but first remove pConv from hWnd.
2095  * this would help the wndProc do appropriate handling upon a WM_DESTROY message
2096  */
2097  hWnd = (side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer;
2099 
2100  DestroyWindow((side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer);
2101 
2102  WDML_DecHSZ(pRef->instance, pRef->hszService);
2103  WDML_DecHSZ(pRef->instance, pRef->hszTopic);
2104 
2105  for (pCurrent = pRef->instance->convs[side]; pCurrent != NULL; pCurrent = (pPrev = pCurrent)->next)
2106  {
2107  if (pCurrent == pRef)
2108  {
2109  if (pCurrent == pRef->instance->convs[side])
2110  {
2111  pRef->instance->convs[side] = pCurrent->next;
2112  }
2113  else
2114  {
2115  pPrev->next = pCurrent->next;
2116  }
2117  pCurrent->magic = 0;
2118  HeapFree(GetProcessHeap(), 0, pCurrent);
2119  break;
2120  }
2121  }
2122 }
2123 
2124 /******************************************************************
2125  * WDML_EnableCallback
2126  */
2128 {
2129  if (wCmd == EC_DISABLE)
2130  {
2131  pConv->wStatus |= ST_BLOCKED;
2132  TRACE("EC_DISABLE: conv %p status flags %04x\n", pConv, pConv->wStatus);
2133  return TRUE;
2134  }
2135 
2136  if (wCmd == EC_QUERYWAITING)
2137  return pConv->transactions != NULL;
2138 
2139  if (wCmd != EC_ENABLEALL && wCmd != EC_ENABLEONE)
2140  {
2141  FIXME("Unknown command code %04x\n", wCmd);
2142  return FALSE;
2143  }
2144 
2145  if (wCmd == EC_ENABLEALL)
2146  {
2147  pConv->wStatus &= ~ST_BLOCKED;
2148  TRACE("EC_ENABLEALL: conv %p status flags %04x\n", pConv, pConv->wStatus);
2149  }
2150 
2151  while (pConv->transactions)
2152  {
2153  WDML_XACT *pXAct = pConv->transactions;
2154 
2155  if (pConv->wStatus & ST_CLIENT)
2156  {
2157  /* transaction should be in the queue until handled */
2158  WDML_ClientHandle(pConv, pXAct, 0, NULL);
2159  WDML_UnQueueTransaction(pConv, pXAct);
2160  }
2161  else
2162  {
2163  /* transaction should be removed from the queue before handling */
2164  WDML_UnQueueTransaction(pConv, pXAct);
2165  WDML_ServerHandle(pConv, pXAct);
2166  }
2167 
2168  WDML_FreeTransaction(pConv->instance, pXAct, TRUE);
2169 
2170  if (wCmd == EC_ENABLEONE) break;
2171  }
2172  return TRUE;
2173 }
2174 
2175 /*****************************************************************
2176  * DdeEnableCallback (USER32.@)
2177  */
2178 BOOL WINAPI DdeEnableCallback(DWORD idInst, HCONV hConv, UINT wCmd)
2179 {
2180  BOOL ret = FALSE;
2181  WDML_CONV *pConv;
2182 
2183  TRACE("(%d, %p, %04x)\n", idInst, hConv, wCmd);
2184 
2185  if (hConv)
2186  {
2187  pConv = WDML_GetConv(hConv, TRUE);
2188 
2189  if (pConv && pConv->instance->instanceID == idInst)
2190  ret = WDML_EnableCallback(pConv, wCmd);
2191  }
2192  else
2193  {
2194  WDML_INSTANCE *pInstance = WDML_GetInstance(idInst);
2195 
2196  if (!pInstance)
2197  return FALSE;
2198 
2199  TRACE("adding flags %04x to instance %p\n", wCmd, pInstance);
2200  pInstance->wStatus |= wCmd;
2201 
2202  if (wCmd == EC_DISABLE)
2203  {
2204  pInstance->wStatus |= ST_BLOCKED;
2205  TRACE("EC_DISABLE: inst %p status flags %04x\n", pInstance, pInstance->wStatus);
2206  }
2207  else if (wCmd == EC_ENABLEALL)
2208  {
2209  pInstance->wStatus &= ~ST_BLOCKED;
2210  TRACE("EC_ENABLEALL: inst %p status flags %04x\n", pInstance, pInstance->wStatus);
2211  }
2212 
2213  ret = TRUE;
2214 
2215  for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv != NULL; pConv = pConv->next)
2216  {
2217  ret = WDML_EnableCallback(pConv, wCmd);
2218  if (ret && wCmd == EC_QUERYWAITING) break;
2219  }
2220  }
2221 
2222  return ret;
2223 }
2224 
2225 /******************************************************************
2226  * WDML_GetConv
2227  *
2228  *
2229  */
2230 WDML_CONV* WDML_GetConv(HCONV hConv, BOOL checkConnected)
2231 {
2232  WDML_CONV* pConv = (WDML_CONV*)hConv;
2233 
2234  /* FIXME: should do better checking */
2235  if (pConv == NULL || pConv->magic != WDML_CONV_MAGIC) return NULL;
2236 
2237  if (!pConv->instance)
2238  {
2239  WARN("wrong thread ID, no instance\n");
2240  return NULL;
2241  }
2242 
2243  if (pConv->instance->threadID != GetCurrentThreadId())
2244  {
2245  WARN("wrong thread ID\n");
2246  pConv->instance->lastError = DMLERR_INVALIDPARAMETER; /* FIXME: check */
2247  return NULL;
2248  }
2249 
2250  if (checkConnected && !(pConv->wStatus & ST_CONNECTED))
2251  {
2252  WARN("found conv but ain't connected\n");
2253  pConv->instance->lastError = DMLERR_NO_CONV_ESTABLISHED;
2254  return NULL;
2255  }
2256 
2257  return pConv;
2258 }
2259 
2260 /******************************************************************
2261  * WDML_GetConvFromWnd
2262  *
2263  *
2264  */
2266 {
2268 }
2269 
2270 /******************************************************************
2271  * WDML_PostAck
2272  *
2273  *
2274  */
2275 BOOL WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode,
2276  BOOL fBusy, BOOL fAck, UINT_PTR pmt, LPARAM lParam, UINT oldMsg)
2277 {
2278  DDEACK ddeAck;
2279  HWND from, to;
2280 
2281  if (side == WDML_SERVER_SIDE)
2282  {
2283  from = pConv->hwndServer;
2284  to = pConv->hwndClient;
2285  }
2286  else
2287  {
2288  to = pConv->hwndServer;
2289  from = pConv->hwndClient;
2290  }
2291 
2292  ddeAck.bAppReturnCode = appRetCode;
2293  ddeAck.reserved = 0;
2294  ddeAck.fBusy = fBusy;
2295  ddeAck.fAck = fAck;
2296 
2297  TRACE("Posting a %s ack\n", ddeAck.fAck ? "positive" : "negative");
2298 
2299  lParam = (lParam) ? ReuseDDElParam(lParam, oldMsg, WM_DDE_ACK, *(WORD*)&ddeAck, pmt) :
2300  PackDDElParam(WM_DDE_ACK, *(WORD*)&ddeAck, pmt);
2301  if (!PostMessageW(to, WM_DDE_ACK, (WPARAM)from, lParam))
2302  {
2303  pConv->wStatus &= ~ST_CONNECTED;
2304  pConv->instance->lastError = DMLERR_POSTMSG_FAILED;
2306  return FALSE;
2307  }
2308  return TRUE;
2309 }
2310 
2311 /*****************************************************************
2312  * DdeSetUserHandle (USER32.@)
2313  */
2314 BOOL WINAPI DdeSetUserHandle(HCONV hConv, DWORD id, DWORD hUser)
2315 {
2316  WDML_CONV* pConv;
2317 
2318  pConv = WDML_GetConv(hConv, FALSE);
2319  if (pConv == NULL)
2320  return FALSE;
2321 
2322  if (id == QID_SYNC)
2323  {
2324  pConv->hUser = hUser;
2325  }
2326  else
2327  {
2328  WDML_XACT* pXAct;
2329 
2330  pXAct = WDML_FindTransaction(pConv, id);
2331  if (pXAct)
2332  {
2333  pXAct->hUser = hUser;
2334  }
2335  else
2336  {
2337  pConv->instance->lastError = DMLERR_UNFOUND_QUEUE_ID;
2338  return FALSE;
2339  }
2340  }
2341  return TRUE;
2342 }
2343 
2344 /******************************************************************
2345  * WDML_GetLocalConvInfo
2346  *
2347  *
2348  */
2350 {
2351  BOOL ret = TRUE;
2352  WDML_LINK* pLink;
2353  WDML_SIDE side;
2354 
2355  ci->hConvPartner = (pConv->wStatus & ST_ISLOCAL) ? (HCONV)((ULONG_PTR)pConv | 1) : 0;
2356  ci->hszSvcPartner = pConv->hszService;
2357  ci->hszServiceReq = pConv->hszService; /* FIXME: they shouldn't be the same, should they ? */
2358  ci->hszTopic = pConv->hszTopic;
2359  ci->wStatus = pConv->wStatus;
2360 
2361  side = (pConv->wStatus & ST_CLIENT) ? WDML_CLIENT_SIDE : WDML_SERVER_SIDE;
2362 
2363  for (pLink = pConv->instance->links[side]; pLink != NULL; pLink = pLink->next)
2364  {
2365  if (pLink->hConv == (HCONV)pConv)
2366  {
2367  ci->wStatus |= ST_ADVISE;
2368  break;
2369  }
2370  }
2371 
2372  /* FIXME: non handled status flags:
2373  ST_BLOCKED
2374  ST_BLOCKNEXT
2375  ST_INLIST
2376  */
2377 
2378  ci->wConvst = pConv->wConvst; /* FIXME */
2379 
2380  ci->wLastError = 0; /* FIXME: note it's not the instance last error */
2381  ci->hConvList = 0;
2382  ci->ConvCtxt = pConv->convContext;
2383  if (ci->wStatus & ST_CLIENT)
2384  {
2385  ci->hwnd = pConv->hwndClient;
2386  ci->hwndPartner = pConv->hwndServer;
2387  }
2388  else
2389  {
2390  ci->hwnd = pConv->hwndServer;
2391  ci->hwndPartner = pConv->hwndClient;
2392  }
2393  if (id == QID_SYNC)
2394  {
2395  ci->hUser = pConv->hUser;
2396  ci->hszItem = 0;
2397  ci->wFmt = 0;
2398  ci->wType = 0;
2399  }
2400  else
2401  {
2402  WDML_XACT* pXAct;
2403 
2404  pXAct = WDML_FindTransaction(pConv, id);
2405  if (pXAct)
2406  {
2407  ci->hUser = pXAct->hUser;
2408  ci->hszItem = pXAct->hszItem;
2409  ci->wFmt = pXAct->wFmt;
2410  ci->wType = pXAct->wType;
2411  }
2412  else
2413  {
2414  ret = 0;
2415  pConv->instance->lastError = DMLERR_UNFOUND_QUEUE_ID;
2416  }
2417  }
2418  return ret;
2419 }
2420 
2421 /******************************************************************
2422  * DdeQueryConvInfo (USER32.@)
2423  *
2424  * FIXME: Set last DDE error on failure.
2425  */
2426 UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, PCONVINFO lpConvInfo)
2427 {
2428  UINT ret = lpConvInfo->cb;
2429  CONVINFO ci;
2430  WDML_CONV* pConv;
2431 
2432  TRACE("(%p,%x,%p)\n", hConv, id, lpConvInfo);
2433 
2434  if (!hConv)
2435  {
2436  FIXME("hConv is NULL\n");
2437  return 0;
2438  }
2439 
2440  pConv = WDML_GetConv(hConv, FALSE);
2441  if (pConv != NULL)
2442  {
2443  if (!WDML_GetLocalConvInfo(pConv, &ci, id))
2444  ret = 0;
2445  }
2446  else
2447  {
2448  if ((ULONG_PTR)hConv & 1)
2449  {
2450  pConv = WDML_GetConv((HCONV)((ULONG_PTR)hConv & ~1), FALSE);
2451  if (pConv != NULL)
2452  FIXME("Request on remote conversation information is not implemented yet\n");
2453  }
2454  ret = 0;
2455  }
2456 
2457  if (ret != 0)
2458  {
2459  ci.cb = lpConvInfo->cb;
2460  memcpy(lpConvInfo, &ci, min((size_t)lpConvInfo->cb, sizeof(ci)));
2461  }
2462  return ret;
2463 }
2464 
2465 /* ================================================================
2466  *
2467  * Information broadcast across DDEML implementations
2468  *
2469  * ================================================================ */
2470 
2472 {
2477 };
2478 
2479 /******************************************************************
2480  * WDML_BroadcastEnumProc
2481  *
2482  *
2483  */
2485 {
2487  WCHAR buffer[128];
2488 
2489  if (GetClassNameW(hWnd, buffer, 128) > 0 &&
2490  lstrcmpiW(buffer, s->clsName) == 0)
2491  {
2492  PostMessageW(hWnd, s->uMsg, s->wParam, s->lParam);
2493  }
2494  return TRUE;
2495 }
2496 
2497 /******************************************************************
2498  * WDML_BroadcastDDEWindows
2499  *
2500  *
2501  */
2503 {
2504  struct tagWDML_BroadcastPmt s;
2505 
2506  s.clsName = clsName;
2507  s.uMsg = uMsg;
2508  s.wParam = wParam;
2509  s.lParam = lParam;
2511 }
#define DNS_UNREGISTER
Definition: ddeml.h:153
#define ST_ISLOCAL
Definition: ddeml.h:82
UINT WINAPI GetAtomNameA(ATOM nAtom, LPSTR lpBuffer, int nSize)
Definition: atom.c:577
WDML_INSTANCE * WDML_GetInstance(DWORD instId)
Definition: ddemisc.c:1230
unsigned short fResponse
Definition: dde_private.h:83
#define APPCLASS_MONITOR
Definition: ddeml.h:131
static HSZ WDML_CreateString(WDML_INSTANCE *pInstance, LPCVOID ptr, int codepage)
Definition: ddemisc.c:550
ATOM WINAPI GlobalDeleteAtom(ATOM nAtom)
Definition: atom.c:454
#define HSZ2ATOM(hsz)
Definition: ddemisc.c:34
static BOOL WDML_EnableCallback(WDML_CONV *pConv, UINT wCmd)
Definition: ddemisc.c:2127
BOOL WDML_UnQueueTransaction(WDML_CONV *pConv, WDML_XACT *pXAct)
Definition: ddemisc.c:1947
struct tagHSZNode * next
Definition: dde_private.h:93
#define TRUE
Definition: types.h:120
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
UINT WINAPI DdeInitializeW(LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes)
Definition: ddemisc.c:1095
struct tagWDML_CONV * next
Definition: dde_private.h:126
BOOL WINAPI DdeSetUserHandle(HCONV hConv, DWORD id, DWORD hUser)
Definition: ddemisc.c:2314
static CRITICAL_SECTION WDML_CritSect
Definition: ddemisc.c:41
#define snprintfW
Definition: unicode.h:60
static rfbScreenInfoPtr server
Definition: vnc.c:74
int cbWndExtra
Definition: winuser.h:3194
HDDEDATA hDdeData
Definition: dde_private.h:113
#define DWORD_PTR
Definition: treelist.c:76
#define ST_CLIENT
Definition: ddeml.h:84
static WDML_INSTANCE * WDML_InstanceList
Definition: ddemisc.c:36
unsigned short fAckReq
Definition: dde_private.h:83
static WDML_XACT * WDML_FindTransaction(WDML_CONV *pConv, DWORD tid)
Definition: ddemisc.c:1984
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
HGLOBAL NTAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:825
unsigned short bAppReturnCode
Definition: dde.h:52
WORD ATOM
Definition: dimm.idl:113
#define pt(x, y)
Definition: drawing.c:79
HGLOBAL hMem
Definition: dde_private.h:120
ATOM WDML_MakeAtomFromHsz(HSZ hsz)
Definition: ddemisc.c:325
static void WDML_FreeAllHSZ(WDML_INSTANCE *pInstance)
Definition: ddemisc.c:419
GLuint GLuint GLsizei count
Definition: gl.h:1545
WDML_CONV * WDML_GetConvFromWnd(HWND hWnd)
Definition: ddemisc.c:2265
char CHAR
Definition: xmlstorage.h:175
HDDEDATA WINAPI DdeAddData(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
Definition: ddemisc.c:1340
#define ST_BLOCKED
Definition: ddeml.h:83
#define CBF_SKIP_UNREGISTRATIONS
Definition: ddeml.h:113
#define WARN(fmt,...)
Definition: debug.h:111
#define MAKELPARAM(l, h)
Definition: winuser.h:3947
WDML_XACT * transactions
Definition: dde_private.h:135
#define CALLBACK
Definition: compat.h:27
HWND hWnd
Definition: settings.c:17
#define DMLERR_MEMORY_ERROR
Definition: ddeml.h:254
UINT WINAPI GetAtomNameW(ATOM nAtom, LPWSTR lpBuffer, int nSize)
Definition: atom.c:589
CONVCONTEXT ConvCtxt
Definition: ddeml.h:330
#define MAX_BUFFER_LEN
Definition: dde_private.h:34
#define XTYP_CONNECT_CONFIRM
Definition: ddeml.h:187
#define EC_QUERYWAITING
Definition: ddeml.h:97
BOOL WINAPI DdeSetQualityOfService(HWND hwndClient, const SECURITY_QUALITY_OF_SERVICE *pqosNew, PSECURITY_QUALITY_OF_SERVICE pqosPrev)
Definition: ddemisc.c:231
void WDML_NotifyThreadDetach(void)
Definition: ddemisc.c:1181
HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult) DECLSPEC_HIDDEN
Definition: ddeclient.c:1090
GLuint buffer
Definition: glext.h:5915
HICON hIcon
Definition: winuser.h:3196
#define ST_CONNECTED
Definition: ddeml.h:80
static BOOL CALLBACK WDML_BroadcastEnumProc(HWND hWnd, LPARAM lParam)
Definition: ddemisc.c:2484
HGLOBAL NTAPI GlobalHandle(LPCVOID pMem)
Definition: heapmem.c:705
UINT_PTR WPARAM
Definition: windef.h:207
#define DMLERR_POSTMSG_FAILED
Definition: ddeml.h:258
#define GetWindowLongPtrW
Definition: winuser.h:4730
short cfFormat
Definition: dde.h:59
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
char * LPSTR
Definition: xmlstorage.h:182
unsigned short fRelease
Definition: dde_private.h:83
#define APPCLASS_MASK
Definition: ddeml.h:132
UINT wLastError
Definition: ddeml.h:328
static BOOL WDML_GetLocalConvInfo(WDML_CONV *pConv, CONVINFO *ci, DWORD id)
Definition: ddemisc.c:2349
DWORD cb
Definition: ddeml.h:317
BOOL WINAPI DestroyWindow(_In_ HWND)
HSZ WDML_MakeHszFromAtom(const WDML_INSTANCE *pInstance, ATOM atom)
Definition: ddemisc.c:342
#define ATOM2HSZ(atom)
Definition: ddemisc.c:33
LPARAM WINAPI ReuseDDElParam(LPARAM lParam, UINT msgIn, UINT msgOut, UINT_PTR uiLo, UINT_PTR uiHi)
Definition: ddemisc.c:171
BOOL WDML_IncHSZ(WDML_INSTANCE *pInstance, HSZ hsz)
Definition: ddemisc.c:362
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4217
int32_t INT
Definition: typedefs.h:56
WPARAM wParam
Definition: combotst.c:138
static LRESULT CALLBACK WDML_EventProc(HWND hwndEvent, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: ddemisc.c:759
#define MF_MASK
Definition: ddeml.h:146
ATOM atomServiceSpec
Definition: dde_private.h:104
Definition: dde.h:50
WDML_CONV * convs[2]
Definition: dde_private.h:168
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
WDML_XACT * WDML_AllocTransaction(WDML_INSTANCE *pInstance, UINT ddeMsg, UINT wFmt, HSZ hszItem)
Definition: ddemisc.c:1900
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
HWND hwnd
Definition: ddeml.h:331
uint32_t ULONG_PTR
Definition: typedefs.h:63
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
#define CBF_SKIP_REGISTRATIONS
Definition: ddeml.h:112
#define XST_NULL
Definition: ddeml.h:62
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
ATOM WINAPI RegisterClassExW(_In_ CONST WNDCLASSEXW *)
#define WDML_CONV_MAGIC
Definition: dde_private.h:141
#define DMLERR_UNFOUND_QUEUE_ID
Definition: ddeml.h:263
LPARAM lParam
Definition: dde_private.h:121
LPCWSTR lpszMenuName
Definition: winuser.h:3199
HSZ hszServiceReq
Definition: ddeml.h:321
unsigned char * LPBYTE
Definition: typedefs.h:52
GLenum const GLfloat * params
Definition: glext.h:5645
#define EC_ENABLEONE
Definition: ddeml.h:95
HSZ hszTopic
Definition: ddeml.h:322
ATOM WINAPI DeleteAtom(ATOM nAtom)
Definition: atom.c:546
BOOL WDML_DecHSZ(WDML_INSTANCE *pInstance, HSZ hsz)
Definition: ddemisc.c:380
struct tagWDML_XACT * next
Definition: dde_private.h:110
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
unsigned short fAck
Definition: dde.h:52
#define WM_DDE_TERMINATE
Definition: dde.h:38
static void WDML_InsertHSZNode(WDML_INSTANCE *pInstance, HSZ hsz)
Definition: ddemisc.c:434
#define WM_DDE_DATA
Definition: dde.h:42
uint32_t * PUINT_PTR
Definition: typedefs.h:63
#define debugstr_w
Definition: kernel32.h:32
HCONVLIST hConvList
Definition: ddeml.h:329
#define DMLERR_NO_ERROR
Definition: ddeml.h:242
enum tagWDML_SIDE WDML_SIDE
BOOL WINAPI DdeUninitialize(DWORD idInst)
Definition: ddemisc.c:1112
#define FIXME(fmt,...)
Definition: debug.h:110
static PVOID ptr
Definition: dispmode.c:27
static int error_code[8]
Definition: odbccp32.c:62
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetWindowThreadProcessId(HWND, PDWORD)
#define CF_BITMAP
Definition: constants.h:397
#define MAKELONG(a, b)
Definition: typedefs.h:248
smooth NULL
Definition: ftsmooth.c:416
LPBYTE WINAPI DdeAccessData(HDDEDATA hData, LPDWORD pcbDataSize)
Definition: ddemisc.c:1422
HSZNode * nodeList
Definition: dde_private.h:160
#define APPCMD_FILTERINITS
Definition: ddeml.h:123
LONG_PTR LPARAM
Definition: windef.h:208
ATOM WINAPI AddAtomW(LPCWSTR lpString)
Definition: atom.c:536
int cbClsExtra
Definition: winuser.h:3193
#define DMLERR_SYS_ERROR
Definition: ddeml.h:261
unsigned short reserved
Definition: dde.h:52
UINT wConvst
Definition: ddeml.h:327
WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV *pConv, WDML_XACT *pXAct) DECLSPEC_HIDDEN
Definition: ddeserver.c:968
const char * LPCSTR
Definition: xmlstorage.h:183
BOOL WINAPI DdeFreeDataHandle(HDDEDATA hData)
Definition: ddemisc.c:1461
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
LPCWSTR lpszClassName
Definition: winuser.h:3200
#define CF_TEXT
Definition: constants.h:396
Definition: dde.h:56
HBITMAP hbmp
UINT wStatus
Definition: ddeml.h:326
UINT WINAPI GlobalGetAtomNameW(ATOM nAtom, LPWSTR lpBuffer, int nSize)
Definition: atom.c:496
BOOL WINAPI DdeFreeStringHandle(DWORD idInst, HSZ hsz)
Definition: ddemisc.c:631
HCONV hConvPartner
Definition: ddeml.h:319
#define TRACE(s)
Definition: solgame.cpp:4
BOOL WINAPI DdeDisconnect(HCONV)
Definition: ddeclient.c:1363
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
unsigned short fDeferUpd
Definition: dde_private.h:83
#define APPCMD_CLIENTONLY
Definition: ddeml.h:122
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
HBRUSH hbrBackground
Definition: winuser.h:3198
#define XTYP_REGISTER
Definition: ddeml.h:190
UINT cbSize
Definition: winuser.h:3190
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: ddemisc.c:42
LONG WINAPI GetBitmapBits(_In_ HBITMAP hbit, _In_ LONG cb, _Out_writes_bytes_(cb) LPVOID lpvBits)
#define WINAPI
Definition: msvc.h:8
WDML_CONV * WDML_GetConv(HCONV hConv, BOOL checkConnected)
Definition: ddemisc.c:2230
CONVCONTEXT convContext
Definition: dde_private.h:132
BOOL WINAPI EnumWindows(_In_ WNDENUMPROC, _In_ LPARAM)
static FILE * client
Definition: client.c:41
unsigned short WORD
Definition: ntddk_ex.h:93
BOOL WINAPI ImpersonateDdeClientWindow(HWND hWndClient, HWND hWndServer)
Definition: ddemisc.c:221
unsigned long DWORD
Definition: ntddk_ex.h:95
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
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:2275
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease, BOOL fDeferUpd, BOOL fAckReq)
Definition: ddemisc.c:1563
WDML_SERVER * WDML_FindServer(WDML_INSTANCE *pInstance, HSZ hszService, HSZ hszTopic)
Definition: ddemisc.c:1729
static DWORD cb
Definition: integrity.c:41
WDML_LINK * WDML_FindLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, HSZ hszItem, BOOL use_fmt, UINT uFmt)
Definition: ddemisc.c:1868
BITMAP bmp
Definition: alphablend.c:62
HINSTANCE hInstance
Definition: winuser.h:3195
UINT cchMax
DWORD WINAPI DdeQueryStringW(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, INT iCodePage)
Definition: ddemisc.c:525
#define ST_ISSELF
Definition: ddeml.h:88
#define GWL_WDML_INSTANCE
Definition: dde_private.h:259
BOOL WINAPI DdeKeepStringHandle(DWORD idInst, HSZ hsz)
Definition: ddemisc.c:654
#define CBF_SKIP_CONNECT_CONFIRMS
Definition: ddeml.h:111
int ret
ATOM WINAPI AddAtomA(LPCSTR lpString)
Definition: atom.c:526
#define WM_DDE_POKE
Definition: dde.h:44
static UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes, BOOL bUnicode)
Definition: ddemisc.c:827
static const WCHAR L[]
Definition: oid.c:1250
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
HSZ hszItem
Definition: ddeml.h:323
DWORD WINAPI DdeGetData(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
Definition: ddemisc.c:1379
void WDML_RemoveServer(WDML_INSTANCE *pInstance, HSZ hszService, HSZ hszTopic)
Definition: ddemisc.c:1670
UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, PCONVINFO lpConvInfo)
Definition: ddemisc.c:2426
unsigned short unused
Definition: dde_private.h:83
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLdouble s
Definition: gl.h:2039
HCURSOR hCursor
Definition: winuser.h:3197
#define GWL_WDML_CONVERSATION
Definition: dde_private.h:260
#define DMLERR_DLL_USAGE
Definition: ddeml.h:250
UINT style
Definition: winuser.h:3191
LIST_ENTRY ProcessLocksList
Definition: winbase.h:848
static LONG WDML_MaxInstanceID
Definition: ddemisc.c:37
WDML_LINK * links[2]
Definition: dde_private.h:169
static HSZ hszTopic
Definition: shlexec.c:155
struct tagDDE_DATAHANDLE_HEAD DDE_DATAHANDLE_HEAD
WNDPROC lpfnWndProc
Definition: winuser.h:3192
const WCHAR WDML_szEventClass[]
Definition: ddemisc.c:38
WDML_SERVER * WDML_AddServer(WDML_INSTANCE *pInstance, HSZ hszService, HSZ hszTopic)
Definition: ddemisc.c:1638
#define ERR(fmt,...)
Definition: debug.h:109
void WDML_QueueTransaction(WDML_CONV *pConv, WDML_XACT *pXAct)
Definition: ddemisc.c:1933
#define CBF_FAIL_ALLSVRXACTIONS
Definition: ddeml.h:109
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define DMLERR_INVALIDPARAMETER
Definition: ddeml.h:252
void WDML_RemoveConv(WDML_CONV *pRef, WDML_SIDE side)
Definition: ddemisc.c:2070
static void WDML_SetAllLastError(DWORD lastError)
Definition: ddemisc.c:279
#define ST_ADVISE
Definition: ddeml.h:81
struct tagWDML_INSTANCE * instance
Definition: dde_private.h:127
#define CP_WINANSI
Definition: ddeml.h:32
HDDEDATA WDML_Global2DataHandle(WDML_CONV *pConv, HGLOBAL hMem, WINE_DDEHEAD *p)
Definition: ddemisc.c:1504
static unsigned __int64 next
Definition: rand_nt.c:6
BOOL WDML_IsAppOwned(HDDEDATA hData)
Definition: ddemisc.c:1477
#define HDATA_APPOWNED
Definition: ddeml.h:267
DWORD hUser
Definition: ddeml.h:318
#define InterlockedIncrement
Definition: armddk.h:53
DWORD WINAPI DdeQueryStringA(DWORD idInst, HSZ hsz, LPSTR psz, DWORD cchMax, INT iCodePage)
Definition: ddemisc.c:501
static int WDML_QueryString(WDML_INSTANCE *pInstance, HSZ hsz, LPVOID ptr, DWORD cchMax, int codepage)
Definition: ddemisc.c:461
#define EC_DISABLE
Definition: ddeml.h:96
HSZ WINAPI DdeCreateStringHandleA(DWORD idInst, LPCSTR psz, INT codepage)
Definition: ddemisc.c:577
#define WM_WDML_REGISTER
Definition: dde_private.h:248
WDML_CONV * WDML_FindConv(WDML_INSTANCE *pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic)
Definition: ddemisc.c:2048
Definition: bl.h:1331
HDDEDATA WINAPI DdeCreateDataHandle(DWORD idInst, LPBYTE pSrc, DWORD cb, DWORD cbOff, HSZ hszItem, UINT wFmt, UINT afCmd)
Definition: ddemisc.c:1275
#define CP_WINUNICODE
Definition: ddeml.h:33
#define min(a, b)
Definition: monoChain.cc:55
#define WS_POPUP
Definition: pedump.c:616
unsigned int UINT
Definition: ndis.h:50
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HDDEDATA WINAPI DdeNameService(DWORD, HSZ, HSZ, UINT)
Definition: ddeserver.c:154
#define QID_SYNC
Definition: ddeml.h:40
HSZ WINAPI DdeCreateStringHandleW(DWORD idInst, LPCWSTR psz, INT codepage)
Definition: ddemisc.c:608
unsigned short fBusy
Definition: dde.h:52
ATOM WINAPI GlobalAddAtomW(LPCWSTR lpString)
Definition: atom.c:444
BOOL WINAPI FreeDDElParam(UINT msg, LPARAM lParam)
Definition: ddemisc.c:147
PFNCALLBACK callback
Definition: dde_private.h:161
#define GMEM_DDESHARE
Definition: winbase.h:295
struct define * next
Definition: wpp.c:35
UINT wType
Definition: ddeml.h:325
HICON hIconSm
Definition: winuser.h:3201
HWND hwndPartner
Definition: ddeml.h:332
LPARAM WINAPI PackDDElParam(UINT msg, UINT_PTR uiLo, UINT_PTR uiHi)
Definition: ddemisc.c:63
#define msg(x)
Definition: auth_time.c:54
CONST void * LPCVOID
Definition: windef.h:191
void WDML_FreeTransaction(WDML_INSTANCE *pInstance, WDML_XACT *pXAct, BOOL doFreePmt)
Definition: ddemisc.c:1967
HSZ hszSvcPartner
Definition: ddeml.h:320
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
#define EC_ENABLEALL
Definition: ddeml.h:94
#define HIWORD(l)
Definition: typedefs.h:246
GLenum GLuint id
Definition: glext.h:5579
struct tagWDML_INSTANCE * next
Definition: dde_private.h:154
UINT WINAPI DdeGetLastError(DWORD idInst)
Definition: ddemisc.c:253
#define ULONG_PTR
Definition: config.h:101
#define SetWindowLongPtrW
Definition: winuser.h:5247
static HBITMAP
Definition: button.c:44
void WDML_BroadcastDDEWindows(LPCWSTR clsName, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: ddemisc.c:2502
#define WM_DDE_ADVISE
Definition: dde.h:39
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
unsigned refCount
Definition: dde_private.h:95
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static void WDML_RemoveAllLinks(WDML_INSTANCE *pInstance, WDML_CONV *pConv, WDML_SIDE side)
Definition: ddemisc.c:1822
LONG_PTR LRESULT
Definition: windef.h:209
CardRegion * from
Definition: spigame.cpp:19
INT WINAPI DdeCmpStringHandles(HSZ hsz1, HSZ hsz2)
Definition: ddemisc.c:685
#define DMLERR_NO_CONV_ESTABLISHED
Definition: ddeml.h:256
void WDML_AddLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, UINT wType, HSZ hszItem, UINT wFmt)
Definition: ddemisc.c:1755
BOOL WINAPI UnpackDDElParam(UINT msg, LPARAM lParam, PUINT_PTR uiLo, PUINT_PTR uiHi)
Definition: ddemisc.c:105
HDDEDATA WDML_InvokeCallback(WDML_INSTANCE *pInstance, UINT uType, UINT uFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
Definition: ddemisc.c:1206
BOOL WINAPI DdeUnaccessData(HDDEDATA hData)
Definition: ddemisc.c:1447
BOOL WINAPI DdeEnableCallback(DWORD idInst, HCONV hConv, UINT wCmd)
Definition: ddemisc.c:2178
UINT wFmt
Definition: ddeml.h:324
WDML_SERVER * servers
Definition: dde_private.h:167
#define WM_DDE_EXECUTE
Definition: dde.h:45
static HSZNode * WDML_FindNode(WDML_INSTANCE *pInstance, HSZ hsz)
Definition: ddemisc.c:305
static TfClientId tid
LPARAM lParam
Definition: combotst.c:139
void WDML_RemoveLink(WDML_INSTANCE *pInstance, HCONV hConv, WDML_SIDE side, HSZ hszItem, UINT uFmt)
Definition: ddemisc.c:1780
#define LOWORD(l)
Definition: pedump.c:82
#define HeapFree(x, y, z)
Definition: compat.h:394
#define GMEM_MOVEABLE
Definition: winbase.h:291
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:54
WINE_DEFAULT_DEBUG_CHANNEL(ddeml)
UINT WINAPI DdeInitializeA(LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes)
Definition: ddemisc.c:1075
#define WIN_GetFullHandle(h)
Definition: user_x.h:108
HDDEDATA(CALLBACK * PFNCALLBACK)(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, ULONG_PTR, ULONG_PTR)
Definition: ddeml.h:290
#define WM_WDML_CONNECT_CONFIRM
Definition: dde_private.h:250
DWORD WINAPI GetCurrentProcessId(VOID)
Definition: proc.c:1158
WDML_INSTANCE * WDML_GetInstanceFromWnd(HWND hWnd)
Definition: ddemisc.c:1261
#define APPCMD_MASK
Definition: ddeml.h:124
static void WDML_IncrementInstanceId(WDML_INSTANCE *pInstance)
Definition: ddemisc.c:746
#define XTYP_UNREGISTER
Definition: ddeml.h:193
struct tagWDML_SERVER * next
Definition: dde_private.h:100
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
#define WM_WDML_UNREGISTER
Definition: dde_private.h:249
BYTE Value[1]
Definition: dde.h:60
WDML_CONV * WDML_AddConv(WDML_INSTANCE *pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer)
Definition: ddemisc.c:2008