wordpad: Allow objects & images to be added with native riched20.
[wine] / dlls / user32 / tests / dde.c
1 /*
2  * Unit tests for DDE functions
3  *
4  * Copyright (c) 2004 Dmitry Timoshkov
5  * Copyright (c) 2007 James Hawkins
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "dde.h"
31 #include "ddeml.h"
32 #include "winerror.h"
33
34 #include "wine/test.h"
35
36 static const WCHAR TEST_DDE_SERVICE[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};
37
38 static char exec_cmdA[] = "ANSI dde command";
39 static WCHAR exec_cmdAW[] = {'A','N','S','I',' ','d','d','e',' ','c','o','m','m','a','n','d',0};
40 static WCHAR exec_cmdW[] = {'u','n','i','c','o','d','e',' ','d','d','e',' ','c','o','m','m','a','n','d',0};
41 static char exec_cmdWA[] = "unicode dde command";
42
43 static WNDPROC old_dde_client_wndproc;
44
45 static const DWORD default_timeout = 200;
46
47 static void flush_events(void)
48 {
49     MSG msg;
50     int diff = default_timeout;
51     int min_timeout = 50;
52     DWORD time = GetTickCount() + diff;
53
54     while (diff > 0)
55     {
56         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
57         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
58         diff = time - GetTickCount();
59         min_timeout = 10;
60     }
61 }
62
63 static void create_dde_window(HWND *hwnd, LPCSTR name, WNDPROC wndproc)
64 {
65     WNDCLASSA wcA;
66
67     memset(&wcA, 0, sizeof(wcA));
68     wcA.lpfnWndProc = wndproc;
69     wcA.lpszClassName = name;
70     wcA.hInstance = GetModuleHandleA(0);
71     assert(RegisterClassA(&wcA));
72
73     *hwnd = CreateWindowExA(0, name, NULL, WS_POPUP,
74                             500, 500, CW_USEDEFAULT, CW_USEDEFAULT,
75                             GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
76     assert(*hwnd);
77 }
78
79 static void destroy_dde_window(HWND *hwnd, LPCSTR name)
80 {
81     DestroyWindow(*hwnd);
82     UnregisterClass(name, GetModuleHandleA(0));
83 }
84
85 static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
86 {
87     UINT_PTR lo, hi;
88     char str[MAX_PATH], *ptr;
89     HGLOBAL hglobal;
90     DDEDATA *data;
91     DDEPOKE *poke;
92     DWORD size;
93
94     static int msg_index = 0;
95     static HWND client = 0;
96     static BOOL executed = FALSE;
97
98     if (msg < WM_DDE_FIRST || msg > WM_DDE_LAST)
99         return DefWindowProcA(hwnd, msg, wparam, lparam);
100
101     msg_index++;
102
103     switch (msg)
104     {
105     case WM_DDE_INITIATE:
106     {
107         client = (HWND)wparam;
108         ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
109
110         GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
111         ok(!lstrcmpA(str, "TestDDEService"), "Expected TestDDEService, got %s\n", str);
112
113         GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
114         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
115
116         SendMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
117
118         break;
119     }
120
121     case WM_DDE_REQUEST:
122     {
123         ok((msg_index >= 2 && msg_index <= 4) ||
124            (msg_index >= 7 && msg_index <= 8),
125            "Expected 2, 3, 4, 7 or 8, got %d\n", msg_index);
126         ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
127         ok(LOWORD(lparam) == CF_TEXT, "Expected CF_TEXT, got %d\n", LOWORD(lparam));
128
129         GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
130         if (msg_index < 8)
131             ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
132         else
133             ok(!lstrcmpA(str, "executed"), "Expected executed, got %s\n", str);
134
135         if (msg_index == 8)
136         {
137             if (executed)
138                 lstrcpyA(str, "command executed\r\n");
139             else
140                 lstrcpyA(str, "command not executed\r\n");
141         }
142         else
143             lstrcpyA(str, "requested data\r\n");
144
145         size = sizeof(DDEDATA) + lstrlenA(str) + 1;
146         hglobal = GlobalAlloc(GMEM_MOVEABLE, size);
147         ok(hglobal != NULL, "Expected non-NULL hglobal\n");
148
149         data = GlobalLock(hglobal);
150         ZeroMemory(data, size);
151
152         /* setting fResponse to FALSE at this point destroys
153          * the internal messaging state of native dde
154          */
155         data->fResponse = TRUE;
156
157         if (msg_index == 2)
158             data->fRelease = TRUE;
159         else if (msg_index == 3)
160             data->fAckReq = TRUE;
161
162         data->cfFormat = CF_TEXT;
163         lstrcpyA((LPSTR)data->Value, str);
164         GlobalUnlock(hglobal);
165
166         lparam = PackDDElParam(WM_DDE_DATA, (UINT_PTR)hglobal, HIWORD(lparam));
167         PostMessageA(client, WM_DDE_DATA, (WPARAM)hwnd, lparam);
168
169         break;
170     }
171
172     case WM_DDE_POKE:
173     {
174         ok(msg_index == 5 || msg_index == 6, "Expected 5 or 6, got %d\n", msg_index);
175         ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
176
177         UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi);
178
179         GlobalGetAtomNameA(hi, str, MAX_PATH);
180         ok(!lstrcmpA(str, "poker"), "Expected poker, got %s\n", str);
181
182         poke = GlobalLock((HGLOBAL)lo);
183         ok(poke != NULL, "Expected non-NULL poke\n");
184         ok(poke->fReserved == 0, "Expected 0, got %d\n", poke->fReserved);
185         ok(poke->unused == 0, "Expected 0, got %d\n", poke->unused);
186         ok(poke->fRelease == TRUE, "Expected TRUE, got %d\n", poke->fRelease);
187         ok(poke->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", poke->cfFormat);
188
189         if (msg_index == 5)
190         {
191             size = GlobalSize((HGLOBAL)lo);
192             ok(size == 4 || broken(size == 32), /* sizes are rounded up on win9x */ "got %d\n", size);
193         }
194         else
195             ok(!lstrcmpA((LPSTR)poke->Value, "poke data\r\n"),
196                "Expected 'poke data\\r\\n', got %s\n", poke->Value);
197
198         GlobalUnlock((HGLOBAL)lo);
199
200         lparam = PackDDElParam(WM_DDE_ACK, DDE_FACK, hi);
201         PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
202
203         break;
204     }
205
206     case WM_DDE_EXECUTE:
207     {
208         ok(msg_index == 7, "Expected 7, got %d\n", msg_index);
209         ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
210
211         ptr = GlobalLock((HGLOBAL)lparam);
212         ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected [Command(Var)], got %s\n", ptr);
213         GlobalUnlock((HGLOBAL)lparam);
214
215         executed = TRUE;
216
217         lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, DDE_FACK, lparam);
218         PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
219
220         break;
221     }
222
223     case WM_DDE_TERMINATE:
224     {
225         ok(msg_index == 9, "Expected 9, got %d\n", msg_index);
226         ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
227         ok(lparam == 0, "Expected 0, got %08lx\n", lparam);
228
229         PostMessageA(client, WM_DDE_TERMINATE, (WPARAM)hwnd, 0);
230
231         break;
232     }
233
234     case WM_DDE_ACK:  /* happens on win9x when fAckReq is TRUE, ignore it */
235         ok(msg_index == 4, "Expected 4, got %d\n", msg_index);
236         msg_index--;
237         break;
238
239     default:
240         ok(FALSE, "Unhandled msg: %08x\n", msg);
241     }
242
243     return DefWindowProcA(hwnd, msg, wparam, lparam);
244 }
245
246 static void test_msg_server(HANDLE hproc, HANDLE hthread)
247 {
248     MSG msg;
249     HWND hwnd;
250     DWORD res;
251
252     create_dde_window(&hwnd, "dde_server", dde_server_wndproc);
253     ResumeThread( hthread );
254
255     while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
256     {
257         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
258     }
259
260     destroy_dde_window(&hwnd, "dde_server");
261     GetExitCodeProcess( hproc, &res );
262     ok( !res, "client failed with %u error(s)\n", res );
263 }
264
265 static HDDEDATA CALLBACK client_ddeml_callback(UINT uType, UINT uFmt, HCONV hconv,
266                                                HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
267                                                ULONG_PTR dwData1, ULONG_PTR dwData2)
268 {
269     ok(FALSE, "Unhandled msg: %08x\n", uType);
270     return 0;
271 }
272
273 static void test_ddeml_client(void)
274 {
275     UINT ret;
276     char buffer[32];
277     LPSTR str;
278     DWORD size, res;
279     HDDEDATA hdata, op;
280     HSZ server, topic, item;
281     DWORD client_pid;
282     HCONV conversation;
283
284     client_pid = 0;
285     ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
286     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
287
288     /* FIXME: make these atoms global and check them in the server */
289
290     server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI);
291     topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI);
292
293     DdeGetLastError(client_pid);
294     conversation = DdeConnect(client_pid, server, topic, NULL);
295     ok(conversation != NULL, "Expected non-NULL conversation\n");
296     ret = DdeGetLastError(client_pid);
297     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
298
299     DdeFreeStringHandle(client_pid, server);
300
301     item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI);
302
303     /* XTYP_REQUEST, fRelease = TRUE */
304     res = 0xdeadbeef;
305     DdeGetLastError(client_pid);
306     hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
307     ret = DdeGetLastError(client_pid);
308     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
309     ok(res == DDE_FNOTPROCESSED || broken(res == 0xdeadbeef), /* win9x */
310        "Expected DDE_FNOTPROCESSED, got %08x\n", res);
311     ok( hdata != NULL, "hdata is NULL\n" );
312     if (hdata)
313     {
314         str = (LPSTR)DdeAccessData(hdata, &size);
315         ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
316         ok(size == 19 || broken(size == 28), /* sizes are rounded up on win9x */
317            "Expected 19, got %d\n", size);
318
319         ret = DdeUnaccessData(hdata);
320         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
321     }
322
323     /* XTYP_REQUEST, fAckReq = TRUE */
324     res = 0xdeadbeef;
325     DdeGetLastError(client_pid);
326     hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
327     ret = DdeGetLastError(client_pid);
328     ok(res == DDE_FNOTPROCESSED || broken(res == 0xdeadbeef), /* win9x */
329        "Expected DDE_FNOTPROCESSED, got %x\n", res);
330 todo_wine
331     ok(ret == DMLERR_MEMORY_ERROR || broken(ret == 0), /* win9x */
332        "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
333     ok( hdata != NULL, "hdata is NULL\n" );
334     if (hdata)
335     {
336         str = (LPSTR)DdeAccessData(hdata, &size);
337         ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
338         ok(size == 19 || broken(size == 28), /* sizes are rounded up on win9x */
339            "Expected 19, got %d\n", size);
340
341         ret = DdeUnaccessData(hdata);
342         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
343     }
344
345     /* XTYP_REQUEST, all params normal */
346     res = 0xdeadbeef;
347     DdeGetLastError(client_pid);
348     hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
349     ret = DdeGetLastError(client_pid);
350     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
351     ok(res == DDE_FNOTPROCESSED || broken(res == 0xdeadbeef), /* win9x */
352        "Expected DDE_FNOTPROCESSED, got %x\n", res);
353     if (hdata == NULL)
354         ok(FALSE, "hdata is NULL\n");
355     else
356     {
357         str = (LPSTR)DdeAccessData(hdata, &size);
358         ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
359         ok(size == 19 || broken(size == 28), /* sizes are rounded up on win9x */
360            "Expected 19, got %d\n", size);
361
362         ret = DdeUnaccessData(hdata);
363         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
364     }
365
366     /* XTYP_REQUEST, no item */
367     res = 0xdeadbeef;
368     DdeGetLastError(client_pid);
369     hdata = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
370     ret = DdeGetLastError(client_pid);
371     ok(hdata == NULL, "Expected NULL hdata, got %p\n", hdata);
372     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res);
373     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
374
375     DdeFreeStringHandle(client_pid, item);
376
377     item = DdeCreateStringHandleA(client_pid, "poker", CP_WINANSI);
378
379     lstrcpyA(buffer, "poke data\r\n");
380     hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
381                                 0, item, CF_TEXT, 0);
382     ok(hdata != NULL, "Expected non-NULL hdata\n");
383
384     /* XTYP_POKE, no item */
385     res = 0xdeadbeef;
386     DdeGetLastError(client_pid);
387     op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
388     ret = DdeGetLastError(client_pid);
389     ok(op == NULL, "Expected NULL, got %p\n", op);
390     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
391     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
392
393     /* XTYP_POKE, no data */
394     res = 0xdeadbeef;
395     DdeGetLastError(client_pid);
396     op = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
397     ret = DdeGetLastError(client_pid);
398     ok(op == NULL, "Expected NULL, got %p\n", op);
399     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
400     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
401
402     /* XTYP_POKE, wrong size */
403     res = 0xdeadbeef;
404     DdeGetLastError(client_pid);
405     op = DdeClientTransaction((LPBYTE)hdata, 0, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
406     ret = DdeGetLastError(client_pid);
407     ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
408     ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
409        "Expected DDE_FACK, got %x\n", res);
410     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
411
412     /* XTYP_POKE, correct params */
413     res = 0xdeadbeef;
414     DdeGetLastError(client_pid);
415     op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
416     ret = DdeGetLastError(client_pid);
417     ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
418     ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
419        "Expected DDE_FACK, got %x\n", res);
420     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
421
422     DdeFreeDataHandle(hdata);
423
424     lstrcpyA(buffer, "[Command(Var)]");
425     hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
426                                 0, NULL, CF_TEXT, 0);
427     ok(hdata != NULL, "Expected non-NULL hdata\n");
428
429     /* XTYP_EXECUTE, correct params */
430     res = 0xdeadbeef;
431     DdeGetLastError(client_pid);
432     op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
433     ret = DdeGetLastError(client_pid);
434     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
435     ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
436     ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
437        "Expected DDE_FACK, got %x\n", res);
438
439     /* XTYP_EXECUTE, no data */
440     res = 0xdeadbeef;
441     DdeGetLastError(client_pid);
442     op = DdeClientTransaction(NULL, 0, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
443     ret = DdeGetLastError(client_pid);
444     ok(op == NULL || broken(op == (HDDEDATA)TRUE), /* win9x */ "Expected NULL, got %p\n", op);
445     if (!op)
446     {
447         ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
448         ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
449     }
450     else  /* win9x */
451     {
452         ok(res == (0xdead0000 | DDE_FACK), "Expected DDE_FACK, got %x\n", res);
453         ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
454     }
455
456     /* XTYP_EXECUTE, no data, -1 size */
457     res = 0xdeadbeef;
458     DdeGetLastError(client_pid);
459     op = DdeClientTransaction(NULL, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
460     ret = DdeGetLastError(client_pid);
461     ok(op == NULL, "Expected NULL, got %p\n", op);
462     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
463     ok(ret == DMLERR_INVALIDPARAMETER || broken(ret == DMLERR_NO_ERROR), /* win9x */
464        "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
465
466     DdeFreeStringHandle(client_pid, topic);
467     DdeFreeDataHandle(hdata);
468
469     item = DdeCreateStringHandleA(client_pid, "executed", CP_WINANSI);
470
471     /* verify the execute */
472     res = 0xdeadbeef;
473     DdeGetLastError(client_pid);
474     hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
475     ret = DdeGetLastError(client_pid);
476     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
477     ok(res == DDE_FNOTPROCESSED || broken(res == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
478        "Expected DDE_FNOTPROCESSED, got %d\n", res);
479     if (hdata == NULL)
480         ok(FALSE, "hdata is NULL\n");
481     else
482     {
483         str = (LPSTR)DdeAccessData(hdata, &size);
484         ok(!lstrcmpA(str, "command executed\r\n"), "Expected 'command executed\\r\\n', got %s\n", str);
485         ok(size == 21 || broken(size == 28), /* sizes are rounded up on win9x */
486            "Expected 21, got %d\n", size);
487
488         ret = DdeUnaccessData(hdata);
489         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
490     }
491
492     /* invalid transactions */
493     res = 0xdeadbeef;
494     DdeGetLastError(client_pid);
495     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ADVREQ, default_timeout, &res);
496     ret = DdeGetLastError(client_pid);
497     ok(op == NULL, "Expected NULL, got %p\n", op);
498     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
499     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
500
501     res = 0xdeadbeef;
502     DdeGetLastError(client_pid);
503     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT, default_timeout, &res);
504     ret = DdeGetLastError(client_pid);
505     ok(op == NULL, "Expected NULL, got %p\n", op);
506     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
507     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
508
509     res = 0xdeadbeef;
510     DdeGetLastError(client_pid);
511     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT_CONFIRM, default_timeout, &res);
512     ret = DdeGetLastError(client_pid);
513     ok(op == NULL, "Expected NULL, got %p\n", op);
514     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
515     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
516
517     res = 0xdeadbeef;
518     DdeGetLastError(client_pid);
519     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_DISCONNECT, default_timeout, &res);
520     ret = DdeGetLastError(client_pid);
521     ok(op == NULL, "Expected NULL, got %p\n", op);
522     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
523     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
524
525     res = 0xdeadbeef;
526     DdeGetLastError(client_pid);
527     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ERROR, default_timeout, &res);
528     ret = DdeGetLastError(client_pid);
529     ok(op == NULL, "Expected NULL, got %p\n", op);
530     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
531     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
532
533     res = 0xdeadbeef;
534     DdeGetLastError(client_pid);
535     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_MONITOR, default_timeout, &res);
536     ret = DdeGetLastError(client_pid);
537     ok(op == NULL, "Expected NULL, got %p\n", op);
538     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
539     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
540
541     res = 0xdeadbeef;
542     DdeGetLastError(client_pid);
543     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REGISTER, default_timeout, &res);
544     ret = DdeGetLastError(client_pid);
545     ok(op == NULL, "Expected NULL, got %p\n", op);
546     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
547     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
548
549     res = 0xdeadbeef;
550     DdeGetLastError(client_pid);
551     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_UNREGISTER, default_timeout, &res);
552     ret = DdeGetLastError(client_pid);
553     ok(op == NULL, "Expected NULL, got %p\n", op);
554     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
555     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
556
557     res = 0xdeadbeef;
558     DdeGetLastError(client_pid);
559     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_WILDCONNECT, default_timeout, &res);
560     ret = DdeGetLastError(client_pid);
561     ok(op == NULL, "Expected NULL, got %p\n", op);
562     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
563     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
564
565     res = 0xdeadbeef;
566     DdeGetLastError(client_pid);
567     op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_XACT_COMPLETE, default_timeout, &res);
568     ret = DdeGetLastError(client_pid);
569     ok(op == NULL, "Expected NULL, got %p\n", op);
570     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
571     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
572
573     DdeFreeStringHandle(client_pid, item);
574
575     ret = DdeDisconnect(conversation);
576     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
577
578     ret = DdeUninitialize(client_pid);
579     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
580 }
581
582 static DWORD server_pid;
583
584 static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hconv,
585                                                HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
586                                                ULONG_PTR dwData1, ULONG_PTR dwData2)
587 {
588     char str[MAX_PATH], *ptr;
589     HDDEDATA ret = NULL;
590     DWORD size;
591
592     static int msg_index = 0;
593     static HCONV conversation = 0;
594
595     msg_index++;
596
597     switch (uType)
598     {
599     case XTYP_REGISTER:
600     {
601         ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
602         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
603         ok(hconv == 0, "Expected 0, got %p\n", hconv);
604         ok(hdata == 0, "Expected 0, got %p\n", hdata);
605         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
606         ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
607
608         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
609         ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
610         ok(size == 13, "Expected 13, got %d\n", size);
611
612         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
613         if (!strncmp( str, "TestDDEServer:(", 15 ))  /* win9x style */
614         {
615             ok(size == 16 + 2*sizeof(WORD), "Got size %d for %s\n", size, str);
616         }
617         else
618         {
619             ok(!strncmp(str, "TestDDEServer(", 14), "Expected TestDDEServer(, got %s\n", str);
620             ok(size == 17 + 2*sizeof(ULONG_PTR), "Got size %d for %s\n", size, str);
621         }
622             ok(str[size - 1] == ')', "Expected ')', got %c\n", str[size - 1]);
623
624         return (HDDEDATA)TRUE;
625     }
626
627     case XTYP_CONNECT:
628     {
629         ok(msg_index == 2, "Expected 2, got %d\n", msg_index);
630         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
631         ok(hconv == 0, "Expected 0, got %p\n", hconv);
632         ok(hdata == 0, "Expected 0, got %p\n", hdata);
633         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
634         ok(dwData2 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
635
636         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
637         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
638         ok(size == 12, "Expected 12, got %d\n", size);
639
640         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
641         ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
642         ok(size == 13, "Expected 13, got %d\n", size);
643
644         return (HDDEDATA)TRUE;
645     }
646
647     case XTYP_CONNECT_CONFIRM:
648     {
649         conversation = hconv;
650
651         ok(msg_index == 3, "Expected 3, got %d\n", msg_index);
652         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
653         ok(hconv != NULL, "Expected non-NULL hconv\n");
654         ok(hdata == 0, "Expected 0, got %p\n", hdata);
655         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
656         ok(dwData2 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
657
658         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
659         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
660         ok(size == 12, "Expected 12, got %d\n", size);
661
662         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
663         ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
664         ok(size == 13, "Expected 13, got %d\n", size);
665
666         return (HDDEDATA)TRUE;
667     }
668
669     case XTYP_REQUEST:
670     {
671         ok(msg_index == 4 || msg_index == 5 || msg_index == 6,
672            "Expected 4, 5 or 6, got %d\n", msg_index);
673         ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
674         ok(hdata == 0, "Expected 0, got %p\n", hdata);
675         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
676         ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
677
678         if (msg_index == 4)
679             ok(uFmt == 0xbeef, "Expected 0xbeef, got %08x\n", uFmt);
680         else
681             ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %08x\n", uFmt);
682
683         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
684         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
685         ok(size == 12, "Expected 12, got %d\n", size);
686
687         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
688
689         if (msg_index == 5)
690         {
691             {
692                 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
693                 ok(size == 1, "Expected 1, got %d\n", size);
694             }
695         }
696         else if (msg_index == 6)
697         {
698             ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
699             ok(size == 7, "Expected 7, got %d\n", size);
700         }
701
702         if (msg_index == 6)
703         {
704             lstrcpyA(str, "requested data\r\n");
705             return DdeCreateDataHandle(server_pid, (LPBYTE)str, lstrlenA(str) + 1,
706                                         0, hsz2, CF_TEXT, 0);
707         }
708
709         return NULL;
710     }
711
712     case XTYP_POKE:
713     {
714         ok(msg_index == 7 || msg_index == 8, "Expected 7 or 8, got %d\n", msg_index);
715         ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %d\n", uFmt);
716         ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
717         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
718         ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
719
720         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
721         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
722         ok(size == 12, "Expected 12, got %d\n", size);
723
724         ptr = (LPSTR)DdeAccessData(hdata, &size);
725         ok(!lstrcmpA(ptr, "poke data\r\n"), "Expected 'poke data\\r\\n', got %s\n", ptr);
726         ok(size == 12 || broken(size == 28), /* sizes are rounded up on win9x */
727            "Expected 12, got %d\n", size);
728         DdeUnaccessData(hdata);
729
730         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
731         if (msg_index == 7)
732         {
733             {
734                 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
735                 ok(size == 1, "Expected 1, got %d\n", size);
736             }
737         }
738         else
739         {
740             ok(!lstrcmpA(str, "poke"), "Expected poke, got %s\n", str);
741             ok(size == 4, "Expected 4, got %d\n", size);
742         }
743
744         return (HDDEDATA)DDE_FACK;
745     }
746
747     case XTYP_EXECUTE:
748     {
749         ok(msg_index >= 9 && msg_index <= 11, "Expected 9 or 11, got %d\n", msg_index);
750         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
751         ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
752         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
753         ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
754         ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
755
756         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
757         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
758         ok(size == 12, "Expected 12, got %d\n", size);
759
760         if (msg_index == 9 || msg_index == 11)
761         {
762             ptr = (LPSTR)DdeAccessData(hdata, &size);
763
764             if (msg_index == 9)
765             {
766                 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected '[Command(Var)]', got %s\n", ptr);
767                 ok(size == 15, "Expected 15, got %d\n", size);
768                 ret = (HDDEDATA)DDE_FACK;
769             }
770             else
771             {
772                 ok(!lstrcmpA(ptr, "[BadCommand(Var)]"), "Expected '[BadCommand(Var)]', got %s\n", ptr);
773                 ok(size == 18, "Expected 18, got %d\n", size);
774                 ret = DDE_FNOTPROCESSED;
775             }
776
777             DdeUnaccessData(hdata);
778         }
779         else if (msg_index == 10)
780         {
781             DWORD rsize = 0;
782             size = 0;
783
784             size = DdeGetData(hdata, NULL, 0, 0);
785             ok(size == 17, "DdeGetData should have returned 17 not %d\n", size);
786             ptr = HeapAlloc(GetProcessHeap(), 0, size);
787             ok(ptr != NULL,"HeapAlloc should have returned ptr not NULL\n");
788             rsize = DdeGetData(hdata, (LPBYTE)ptr, size, 0);
789             ok(rsize == size, "DdeGetData did not return %d bytes but %d\n", size, rsize);
790
791             ok(!lstrcmpA(ptr, "[Command-2(Var)]"), "Expected '[Command-2(Var)]' got %s\n", ptr);
792             ok(size == 17, "Expected 17, got %d\n", size);
793             ret = (HDDEDATA)DDE_FACK;
794
795             HeapFree(GetProcessHeap(), 0, ptr);
796         }
797
798         return ret;
799     }
800
801     case XTYP_DISCONNECT:
802     {
803         ok(msg_index == 12, "Expected 12, got %d\n", msg_index);
804         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
805         ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
806         ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
807         ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
808         ok(hsz1 == 0, "Expected 0, got %p\n", hsz2);
809         ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
810
811         return 0;
812     }
813
814     default:
815         ok(FALSE, "Unhandled msg: %08x\n", uType);
816     }
817
818     return 0;
819 }
820
821 static void test_ddeml_server(HANDLE hproc)
822 {
823     MSG msg;
824     UINT res;
825     BOOL ret;
826     HSZ server;
827     HDDEDATA hdata;
828
829     /* set up DDE server */
830     server_pid = 0;
831     res = DdeInitialize(&server_pid, server_ddeml_callback, APPCLASS_STANDARD, 0);
832     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
833
834     server = DdeCreateStringHandle(server_pid, "TestDDEServer", CP_WINANSI);
835     ok(server != NULL, "Expected non-NULL string handle\n");
836
837     hdata = DdeNameService(server_pid, server, 0, DNS_REGISTER);
838     ok(hdata == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", hdata);
839
840     while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
841     {
842         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
843     }
844     ret = DdeUninitialize(server_pid);
845     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
846     GetExitCodeProcess( hproc, &res );
847     ok( !res, "client failed with %u error(s)\n", res );
848 }
849
850 static HWND client_hwnd, server_hwnd;
851 static ATOM server, topic, item;
852 static HGLOBAL execute_hglobal;
853
854 static LRESULT WINAPI dde_msg_client_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
855 {
856     char str[MAX_PATH];
857     UINT_PTR lo, hi;
858     DDEDATA *data;
859     DDEACK *ack;
860     DWORD size;
861     LPSTR ptr;
862
863     static int msg_index = 0;
864
865     if (msg < WM_DDE_FIRST || msg > WM_DDE_LAST)
866         return DefWindowProcA(hwnd, msg, wparam, lparam);
867
868     msg_index++;
869
870     switch (msg)
871     {
872     case WM_DDE_INITIATE:
873     {
874         ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
875         ok(wparam == (WPARAM)client_hwnd, "Expected client hwnd, got %08lx\n", wparam);
876
877         size = GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
878         ok(LOWORD(lparam) == server, "Expected server atom, got %08x\n", LOWORD(lparam));
879         ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
880         ok(size == 13, "Expected 13, got %d\n", size);
881
882         size = GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
883         ok(HIWORD(lparam) == topic, "Expected topic atom, got %08x\n", HIWORD(lparam));
884         ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
885         ok(size == 12, "Expected 12, got %d\n", size);
886
887         break;
888     }
889
890     case WM_DDE_ACK:
891     {
892         ok((msg_index >= 2 && msg_index <= 4) || (msg_index >= 6 && msg_index <= 11),
893            "Expected 2, 3, 4, 6, 7, 8, 9, 10 or 11, got %d\n", msg_index);
894
895         if (msg_index == 2)
896         {
897             server_hwnd = (HWND)wparam;
898             ok(wparam != 0, "Expected non-NULL wparam, got %08lx\n", wparam);
899
900             size = GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
901             ok(LOWORD(lparam) == server, "Expected server atom, got %08x\n", LOWORD(lparam));
902             ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
903             ok(size == 13, "Expected 13, got %d\n", size);
904
905             size = GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
906             ok(HIWORD(lparam) == topic, "Expected topic atom, got %08x\n", HIWORD(lparam));
907             ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
908             ok(size == 12, "Expected 12, got %d\n", size);
909         }
910         else if (msg_index >= 9 && msg_index <= 11)
911         {
912             ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
913
914             UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
915
916             ack = (DDEACK *)&lo;
917             ok(ack->bAppReturnCode == 0, "Expected 0, got %d\n", ack->bAppReturnCode);
918             ok(ack->reserved == 0, "Expected 0, got %d\n", ack->reserved);
919             ok(ack->fBusy == FALSE, "Expected FALSE, got %d\n", ack->fBusy);
920
921             ok(hi == (UINT_PTR)execute_hglobal, "Expected execute hglobal, got %08lx\n", hi);
922             ptr = GlobalLock((HGLOBAL)hi);
923
924             if (msg_index == 9)
925             {
926                 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
927                 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected '[Command(Var)]', got %s\n", ptr);
928             } else if (msg_index == 10)
929             {
930                 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
931                 ok(!lstrcmpA(ptr, "[Command-2(Var)]"), "Expected '[Command-2(Var)]', got %s\n", ptr);
932             }
933             else
934             {
935                 ok(ack->fAck == FALSE, "Expected FALSE, got %d\n", ack->fAck);
936                 ok(!lstrcmpA(ptr, "[BadCommand(Var)]"), "Expected '[BadCommand(Var)]', got %s\n", ptr);
937             }
938
939             GlobalUnlock((HGLOBAL)hi);
940         }
941         else
942         {
943             ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
944
945             UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
946
947             ack = (DDEACK *)&lo;
948             ok(ack->bAppReturnCode == 0, "Expected 0, got %d\n", ack->bAppReturnCode);
949             ok(ack->reserved == 0, "Expected 0, got %d\n", ack->reserved);
950             ok(ack->fBusy == FALSE, "Expected FALSE, got %d\n", ack->fBusy);
951
952             if (msg_index >= 7)
953                 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
954             else
955             {
956                 if (msg_index == 6) todo_wine
957                 ok(ack->fAck == FALSE, "Expected FALSE, got %d\n", ack->fAck);
958             }
959
960             size = GlobalGetAtomNameA(hi, str, MAX_PATH);
961             if (msg_index == 3)
962             {
963                 ok(hi == item, "Expected item atom, got %08lx\n", hi);
964                 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
965                 ok(size == 7, "Expected 7, got %d\n", size);
966             }
967             else if (msg_index == 4 || msg_index == 7)
968             {
969                 ok(hi == 0, "Expected 0, got %08lx\n", hi);
970                 ok(size == 0, "Expected empty string, got %d\n", size);
971             }
972             else
973             {
974                 ok(hi == item, "Expected item atom, got %08lx\n", hi);
975                 if (msg_index == 6) todo_wine
976                 {
977                     ok(!lstrcmpA(str, "poke"), "Expected poke, got %s\n", str);
978                     ok(size == 4, "Expected 4, got %d\n", size);
979                 }
980             }
981         }
982
983         break;
984     }
985
986     case WM_DDE_DATA:
987     {
988         ok(msg_index == 5, "Expected 5, got %d\n", msg_index);
989         ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
990
991         UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi);
992
993         data = GlobalLock((HGLOBAL)lo);
994         ok(data->unused == 0, "Expected 0, got %d\n", data->unused);
995         ok(data->fResponse == TRUE, "Expected TRUE, got %d\n", data->fResponse);
996         todo_wine
997         {
998             ok(data->fRelease == TRUE, "Expected TRUE, got %d\n", data->fRelease);
999         }
1000         ok(data->fAckReq == 0, "Expected 0, got %d\n", data->fAckReq);
1001         ok(data->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", data->cfFormat);
1002         ok(!lstrcmpA((LPSTR)data->Value, "requested data\r\n"),
1003            "Expeted 'requested data\\r\\n', got %s\n", data->Value);
1004         GlobalUnlock((HGLOBAL)lo);
1005
1006         size = GlobalGetAtomNameA(hi, str, MAX_PATH);
1007         ok(hi == item, "Expected item atom, got %08x\n", HIWORD(lparam));
1008         ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
1009         ok(size == 7, "Expected 7, got %d\n", size);
1010
1011         GlobalFree((HGLOBAL)lo);
1012         GlobalDeleteAtom(hi);
1013
1014         break;
1015     }
1016
1017     default:
1018         ok(FALSE, "Unhandled msg: %08x\n", msg);
1019     }
1020
1021     return DefWindowProcA(hwnd, msg, wparam, lparam);
1022 }
1023
1024 static HGLOBAL create_poke(void)
1025 {
1026     HGLOBAL hglobal;
1027     DDEPOKE *poke;
1028     DWORD size;
1029
1030     size = FIELD_OFFSET(DDEPOKE, Value[sizeof("poke data\r\n")]);
1031     hglobal = GlobalAlloc(GMEM_DDESHARE, size);
1032     ok(hglobal != 0, "Expected non-NULL hglobal\n");
1033
1034     poke = GlobalLock(hglobal);
1035     poke->unused = 0;
1036     poke->fRelease = TRUE;
1037     poke->fReserved = TRUE;
1038     poke->cfFormat = CF_TEXT;
1039     lstrcpyA((LPSTR)poke->Value, "poke data\r\n");
1040     GlobalUnlock(hglobal);
1041
1042     return hglobal;
1043 }
1044
1045 static HGLOBAL create_execute(LPCSTR command)
1046 {
1047     HGLOBAL hglobal;
1048     LPSTR ptr;
1049
1050     hglobal = GlobalAlloc(GMEM_DDESHARE, lstrlenA(command) + 1);
1051     ok(hglobal != 0, "Expected non-NULL hglobal\n");
1052
1053     ptr = GlobalLock(hglobal);
1054     lstrcpyA(ptr, command);
1055     GlobalUnlock(hglobal);
1056
1057     return hglobal;
1058 }
1059
1060 static void test_msg_client(void)
1061 {
1062     HGLOBAL hglobal;
1063     LPARAM lparam;
1064
1065     create_dde_window(&client_hwnd, "dde_client", dde_msg_client_wndproc);
1066
1067     server = GlobalAddAtomA("TestDDEServer");
1068     ok(server != 0, "Expected non-NULL server\n");
1069
1070     topic = GlobalAddAtomA("TestDDETopic");
1071     ok(topic != 0, "Expected non-NULL topic\n");
1072
1073     SendMessageA(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)client_hwnd, MAKELONG(server, topic));
1074
1075     GlobalDeleteAtom(server);
1076     GlobalDeleteAtom(topic);
1077
1078     flush_events();
1079
1080     item = GlobalAddAtom("request");
1081     ok(item != 0, "Expected non-NULL item\n");
1082
1083     /* WM_DDE_REQUEST, bad clipboard format */
1084     lparam = PackDDElParam(WM_DDE_REQUEST, 0xdeadbeef, item);
1085     PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1086
1087     flush_events();
1088
1089     /* WM_DDE_REQUEST, no item */
1090     lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, 0);
1091     PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1092
1093     flush_events();
1094
1095     /* WM_DDE_REQUEST, no client hwnd */
1096     lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, item);
1097     PostMessageA(server_hwnd, WM_DDE_REQUEST, 0, lparam);
1098
1099     flush_events();
1100
1101     /* WM_DDE_REQUEST, correct params */
1102     lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, item);
1103     PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1104
1105     flush_events();
1106
1107     GlobalDeleteAtom(item);
1108     item = GlobalAddAtomA("poke");
1109     ok(item != 0, "Expected non-NULL item\n");
1110
1111     hglobal = create_poke();
1112
1113     /* WM_DDE_POKE, no ddepoke */
1114     lparam = PackDDElParam(WM_DDE_POKE, 0, item);
1115     /* win9x returns 0 here and crashes in PostMessageA */
1116     if (lparam) {
1117         PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1118         flush_events();
1119     }
1120     else
1121         win_skip("no lparam for WM_DDE_POKE\n");
1122
1123
1124     /* WM_DDE_POKE, no item */
1125     lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, 0);
1126     PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1127
1128     flush_events();
1129
1130     hglobal = create_poke();
1131
1132     /* WM_DDE_POKE, no client hwnd */
1133     lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, item);
1134     PostMessageA(server_hwnd, WM_DDE_POKE, 0, lparam);
1135
1136     flush_events();
1137
1138     /* WM_DDE_POKE, all params correct */
1139     lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, item);
1140     PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1141
1142     flush_events();
1143
1144     execute_hglobal = create_execute("[Command(Var)]");
1145
1146     /* WM_DDE_EXECUTE, no lparam */
1147     PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, 0);
1148
1149     flush_events();
1150
1151     /* WM_DDE_EXECUTE, no hglobal */
1152     lparam = PackDDElParam(WM_DDE_EXECUTE, 0, 0);
1153     PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1154
1155     flush_events();
1156
1157     /* WM_DDE_EXECUTE, no client hwnd */
1158     lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1159     PostMessageA(server_hwnd, WM_DDE_EXECUTE, 0, lparam);
1160
1161     flush_events();
1162
1163     /* WM_DDE_EXECUTE, all params correct */
1164     lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1165     PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1166
1167     flush_events();
1168
1169     GlobalFree(execute_hglobal);
1170     execute_hglobal = create_execute("[Command-2(Var)]");
1171
1172     /* WM_DDE_EXECUTE, all params correct */
1173     lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1174     PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1175
1176     flush_events();
1177
1178     GlobalFree(execute_hglobal);
1179     execute_hglobal = create_execute("[BadCommand(Var)]");
1180
1181     /* WM_DDE_EXECUTE that will get rejected */
1182     lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1183     PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1184
1185     flush_events();
1186
1187     destroy_dde_window(&client_hwnd, "dde_client");
1188 }
1189
1190 static LRESULT WINAPI hook_dde_client_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1191 {
1192     UINT_PTR lo, hi;
1193
1194     trace("hook_dde_client_wndprocA: %p %04x %08lx %08lx\n", hwnd, msg, wparam, lparam);
1195
1196     switch (msg)
1197     {
1198     case WM_DDE_ACK:
1199         UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
1200         trace("WM_DDE_ACK: status %04lx hglobal %p\n", lo, (HGLOBAL)hi);
1201         break;
1202
1203     default:
1204         break;
1205     }
1206     return CallWindowProcA(old_dde_client_wndproc, hwnd, msg, wparam, lparam);
1207 }
1208
1209 static LRESULT WINAPI hook_dde_client_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1210 {
1211     UINT_PTR lo, hi;
1212
1213     trace("hook_dde_client_wndprocW: %p %04x %08lx %08lx\n", hwnd, msg, wparam, lparam);
1214
1215     switch (msg)
1216     {
1217     case WM_DDE_ACK:
1218         UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
1219         trace("WM_DDE_ACK: status %04lx hglobal %p\n", lo, (HGLOBAL)hi);
1220         break;
1221
1222     default:
1223         break;
1224     }
1225     return CallWindowProcW(old_dde_client_wndproc, hwnd, msg, wparam, lparam);
1226 }
1227
1228 static LRESULT WINAPI dde_server_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1229 {
1230     static BOOL client_unicode, conv_unicode;
1231     static int step;
1232
1233     switch (msg)
1234     {
1235     case WM_DDE_INITIATE:
1236     {
1237         ATOM aService = GlobalAddAtomW(TEST_DDE_SERVICE);
1238
1239         trace("server A: got WM_DDE_INITIATE from %p (%s) with %08lx\n",
1240               (HWND)wparam, client_unicode ? "Unicode" : "ANSI", lparam);
1241
1242         if (LOWORD(lparam) == aService)
1243         {
1244             client_unicode = IsWindowUnicode((HWND)wparam);
1245             conv_unicode = client_unicode;
1246             if (step >= 10) client_unicode = !client_unicode;  /* change the client window type */
1247
1248             if (client_unicode)
1249                 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrW((HWND)wparam, GWLP_WNDPROC,
1250                                                                     (ULONG_PTR)hook_dde_client_wndprocW);
1251             else
1252                 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrA((HWND)wparam, GWLP_WNDPROC,
1253                                                                     (ULONG_PTR)hook_dde_client_wndprocA);
1254             trace("server: sending WM_DDE_ACK to %p\n", (HWND)wparam);
1255             SendMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, PackDDElParam(WM_DDE_ACK, aService, 0));
1256         }
1257         else
1258             GlobalDeleteAtom(aService);
1259         return 0;
1260     }
1261
1262     case WM_DDE_EXECUTE:
1263     {
1264         DDEACK ack;
1265         WORD status;
1266         LPCSTR cmd;
1267         UINT_PTR lo, hi;
1268
1269         trace("server A: got WM_DDE_EXECUTE from %p with %08lx\n", (HWND)wparam, lparam);
1270
1271         UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
1272         trace("%08lx => lo %04lx hi %04lx\n", lparam, lo, hi);
1273
1274         ack.bAppReturnCode = 0;
1275         ack.reserved = 0;
1276         ack.fBusy = 0;
1277         /* We have to send a negative acknowledge even if we don't
1278          * accept the command, otherwise Windows goes mad and next time
1279          * we send an acknowledge DDEML drops the connection.
1280          * Not sure how to call it: a bug or a feature.
1281          */
1282         ack.fAck = 0;
1283
1284         if ((cmd = GlobalLock((HGLOBAL)hi)))
1285         {
1286             ack.fAck = !lstrcmpA(cmd, exec_cmdA) || !lstrcmpW((LPCWSTR)cmd, exec_cmdW);
1287
1288             switch (step % 5)
1289             {
1290             case 0:  /* bad command */
1291                 trace( "server A got unhandled command\n" );
1292                 break;
1293
1294             case 1:  /* ANSI command */
1295                 if (!conv_unicode)
1296                     ok( !lstrcmpA(cmd, exec_cmdA), "server A got wrong command '%s'\n", cmd );
1297                 else  /* we get garbage as the A command was mapped W->A */
1298                     ok( cmd[0] == '?', "server A got wrong command '%s'\n", cmd );
1299                 break;
1300
1301             case 2:  /* ANSI command in Unicode format */
1302                 if (conv_unicode)
1303                     ok( !lstrcmpA(cmd, exec_cmdA), "server A got wrong command '%s'\n", cmd );
1304                 else
1305                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server A got wrong command '%s'\n", cmd );
1306                 break;
1307
1308             case 3:  /* Unicode command */
1309                 if (!conv_unicode)
1310                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server A got wrong command '%s'\n", cmd );
1311                 else  /* correctly mapped W->A */
1312                     ok( !lstrcmpA(cmd, exec_cmdWA), "server A got wrong command '%s'\n", cmd );
1313                 break;
1314
1315             case 4:  /* Unicode command in ANSI format */
1316                 if (!conv_unicode)
1317                     ok( !lstrcmpA(cmd, exec_cmdWA), "server A got wrong command '%s'\n", cmd );
1318                 else  /* we get garbage as the A command was mapped W->A */
1319                     ok( cmd[0] == '?', "server A got wrong command '%s'\n", cmd );
1320                 break;
1321             }
1322             GlobalUnlock((HGLOBAL)hi);
1323         }
1324         else ok( 0, "bad command data %lx\n", hi );
1325
1326         step++;
1327         trace("server A: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1328
1329         status = *((WORD *)&ack);
1330         lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, status, hi);
1331
1332         PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1333         return 0;
1334     }
1335
1336     case WM_DDE_TERMINATE:
1337     {
1338         DDEACK ack;
1339         WORD status;
1340
1341         trace("server A: got WM_DDE_TERMINATE from %p with %08lx\n", (HWND)wparam, lparam);
1342
1343         ack.bAppReturnCode = 0;
1344         ack.reserved = 0;
1345         ack.fBusy = 0;
1346         ack.fAck = 1;
1347
1348         trace("server A: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1349
1350         status = *((WORD *)&ack);
1351         lparam = PackDDElParam(WM_DDE_ACK, status, 0);
1352
1353         PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1354         return 0;
1355     }
1356
1357     default:
1358         break;
1359     }
1360
1361     return DefWindowProcA(hwnd, msg, wparam, lparam);
1362 }
1363
1364 static LRESULT WINAPI dde_server_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1365 {
1366     static BOOL client_unicode, conv_unicode;
1367     static int step;
1368
1369     switch (msg)
1370     {
1371     case WM_DDE_INITIATE:
1372     {
1373         ATOM aService = GlobalAddAtomW(TEST_DDE_SERVICE);
1374
1375         if (LOWORD(lparam) == aService)
1376         {
1377             client_unicode = IsWindowUnicode((HWND)wparam);
1378             conv_unicode = client_unicode;
1379             if (step >= 10) client_unicode = !client_unicode;  /* change the client window type */
1380
1381             if (client_unicode)
1382                 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrW((HWND)wparam, GWLP_WNDPROC,
1383                                                                     (ULONG_PTR)hook_dde_client_wndprocW);
1384             else
1385                 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrA((HWND)wparam, GWLP_WNDPROC,
1386                                                                     (ULONG_PTR)hook_dde_client_wndprocA);
1387             trace("server W: sending WM_DDE_ACK to %p\n", (HWND)wparam);
1388             SendMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, PackDDElParam(WM_DDE_ACK, aService, 0));
1389         }
1390         else
1391             GlobalDeleteAtom(aService);
1392
1393         trace("server W: got WM_DDE_INITIATE from %p with %08lx (client %s conv %s)\n", (HWND)wparam,
1394               lparam, client_unicode ? "Unicode" : "ANSI", conv_unicode ? "Unicode" : "ANSI" );
1395
1396         return 0;
1397     }
1398
1399     case WM_DDE_EXECUTE:
1400     {
1401         DDEACK ack;
1402         WORD status;
1403         LPCSTR cmd;
1404         UINT_PTR lo, hi;
1405
1406         trace("server W: got WM_DDE_EXECUTE from %p with %08lx\n", (HWND)wparam, lparam);
1407
1408         UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
1409         trace("%08lx => lo %04lx hi %04lx\n", lparam, lo, hi);
1410
1411         ack.bAppReturnCode = 0;
1412         ack.reserved = 0;
1413         ack.fBusy = 0;
1414         /* We have to send a negative acknowledge even if we don't
1415          * accept the command, otherwise Windows goes mad and next time
1416          * we send an acknowledge DDEML drops the connection.
1417          * Not sure how to call it: a bug or a feature.
1418          */
1419         ack.fAck = 0;
1420
1421         if ((cmd = GlobalLock((HGLOBAL)hi)))
1422         {
1423             ack.fAck = !lstrcmpA(cmd, exec_cmdA) || !lstrcmpW((LPCWSTR)cmd, exec_cmdW);
1424
1425             switch (step % 5)
1426             {
1427             case 0:  /* bad command */
1428                 trace( "server W got unhandled command\n" );
1429                 break;
1430
1431             case 1:  /* ANSI command */
1432                 if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */
1433                     ok( cmd[0] == '?', "server W got wrong command '%s'\n", cmd );
1434                 else if (!conv_unicode && client_unicode)  /* A->W mapping */
1435                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server W got wrong command '%s'\n", cmd );
1436                 else
1437                     ok( !lstrcmpA(cmd, exec_cmdA), "server W got wrong command '%s'\n", cmd );
1438                 break;
1439
1440             case 2:  /* ANSI command in Unicode format */
1441                 if (conv_unicode && !client_unicode) /* W->A mapping */
1442                     ok( !lstrcmpA(cmd, exec_cmdA), "server W got wrong command '%s'\n", cmd );
1443                 else if (!conv_unicode && client_unicode)  /* A->W mapping */
1444                     ok( *(WCHAR *)cmd == exec_cmdAW[0], "server W got wrong command '%s'\n", cmd );
1445                 else
1446                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server W got wrong command '%s'\n", cmd );
1447                 break;
1448
1449             case 3:  /* Unicode command */
1450                 if (conv_unicode && !client_unicode) /* W->A mapping */
1451                     ok( !lstrcmpA(cmd, exec_cmdWA), "server W got wrong command '%s'\n", cmd );
1452                 else if (!conv_unicode && client_unicode)  /* A->W mapping */
1453                     ok( *(WCHAR *)cmd == exec_cmdW[0], "server W got wrong command '%s'\n", cmd );
1454                 else
1455                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server W got wrong command '%s'\n", cmd );
1456                 break;
1457
1458             case 4:  /* Unicode command in ANSI format */
1459                 if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */
1460                     ok( cmd[0] == '?', "server W got wrong command '%s'\n", cmd );
1461                 else if (!conv_unicode && client_unicode)  /* A->W mapping */
1462                     ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server W got wrong command '%s'\n", cmd );
1463                 else
1464                     ok( !lstrcmpA(cmd, exec_cmdWA), "server W got wrong command '%s'\n", cmd );
1465                 break;
1466             }
1467             GlobalUnlock((HGLOBAL)hi);
1468         }
1469         else ok( 0, "bad command data %lx\n", hi );
1470
1471         step++;
1472         trace("server W: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1473
1474         status = *((WORD *)&ack);
1475         lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, status, hi);
1476
1477         PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1478         return 0;
1479     }
1480
1481     case WM_DDE_TERMINATE:
1482     {
1483         DDEACK ack;
1484         WORD status;
1485
1486         trace("server W: got WM_DDE_TERMINATE from %p with %08lx\n", (HWND)wparam, lparam);
1487
1488         ack.bAppReturnCode = 0;
1489         ack.reserved = 0;
1490         ack.fBusy = 0;
1491         ack.fAck = 1;
1492
1493         trace("server W: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1494
1495         status = *((WORD *)&ack);
1496         lparam = PackDDElParam(WM_DDE_ACK, status, 0);
1497
1498         PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1499         return 0;
1500     }
1501
1502     default:
1503         break;
1504     }
1505
1506     return DefWindowProcW(hwnd, msg, wparam, lparam);
1507 }
1508
1509 static HWND create_dde_server( BOOL unicode )
1510 {
1511     WNDCLASSA wcA;
1512     WNDCLASSW wcW;
1513     HWND server;
1514     static const char server_class_nameA[] = "dde_server_windowA";
1515     static const WCHAR server_class_nameW[] = {'d','d','e','_','s','e','r','v','e','r','_','w','i','n','d','o','w','W',0};
1516
1517     if (unicode)
1518     {
1519         memset(&wcW, 0, sizeof(wcW));
1520         wcW.lpfnWndProc = dde_server_wndprocW;
1521         wcW.lpszClassName = server_class_nameW;
1522         wcW.hInstance = GetModuleHandleA(0);
1523         RegisterClassW(&wcW);
1524
1525         server = CreateWindowExW(0, server_class_nameW, NULL, WS_POPUP,
1526                                  100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1527                                  GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
1528     }
1529     else
1530     {
1531         memset(&wcA, 0, sizeof(wcA));
1532         wcA.lpfnWndProc = dde_server_wndprocA;
1533         wcA.lpszClassName = server_class_nameA;
1534         wcA.hInstance = GetModuleHandleA(0);
1535         RegisterClassA(&wcA);
1536
1537         server = CreateWindowExA(0, server_class_nameA, NULL, WS_POPUP,
1538                                  100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1539                                  GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
1540     }
1541     ok(!IsWindowUnicode(server) == !unicode, "wrong unicode type\n");
1542     return server;
1543 }
1544
1545 static HDDEDATA CALLBACK client_dde_callback(UINT uType, UINT uFmt, HCONV hconv,
1546                                      HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
1547                                      ULONG_PTR dwData1, ULONG_PTR dwData2)
1548 {
1549     static const char * const cmd_type[15] = {
1550         "XTYP_ERROR", "XTYP_ADVDATA", "XTYP_ADVREQ", "XTYP_ADVSTART",
1551         "XTYP_ADVSTOP", "XTYP_EXECUTE", "XTYP_CONNECT", "XTYP_CONNECT_CONFIRM",
1552         "XTYP_XACT_COMPLETE", "XTYP_POKE", "XTYP_REGISTER", "XTYP_REQUEST",
1553         "XTYP_DISCONNECT", "XTYP_UNREGISTER", "XTYP_WILDCONNECT" };
1554     UINT type;
1555     const char *cmd_name;
1556
1557     type = (uType & XTYP_MASK) >> XTYP_SHIFT;
1558     cmd_name = (type <= 14) ? cmd_type[type] : "unknown";
1559
1560     trace("client_dde_callback: %04x (%s) %d %p %p %p %p %08lx %08lx\n",
1561           uType, cmd_name, uFmt, hconv, hsz1, hsz2, hdata, dwData1, dwData2);
1562     return 0;
1563 }
1564
1565 static void test_dde_aw_transaction( BOOL client_unicode, BOOL server_unicode )
1566 {
1567     HSZ hsz_server;
1568     DWORD dde_inst, ret, err;
1569     HCONV hconv;
1570     HWND hwnd_server;
1571     CONVINFO info;
1572     HDDEDATA hdata;
1573     BOOL conv_unicode = client_unicode;
1574     static char test_cmd[] = "test dde command";
1575
1576     if (!(hwnd_server = create_dde_server( server_unicode ))) return;
1577
1578     dde_inst = 0;
1579     if (client_unicode)
1580         ret = DdeInitializeW(&dde_inst, client_dde_callback, APPCMD_CLIENTONLY, 0);
1581     else
1582         ret = DdeInitializeA(&dde_inst, client_dde_callback, APPCMD_CLIENTONLY, 0);
1583     ok(ret == DMLERR_NO_ERROR, "DdeInitializeA failed with error %04x (%x)\n",
1584        ret, DdeGetLastError(dde_inst));
1585
1586     hsz_server = DdeCreateStringHandleW(dde_inst, TEST_DDE_SERVICE, CP_WINUNICODE);
1587
1588     hconv = DdeConnect(dde_inst, hsz_server, 0, NULL);
1589     ok(hconv != 0, "DdeConnect error %x\n", DdeGetLastError(dde_inst));
1590     err = DdeGetLastError(dde_inst);
1591     ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1592
1593     info.cb = sizeof(info);
1594     ret = DdeQueryConvInfo(hconv, QID_SYNC, &info);
1595     ok(ret, "wrong info size %d, DdeQueryConvInfo error %x\n", ret, DdeGetLastError(dde_inst));
1596     ok(info.ConvCtxt.iCodePage == client_unicode ? CP_WINUNICODE : CP_WINANSI,
1597        "wrong iCodePage %d\n", info.ConvCtxt.iCodePage);
1598     ok(!info.hConvPartner, "unexpected info.hConvPartner: %p\n", info.hConvPartner);
1599 todo_wine {
1600     ok((info.wStatus & DDE_FACK), "unexpected info.wStatus: %04x\n", info.wStatus);
1601 }
1602     ok((info.wStatus & (ST_CONNECTED | ST_CLIENT)) == (ST_CONNECTED | ST_CLIENT), "unexpected info.wStatus: %04x\n", info.wStatus);
1603     ok(info.wConvst == XST_CONNECTED, "unexpected info.wConvst: %04x\n", info.wConvst);
1604     ok(info.wType == 0, "unexpected info.wType: %04x\n", info.wType);
1605
1606     client_unicode = IsWindowUnicode( info.hwnd );
1607     trace("hwnd %p, hwndPartner %p, unicode %u\n", info.hwnd, info.hwndPartner, client_unicode);
1608
1609     trace("sending test client transaction command\n");
1610     ret = 0xdeadbeef;
1611     hdata = DdeClientTransaction((LPBYTE)test_cmd, strlen(test_cmd) + 1, hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
1612     ok(!hdata, "DdeClientTransaction succeeded\n");
1613     ok(ret == DDE_FNOTPROCESSED || broken(ret == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
1614        "wrong status code %04x\n", ret);
1615     err = DdeGetLastError(dde_inst);
1616     ok(err == DMLERR_NOTPROCESSED, "wrong dde error %x\n", err);
1617
1618     trace("sending ANSI client transaction command\n");
1619     ret = 0xdeadbeef;
1620     hdata = DdeClientTransaction((LPBYTE)exec_cmdA, lstrlenA(exec_cmdA) + 1, hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1621     err = DdeGetLastError(dde_inst);
1622     if (conv_unicode && (!client_unicode || !server_unicode))  /* W->A mapping -> garbage */
1623     {
1624         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1625         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1626         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1627     }
1628     else if (!conv_unicode && client_unicode && server_unicode)  /* A->W mapping -> wrong cmd */
1629     {
1630         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1631         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1632         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1633     }
1634     else  /* no mapping */
1635     {
1636         ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1637         ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1638         ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1639     }
1640
1641     trace("sending ANSI-as-Unicode client transaction command\n");
1642     ret = 0xdeadbeef;
1643     hdata = DdeClientTransaction((LPBYTE)exec_cmdAW, (lstrlenW(exec_cmdAW) + 1) * sizeof(WCHAR),
1644                                  hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1645     err = DdeGetLastError(dde_inst);
1646     if (conv_unicode && (!client_unicode || !server_unicode))  /* W->A mapping */
1647     {
1648         ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1649         ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1650         ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1651     }
1652     else if (!conv_unicode && client_unicode && server_unicode)  /* A->W mapping -> garbage */
1653     {
1654         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1655         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1656         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1657     }
1658     else  /* no mapping */
1659     {
1660         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1661         ok(ret == DDE_FNOTPROCESSED || broken(ret == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
1662            "wrong status code %04x\n", ret);
1663         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1664     }
1665
1666     trace("sending unicode client transaction command\n");
1667     ret = 0xdeadbeef;
1668     hdata = DdeClientTransaction((LPBYTE)exec_cmdW, (lstrlenW(exec_cmdW) + 1) * sizeof(WCHAR), hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1669     err = DdeGetLastError(dde_inst);
1670     if (conv_unicode && (!client_unicode || !server_unicode))  /* W->A mapping -> wrong cmd */
1671     {
1672         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1673         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1674         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1675     }
1676     else if (!conv_unicode && client_unicode && server_unicode)  /* A->W mapping -> garbage */
1677     {
1678         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1679         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1680         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1681     }
1682     else  /* no mapping */
1683     {
1684         ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1685         ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1686         ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1687     }
1688
1689     trace("sending Unicode-as-ANSI client transaction command\n");
1690     ret = 0xdeadbeef;
1691     hdata = DdeClientTransaction((LPBYTE)exec_cmdWA, lstrlenA(exec_cmdWA) + 1, hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1692     err = DdeGetLastError(dde_inst);
1693     if (conv_unicode && (!client_unicode || !server_unicode))  /* W->A mapping -> garbage */
1694     {
1695         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1696         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1697         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1698     }
1699     else if (!conv_unicode && client_unicode && server_unicode)  /* A->W mapping */
1700     {
1701         ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1702         ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1703         ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1704     }
1705     else  /* no mapping */
1706     {
1707         ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1708         ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1709         ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1710     }
1711
1712     ok(DdeDisconnect(hconv), "DdeDisconnect error %x\n", DdeGetLastError(dde_inst));
1713
1714     info.cb = sizeof(info);
1715     ret = DdeQueryConvInfo(hconv, QID_SYNC, &info);
1716     ok(!ret, "DdeQueryConvInfo should fail\n");
1717     err = DdeGetLastError(dde_inst);
1718 todo_wine {
1719     ok(err == DMLERR_INVALIDPARAMETER, "wrong dde error %x\n", err);
1720 }
1721
1722     ok(DdeFreeStringHandle(dde_inst, hsz_server), "DdeFreeStringHandle error %x\n", DdeGetLastError(dde_inst));
1723
1724     /* This call hangs on win2k SP4 and XP SP1.
1725     DdeUninitialize(dde_inst);*/
1726
1727     DestroyWindow(hwnd_server);
1728 }
1729
1730 static void test_initialisation(void)
1731 {
1732     UINT ret;
1733     DWORD res;
1734     HDDEDATA hdata;
1735     HSZ server, topic, item;
1736     DWORD client_pid;
1737     HCONV conversation;
1738
1739     /* Initialise without a valid server window. */
1740     client_pid = 0;
1741     ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1742     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
1743
1744
1745     server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI);
1746     topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI);
1747
1748     DdeGetLastError(client_pid);
1749
1750     /* There is no server window so no conversation can be extracted */
1751     conversation = DdeConnect(client_pid, server, topic, NULL);
1752     ok(conversation == NULL, "Expected NULL conversation, %p\n", conversation);
1753     ret = DdeGetLastError(client_pid);
1754     ok(ret == DMLERR_NO_CONV_ESTABLISHED, "Expected DMLERR_NO_CONV_ESTABLISHED, got %d\n", ret);
1755
1756     DdeFreeStringHandle(client_pid, server);
1757
1758     item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI);
1759
1760     /* There is no converstation so an invalild parameter results */
1761     res = 0xdeadbeef;
1762     DdeGetLastError(client_pid);
1763     hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
1764     ok(hdata == NULL, "Expected NULL, got %p\n", hdata);
1765     ret = DdeGetLastError(client_pid);
1766 todo_wine
1767     ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
1768     ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res);
1769
1770     DdeFreeStringHandle(client_pid, server);
1771     ret = DdeDisconnect(conversation);
1772     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1773
1774     ret = DdeUninitialize(client_pid);
1775     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1776 }
1777
1778 static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage)
1779 {
1780     static const WCHAR dde_string[] = {'D','D','E',' ','S','t','r','i','n','g',0};
1781     HSZ str_handle;
1782     WCHAR bufW[256];
1783     char buf[256];
1784     ATOM atom;
1785     int ret;
1786
1787     str_handle = DdeCreateStringHandleW(dde_inst, dde_string, codepage);
1788     ok(str_handle != 0, "DdeCreateStringHandleW failed with error %08x\n",
1789        DdeGetLastError(dde_inst));
1790
1791     ret = DdeQueryStringW(dde_inst, str_handle, NULL, 0, codepage);
1792     if (codepage == CP_WINANSI)
1793         ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret);
1794     else
1795         ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret);
1796
1797     ret = DdeQueryStringW(dde_inst, str_handle, bufW, 256, codepage);
1798     if (codepage == CP_WINANSI)
1799     {
1800         ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret);
1801         ok(!lstrcmpA("D", (LPCSTR)bufW), "DdeQueryStringW returned wrong string\n");
1802     }
1803     else
1804     {
1805         ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret);
1806         ok(!lstrcmpW(dde_string, bufW), "DdeQueryStringW returned wrong string\n");
1807     }
1808
1809     ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINANSI);
1810     if (codepage == CP_WINANSI)
1811     {
1812         ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret);
1813         ok(!lstrcmpA("D", buf), "DdeQueryStringW returned wrong string\n");
1814     }
1815     else
1816     {
1817         ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret);
1818         ok(!lstrcmpA("DDE String", buf), "DdeQueryStringA returned wrong string %s\n", buf);
1819     }
1820
1821     ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINUNICODE);
1822     if (codepage == CP_WINANSI)
1823     {
1824         ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret);
1825         ok(!lstrcmpA("D", buf), "DdeQueryStringA returned wrong string %s\n", buf);
1826     }
1827     else
1828     {
1829         ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret);
1830         ok(!lstrcmpW(dde_string, (LPCWSTR)buf), "DdeQueryStringW returned wrong string\n");
1831     }
1832
1833     if (codepage == CP_WINANSI)
1834     {
1835         atom = FindAtomA((LPSTR)dde_string);
1836         ok(atom != 0, "Expected a valid atom\n");
1837
1838         SetLastError(0xdeadbeef);
1839         atom = GlobalFindAtomA((LPSTR)dde_string);
1840         ok(atom == 0, "Expected 0, got %d\n", atom);
1841         ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1842            "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1843     }
1844     else
1845     {
1846         atom = FindAtomW(dde_string);
1847         ok(atom != 0, "Expected a valid atom\n");
1848
1849         SetLastError(0xdeadbeef);
1850         atom = GlobalFindAtomW(dde_string);
1851         ok(atom == 0, "Expected 0, got %d\n", atom);
1852         ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1853            "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1854     }
1855
1856     ok(DdeFreeStringHandle(dde_inst, str_handle), "DdeFreeStringHandle failed\n");
1857 }
1858
1859 static void test_DdeCreateDataHandle(void)
1860 {
1861     HDDEDATA hdata;
1862     DWORD dde_inst, dde_inst2;
1863     DWORD size;
1864     UINT res, err;
1865     BOOL ret;
1866     HSZ item;
1867     LPBYTE ptr;
1868     WCHAR item_str[] = {'i','t','e','m',0};
1869
1870     dde_inst = 0;
1871     dde_inst2 = 0;
1872     res = DdeInitializeA(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1873     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
1874
1875     res = DdeInitializeA(&dde_inst2, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1876     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
1877
1878     /* 0 instance id
1879      * This block tests an invalid instance Id.  The correct behaviour is that if the instance Id
1880      * is invalid then the lastError of all instances is set to the error.  There are two instances
1881      * created, lastError is cleared, an error is generated and then both instances are checked to
1882      * ensure that they both have the same error set
1883      */
1884     item = DdeCreateStringHandleA(0, "item", CP_WINANSI);
1885     ok(item == NULL, "Expected NULL hsz got %p\n", item);
1886     err = DdeGetLastError(dde_inst);
1887     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1888     err = DdeGetLastError(dde_inst2);
1889     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1890     item = DdeCreateStringHandleW(0, item_str, CP_WINUNICODE);
1891     ok(item == NULL, "Expected NULL hsz got %p\n", item);
1892     err = DdeGetLastError(dde_inst);
1893     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1894     err = DdeGetLastError(dde_inst2);
1895     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1896
1897     item = DdeCreateStringHandleA(dde_inst, "item", CP_WINANSI);
1898     ok(item != NULL, "Expected non-NULL hsz\n");
1899     item = DdeCreateStringHandleA(dde_inst2, "item", CP_WINANSI);
1900     ok(item != NULL, "Expected non-NULL hsz\n");
1901
1902     if (0) {
1903         /* do not test with an invalid instance id: that crashes on win9x */
1904         hdata = DdeCreateDataHandle(0xdeadbeef, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0);
1905     }
1906
1907     /* 0 instance id
1908      * This block tests an invalid instance Id.  The correct behaviour is that if the instance Id
1909      * is invalid then the lastError of all instances is set to the error.  There are two instances
1910      * created, lastError is cleared, an error is generated and then both instances are checked to
1911      * ensure that they both have the same error set
1912      */
1913     DdeGetLastError(dde_inst);
1914     DdeGetLastError(dde_inst2);
1915     hdata = DdeCreateDataHandle(0, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0);
1916     err = DdeGetLastError(dde_inst);
1917     ok(hdata == NULL, "Expected NULL, got %p\n", hdata);
1918     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1919     err = DdeGetLastError(dde_inst2);
1920     ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1921
1922     ret = DdeUninitialize(dde_inst2);
1923     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
1924
1925
1926     /* NULL pSrc */
1927     DdeGetLastError(dde_inst);
1928     hdata = DdeCreateDataHandle(dde_inst, NULL, MAX_PATH, 0, item, CF_TEXT, 0);
1929     err = DdeGetLastError(dde_inst);
1930     ok(hdata != NULL, "Expected non-NULL hdata\n");
1931     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1932
1933     ptr = DdeAccessData(hdata, &size);
1934     ok(ptr != NULL, "Expected non-NULL ptr\n");
1935     ok(size == 260, "Expected 260, got %d\n", size);
1936
1937     ret = DdeUnaccessData(hdata);
1938     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1939
1940     ret = DdeFreeDataHandle(hdata);
1941     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1942
1943     /* cb is zero */
1944     DdeGetLastError(dde_inst);
1945     hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", 0, 0, item, CF_TEXT, 0);
1946     err = DdeGetLastError(dde_inst);
1947     ok(hdata != NULL, "Expected non-NULL hdata\n");
1948     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1949
1950     ptr = DdeAccessData(hdata, &size);
1951     ok(ptr != NULL, "Expected non-NULL ptr\n");
1952     ok(size == 0, "Expected 0, got %d\n", size);
1953
1954     ret = DdeUnaccessData(hdata);
1955     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1956
1957     ret = DdeFreeDataHandle(hdata);
1958     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1959
1960     /* cbOff is non-zero */
1961     DdeGetLastError(dde_inst);
1962     hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 2, item, CF_TEXT, 0);
1963     err = DdeGetLastError(dde_inst);
1964     ok(hdata != NULL, "Expected non-NULL hdata\n");
1965     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1966
1967     ptr = DdeAccessData(hdata, &size);
1968     ok(ptr != NULL, "Expected non-NULL ptr\n");
1969     ok(size == 262, "Expected 262, got %d\n", size);
1970     todo_wine
1971     {
1972         ok(lstrlenA((LPSTR)ptr) == 0, "Expected 0, got %d\n", lstrlenA((LPSTR)ptr));
1973     }
1974
1975     ret = DdeUnaccessData(hdata);
1976     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1977
1978     ret = DdeFreeDataHandle(hdata);
1979     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1980
1981     /* NULL item */
1982     DdeGetLastError(dde_inst);
1983     hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, 0, CF_TEXT, 0);
1984     err = DdeGetLastError(dde_inst);
1985     ok(hdata != NULL, "Expected non-NULL hdata\n");
1986     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1987
1988     ptr = DdeAccessData(hdata, &size);
1989     ok(ptr != NULL, "Expected non-NULL ptr\n");
1990     ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
1991     ok(size == 260, "Expected 260, got %d\n", size);
1992
1993     ret = DdeUnaccessData(hdata);
1994     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1995
1996     ret = DdeFreeDataHandle(hdata);
1997     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1998
1999     /* NULL item */
2000     DdeGetLastError(dde_inst);
2001     hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, (HSZ)0xdeadbeef, CF_TEXT, 0);
2002     err = DdeGetLastError(dde_inst);
2003     ok(hdata != NULL, "Expected non-NULL hdata\n");
2004     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
2005
2006     ptr = DdeAccessData(hdata, &size);
2007     ok(ptr != NULL, "Expected non-NULL ptr\n");
2008     ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
2009     ok(size == 260, "Expected 260, got %d\n", size);
2010
2011     ret = DdeUnaccessData(hdata);
2012     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2013
2014     ret = DdeFreeDataHandle(hdata);
2015     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2016
2017     /* invalid clipboard format */
2018     DdeGetLastError(dde_inst);
2019     hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, item, 0xdeadbeef, 0);
2020     err = DdeGetLastError(dde_inst);
2021     ok(hdata != NULL, "Expected non-NULL hdata\n");
2022     ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
2023
2024     ptr = DdeAccessData(hdata, &size);
2025     ok(ptr != NULL, "Expected non-NULL ptr\n");
2026     ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
2027     ok(size == 260, "Expected 260, got %d\n", size);
2028
2029     ret = DdeUnaccessData(hdata);
2030     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2031
2032     ret = DdeFreeDataHandle(hdata);
2033     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2034
2035     ret = DdeUninitialize(dde_inst);
2036     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
2037 }
2038
2039 static void test_DdeCreateStringHandle(void)
2040 {
2041     DWORD dde_inst, ret;
2042
2043     dde_inst = 0xdeadbeef;
2044     SetLastError(0xdeadbeef);
2045     ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
2046     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2047     {
2048         win_skip("DdeInitializeW is unimplemented\n");
2049         return;
2050     }
2051
2052     ok(ret == DMLERR_INVALIDPARAMETER, "DdeInitializeW should fail, but got %04x instead\n", ret);
2053     ok(DdeGetLastError(dde_inst) == DMLERR_INVALIDPARAMETER, "expected DMLERR_INVALIDPARAMETER\n");
2054
2055     dde_inst = 0;
2056     ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
2057     ok(ret == DMLERR_NO_ERROR, "DdeInitializeW failed with error %04x (%08x)\n",
2058        ret, DdeGetLastError(dde_inst));
2059
2060     test_DdeCreateStringHandleW(dde_inst, 0);
2061     test_DdeCreateStringHandleW(dde_inst, CP_WINUNICODE);
2062     test_DdeCreateStringHandleW(dde_inst, CP_WINANSI);
2063
2064     ok(DdeUninitialize(dde_inst), "DdeUninitialize failed\n");
2065 }
2066
2067 static void test_FreeDDElParam(void)
2068 {
2069     HGLOBAL val, hglobal;
2070     BOOL ret;
2071
2072     ret = FreeDDElParam(WM_DDE_INITIATE, 0);
2073     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2074
2075     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2076     ret = FreeDDElParam(WM_DDE_INITIATE, (LPARAM)hglobal);
2077     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2078     val = GlobalFree(hglobal);
2079     ok(val == NULL, "Expected NULL, got %p\n", val);
2080
2081     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2082     ret = FreeDDElParam(WM_DDE_ADVISE, (LPARAM)hglobal);
2083     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2084
2085     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2086     ret = FreeDDElParam(WM_DDE_UNADVISE, (LPARAM)hglobal);
2087     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2088     val = GlobalFree(hglobal);
2089     ok(val == NULL, "Expected NULL, got %p\n", val);
2090
2091     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2092     ret = FreeDDElParam(WM_DDE_ACK, (LPARAM)hglobal);
2093     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2094
2095     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2096     ret = FreeDDElParam(WM_DDE_DATA, (LPARAM)hglobal);
2097     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2098
2099     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2100     ret = FreeDDElParam(WM_DDE_REQUEST, (LPARAM)hglobal);
2101     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2102     val = GlobalFree(hglobal);
2103     ok(val == NULL, "Expected NULL, got %p\n", val);
2104
2105     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2106     ret = FreeDDElParam(WM_DDE_POKE, (LPARAM)hglobal);
2107     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2108
2109     hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2110     ret = FreeDDElParam(WM_DDE_EXECUTE, (LPARAM)hglobal);
2111     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2112     val = GlobalFree(hglobal);
2113     ok(val == NULL, "Expected NULL, got %p\n", val);
2114 }
2115
2116 static void test_PackDDElParam(void)
2117 {
2118     UINT_PTR lo, hi, *ptr;
2119     LPARAM lparam;
2120     BOOL ret;
2121
2122     lparam = PackDDElParam(WM_DDE_INITIATE, 0xcafe, 0xbeef);
2123     /* value gets sign-extended despite being an LPARAM */
2124     ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2125
2126     lo = hi = 0;
2127     ret = UnpackDDElParam(WM_DDE_INITIATE, lparam, &lo, &hi);
2128     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2129     ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2130     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2131
2132     ret = FreeDDElParam(WM_DDE_INITIATE, lparam);
2133     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2134
2135     lparam = PackDDElParam(WM_DDE_TERMINATE, 0xcafe, 0xbeef);
2136     ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2137
2138     lo = hi = 0;
2139     ret = UnpackDDElParam(WM_DDE_TERMINATE, lparam, &lo, &hi);
2140     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2141     ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2142     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2143
2144     ret = FreeDDElParam(WM_DDE_TERMINATE, lparam);
2145     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2146
2147     lparam = PackDDElParam(WM_DDE_ADVISE, 0xcafe, 0xbeef);
2148     /* win9x returns 0 here */
2149     if (lparam) {
2150         ptr = GlobalLock((HGLOBAL)lparam);
2151         ok(ptr != NULL, "Expected non-NULL ptr\n");
2152         ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2153         ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2154
2155         ret = GlobalUnlock((HGLOBAL)lparam);
2156         ok(ret == 1, "Expected 1, got %d\n", ret);
2157
2158         lo = hi = 0;
2159         ret = UnpackDDElParam(WM_DDE_ADVISE, lparam, &lo, &hi);
2160         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2161         ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2162         ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2163     }
2164     else
2165         win_skip("no lparam for WM_DDE_ADVISE\n");
2166
2167     ret = FreeDDElParam(WM_DDE_ADVISE, lparam);
2168     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2169
2170     lparam = PackDDElParam(WM_DDE_UNADVISE, 0xcafe, 0xbeef);
2171     ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2172
2173     lo = hi = 0;
2174     ret = UnpackDDElParam(WM_DDE_UNADVISE, lparam, &lo, &hi);
2175     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2176     ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2177     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2178
2179     ret = FreeDDElParam(WM_DDE_UNADVISE, lparam);
2180     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2181
2182     lparam = PackDDElParam(WM_DDE_ACK, 0xcafe, 0xbeef);
2183     /* win9x returns the input (0xbeef<<16 | 0xcafe) here */
2184     if (lparam != (int)0xbeefcafe) {
2185         ptr = GlobalLock((HGLOBAL)lparam);
2186         ok(ptr != NULL, "Expected non-NULL ptr\n");
2187         ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2188         ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2189
2190         ret = GlobalUnlock((HGLOBAL)lparam);
2191         ok(ret == 1, "Expected 1, got %d\n", ret);
2192
2193         lo = hi = 0;
2194         ret = UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
2195         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2196         ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2197         ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2198
2199         ret = FreeDDElParam(WM_DDE_ACK, lparam);
2200         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2201     }
2202     else
2203         win_skip("got lparam 0x%lx for WM_DDE_ACK\n", lparam);
2204
2205     lparam = PackDDElParam(WM_DDE_DATA, 0xcafe, 0xbeef);
2206     /* win9x returns 0 here */
2207     if (lparam) {
2208         ptr = GlobalLock((HGLOBAL)lparam);
2209         ok(ptr != NULL, "Expected non-NULL ptr\n");
2210         ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2211         ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2212
2213         ret = GlobalUnlock((HGLOBAL)lparam);
2214         ok(ret == 1, "Expected 1, got %d\n", ret);
2215
2216         lo = hi = 0;
2217         ret = UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi);
2218         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2219         ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2220         ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2221     }
2222     else
2223         win_skip("no lparam for WM_DDE_DATA\n");
2224
2225     ret = FreeDDElParam(WM_DDE_DATA, lparam);
2226     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2227
2228     lparam = PackDDElParam(WM_DDE_REQUEST, 0xcafe, 0xbeef);
2229     ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2230
2231     lo = hi = 0;
2232     ret = UnpackDDElParam(WM_DDE_REQUEST, lparam, &lo, &hi);
2233     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2234     ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2235     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2236
2237     ret = FreeDDElParam(WM_DDE_REQUEST, lparam);
2238     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2239
2240     lparam = PackDDElParam(WM_DDE_POKE, 0xcafe, 0xbeef);
2241     /* win9x returns 0 here */
2242     if (lparam) {
2243         ptr = GlobalLock((HGLOBAL)lparam);
2244         ok(ptr != NULL, "Expected non-NULL ptr\n");
2245         ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2246         ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2247
2248         ret = GlobalUnlock((HGLOBAL)lparam);
2249         ok(ret == 1, "Expected 1, got %d\n", ret);
2250
2251         lo = hi = 0;
2252         ret = UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi);
2253         ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2254         ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2255         ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2256     }
2257     else
2258         win_skip("no lparam for WM_DDE_POKE\n");
2259
2260     ret = FreeDDElParam(WM_DDE_POKE, lparam);
2261     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2262
2263     lparam = PackDDElParam(WM_DDE_EXECUTE, 0xcafe, 0xbeef);
2264     ok(lparam == 0xbeef, "Expected 0xbeef, got %08lx\n", lparam);
2265
2266     lo = hi = 0;
2267     ret = UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
2268     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2269     ok(lo == 0, "Expected 0, got %08lx\n", lo);
2270     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2271
2272     ret = FreeDDElParam(WM_DDE_EXECUTE, lparam);
2273     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2274 }
2275
2276 static void test_UnpackDDElParam(void)
2277 {
2278     UINT_PTR lo, hi, *ptr;
2279     HGLOBAL hglobal;
2280     BOOL ret;
2281
2282     /* NULL lParam */
2283     lo = 0xdead;
2284     hi = 0xbeef;
2285     ret = UnpackDDElParam(WM_DDE_INITIATE, 0, &lo, &hi);
2286     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2287     ok(lo == 0, "Expected 0, got %08lx\n", lo);
2288     ok(hi == 0, "Expected 0, got %08lx\n", hi);
2289
2290     /* NULL lo */
2291     lo = 0xdead;
2292     hi = 0xbeef;
2293     ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, NULL, &hi);
2294     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2295     ok(lo == 0xdead, "Expected 0xdead, got %08lx\n", lo);
2296     ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2297
2298     /* NULL hi */
2299     lo = 0xdead;
2300     hi = 0xbeef;
2301     ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, &lo, NULL);
2302     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2303     ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2304     ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2305
2306     lo = 0xdead;
2307     hi = 0xbeef;
2308     ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, &lo, &hi);
2309     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2310     ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2311     ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2312
2313     lo = 0xdead;
2314     hi = 0xbeef;
2315     ret = UnpackDDElParam(WM_DDE_TERMINATE, 0xcafebabe, &lo, &hi);
2316     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2317     ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2318     ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2319
2320     lo = 0xdead;
2321     hi = 0xbeef;
2322     ret = UnpackDDElParam(WM_DDE_ADVISE, 0, &lo, &hi);
2323     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
2324     ok(lo == 0 ||
2325        broken(lo == 0xdead), /* win2k */
2326        "Expected 0, got %08lx\n", lo);
2327     ok(hi == 0 ||
2328        broken(hi == 0xbeef), /* win2k */
2329        "Expected 0, got %08lx\n", hi);
2330
2331     hglobal = GlobalAlloc(GMEM_DDESHARE, 2 * sizeof(*ptr));
2332     ptr = GlobalLock(hglobal);
2333     ptr[0] = 0xcafebabe;
2334     ptr[1] = 0xdeadbeef;
2335     GlobalUnlock(hglobal);
2336
2337     lo = 0xdead;
2338     hi = 0xbeef;
2339     ret = UnpackDDElParam(WM_DDE_ADVISE, (LPARAM)hglobal, &lo, &hi);
2340     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2341     ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2342     ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2343
2344     lo = 0xdead;
2345     hi = 0xbeef;
2346     ret = UnpackDDElParam(WM_DDE_UNADVISE, 0xcafebabe, &lo, &hi);
2347     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2348     ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2349     ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2350
2351     lo = 0xdead;
2352     hi = 0xbeef;
2353     ret = UnpackDDElParam(WM_DDE_ACK, (LPARAM)hglobal, &lo, &hi);
2354     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2355     ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2356     ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2357
2358     lo = 0xdead;
2359     hi = 0xbeef;
2360     ret = UnpackDDElParam(WM_DDE_DATA, (LPARAM)hglobal, &lo, &hi);
2361     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2362     ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2363     ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2364
2365     lo = 0xdead;
2366     hi = 0xbeef;
2367     ret = UnpackDDElParam(WM_DDE_REQUEST, 0xcafebabe, &lo, &hi);
2368     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2369     ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2370     ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2371
2372     lo = 0xdead;
2373     hi = 0xbeef;
2374     ret = UnpackDDElParam(WM_DDE_POKE, (LPARAM)hglobal, &lo, &hi);
2375     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2376     ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2377     ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2378
2379     lo = 0xdead;
2380     hi = 0xbeef;
2381     ret = UnpackDDElParam(WM_DDE_EXECUTE, 0xcafebabe, &lo, &hi);
2382     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2383     ok(lo == 0, "Expected 0, got %08lx\n", lo);
2384     ok(hi == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", hi);
2385
2386     GlobalFree(hglobal);
2387 }
2388
2389 static char test_cmd_a_to_a[] = "Test dde command";
2390 static WCHAR test_cmd_w_to_w[][32] = {
2391     {'t','e','s','t',' ','d','d','e',' ','c','o','m','m','a','n','d',0},
2392     { 0x2018, 0x2019, 0x0161, 0x0041, 0x02dc, 0 },  /* some chars that should map properly to CP1252 */
2393     { 0x2026, 0x2020, 0x2021, 0x0d0a, 0 },  /* false negative for IsTextUnicode */
2394     { 0x4efa, 0x4efc, 0x0061, 0x4efe, 0 },  /* some Chinese chars */
2395 };
2396 static const int nb_callbacks = 5 + sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]);
2397
2398 static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv,
2399                                                HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
2400                                                ULONG_PTR dwData1, ULONG_PTR dwData2)
2401 {
2402     DWORD size, rsize;
2403     char str[MAX_PATH];
2404     static int msg_index = 0;
2405     static HCONV conversation = 0;
2406     static char test_service [] = "TestDDEService";
2407     static char test_topic [] = "TestDDETopic";
2408
2409     msg_index++;
2410
2411     switch (uType)
2412     {
2413     case XTYP_REGISTER:
2414     {
2415         ok(msg_index % nb_callbacks == 1, "Expected 1 modulo %u, got %d\n", nb_callbacks, msg_index);
2416         return (HDDEDATA)TRUE;
2417     }
2418
2419     case XTYP_CONNECT:
2420     {
2421         ok(msg_index % nb_callbacks == 2, "Expected 2 modulo %u, got %d\n", nb_callbacks, msg_index);
2422         ok(uFmt == 0, "Expected 0, got %d, msg_index=%d\n", uFmt, msg_index);
2423         ok(hconv == 0, "Expected 0, got %p, msg_index=%d\n", hconv, msg_index);
2424         ok(hdata == 0, "Expected 0, got %p, msg_index=%d\n", hdata, msg_index);
2425         ok(dwData1 != 0, "Expected not 0, got %08lx, msg_index=%d\n", dwData1, msg_index);
2426         ok(dwData2 == FALSE, "Expected FALSE, got %08lx, msg_index=%d\n", dwData2, msg_index);
2427
2428         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
2429         ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n",
2430                              test_topic, str, msg_index);
2431         ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index);
2432
2433         size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
2434         ok(!lstrcmpA(str, test_service), "Expected %s, got %s, msg_index=%d\n",
2435                              test_service, str, msg_index);
2436         ok(size == 14, "Expected 14, got %d, msg_index=%d\n", size, msg_index);
2437
2438         return (HDDEDATA) TRUE;
2439     }
2440     case XTYP_CONNECT_CONFIRM:
2441     {
2442         ok(msg_index % nb_callbacks == 3, "Expected 3 modulo %u, got %d\n", nb_callbacks, msg_index);
2443         conversation = hconv;
2444         return (HDDEDATA) TRUE;
2445     }
2446     case XTYP_EXECUTE:
2447     {
2448         BYTE *buffer = NULL;
2449         WCHAR *cmd_w;
2450         char test_cmd_w_to_a[64];
2451         WCHAR test_cmd_a_to_w[64];
2452         DWORD size_a, size_w, size_w_to_a, size_a_to_w;
2453         BOOL unicode_server, unicode_client, str_index;
2454
2455         ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
2456         ok(hconv == conversation, "Expected conversation handle, got %p, msg_index=%d\n",
2457                              hconv, msg_index);
2458         ok(dwData1 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData1, msg_index);
2459         ok(dwData2 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData2, msg_index);
2460         ok(hsz2 == 0, "Expected 0, got %p, msg_index=%d\n", hsz2, msg_index);
2461         size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
2462         ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n",
2463                              test_topic, str, msg_index);
2464         ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index);
2465         ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index);
2466
2467         size = DdeGetData(hdata, NULL, 0, 0);
2468         ok((buffer = HeapAlloc(GetProcessHeap(), 0, size)) != NULL, "should not be null\n");
2469         rsize = DdeGetData(hdata, buffer, size, 0);
2470         ok(rsize == size, "Incorrect size returned, expected %d got %d, msg_index=%d\n",
2471            size, rsize, msg_index);
2472         trace("msg %u strA \"%s\" strW %s\n", msg_index, buffer, wine_dbgstr_w((WCHAR*)buffer));
2473
2474         unicode_server = (msg_index / nb_callbacks == 1 || msg_index / nb_callbacks == 2);
2475         unicode_client = (msg_index / nb_callbacks == 1 || msg_index / nb_callbacks == 3);
2476         str_index = msg_index % nb_callbacks - 4;
2477         cmd_w = test_cmd_w_to_w[str_index - 1];
2478         size_a = strlen(test_cmd_a_to_a) + 1;
2479         size_w = (lstrlenW(cmd_w) + 1) * sizeof(WCHAR);
2480         size_a_to_w = MultiByteToWideChar( CP_ACP, 0, test_cmd_a_to_a, -1, test_cmd_a_to_w,
2481                                            sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
2482         size_w_to_a = WideCharToMultiByte( CP_ACP, 0, cmd_w, -1,
2483                                            test_cmd_w_to_a, sizeof(test_cmd_w_to_a), NULL, NULL );
2484         switch (str_index)
2485         {
2486         case 0:  /* ASCII string */
2487             if (unicode_server)
2488             {
2489                 ok(size == size_a_to_w, "Wrong size %d/%d, msg_index=%d\n", size, size_a_to_w, msg_index);
2490                 ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w),
2491                    "Expected %s, msg_index=%d\n", wine_dbgstr_w(test_cmd_a_to_w), msg_index);
2492             }
2493             else if (unicode_client)
2494             {
2495                 /* ASCII string mapped W->A -> garbage */
2496                 ok(size == size_a / sizeof(WCHAR) || size == size_a / sizeof(WCHAR) + 1,
2497                    "Wrong size %d, msg_index=%d\n", size, msg_index);
2498             }
2499             else
2500             {
2501                 ok(size == size_a, "Wrong size %d/%d, msg_index=%d\n", size, size_a, msg_index);
2502                 ok(!lstrcmpA((CHAR*)buffer, test_cmd_a_to_a), "Expected %s, got %s, msg_index=%d\n",
2503                    test_cmd_a_to_a, buffer, msg_index);
2504             }
2505             break;
2506
2507         case 1:  /* Unicode string with only 8-bit chars */
2508             if (unicode_server)
2509             {
2510                 ok(size == size_w, "Wrong size %d/%d, msg_index=%d\n", size, size_w, msg_index);
2511                 ok(!lstrcmpW((WCHAR*)buffer, cmd_w),
2512                    "Expected %s, msg_index=%d\n", wine_dbgstr_w(cmd_w), msg_index);
2513             }
2514             else if (unicode_client)
2515             {
2516                 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n", size, size_w_to_a, msg_index);
2517                 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2518                    test_cmd_w_to_a, buffer, msg_index);
2519             }
2520             else
2521             {
2522                 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n",
2523                    size, size_w_to_a, msg_index);
2524                 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2525                    test_cmd_w_to_a, buffer, msg_index);
2526             }
2527             break;
2528
2529         case 2:  /* normal Unicode string */
2530         case 3:  /* IsTextUnicode false negative */
2531         case 4:  /* Chinese chars */
2532             if (unicode_server)
2533             {
2534                 /* double A->W mapping */
2535                 /* NT uses the full size, XP+ only until the first null */
2536                 DWORD nt_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, size_w, test_cmd_a_to_w,
2537                                                      sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
2538                 DWORD xp_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, -1, NULL, 0 ) * sizeof(WCHAR);
2539                 ok(size == xp_size || broken(size == nt_size),
2540                    "Wrong size %d/%d, msg_index=%d\n", size, size_a_to_w, msg_index);
2541                 ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w),
2542                    "Expected %s, msg_index=%d\n", wine_dbgstr_w(test_cmd_a_to_w), msg_index);
2543             }
2544             else if (unicode_client)
2545             {
2546                 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n", size, size_w_to_a, msg_index);
2547                 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2548                    test_cmd_w_to_a, buffer, msg_index);
2549             }
2550             else
2551             {
2552                 ok(size == size_w, "Wrong size %d/%d, msg_index=%d\n", size, size_w, msg_index);
2553                 ok(!lstrcmpW((WCHAR*)buffer, cmd_w),
2554                    "Expected %s, msg_index=%d\n", wine_dbgstr_w(cmd_w), msg_index);
2555             }
2556             break;
2557
2558         default:
2559             ok( 0, "Invalid message %u\n", msg_index );
2560             break;
2561         }
2562         return (HDDEDATA) DDE_FACK;
2563     }
2564     case XTYP_DISCONNECT:
2565         return (HDDEDATA) TRUE;
2566
2567     default:
2568         ok(FALSE, "Unhandled msg: %08x, msg_index=%d\n", uType, msg_index);
2569     }
2570
2571     return NULL;
2572 }
2573
2574 static HDDEDATA CALLBACK client_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv,
2575                                                HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
2576                                                ULONG_PTR dwData1, ULONG_PTR dwData2)
2577 {
2578     switch (uType)
2579     {
2580     case XTYP_DISCONNECT:
2581         return (HDDEDATA) TRUE;
2582
2583     default:
2584         ok(FALSE, "Unhandled msg: %08x\n", uType);
2585     }
2586
2587     return NULL;
2588 }
2589
2590 static void test_end_to_end_client(BOOL type_a)
2591 {
2592     DWORD i, ret, err;
2593     DWORD client_pid = 0;
2594     HSZ server, topic;
2595     HCONV hconv;
2596     HDDEDATA hdata;
2597     static char test_service[] = "TestDDEService";
2598     static WCHAR test_service_w[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};
2599     static char test_topic[] = "TestDDETopic";
2600     static WCHAR test_topic_w[] = {'T','e','s','t','D','D','E','T','o','p','i','c',0};
2601
2602     trace("Start end to end client %s\n", type_a ? "ASCII" : "UNICODE");
2603
2604     if (type_a)
2605         ret = DdeInitializeA(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0);
2606     else
2607         ret = DdeInitializeW(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0);
2608     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret);
2609
2610     if (type_a)
2611     {
2612         server = DdeCreateStringHandleA(client_pid, test_service, CP_WINANSI);
2613         topic = DdeCreateStringHandleA(client_pid, test_topic, CP_WINANSI);
2614     }
2615     else {
2616         server = DdeCreateStringHandleW(client_pid, test_service_w, CP_WINUNICODE);
2617         topic = DdeCreateStringHandleW(client_pid, test_topic_w, CP_WINUNICODE);
2618     }
2619
2620     DdeGetLastError(client_pid);
2621     hconv = DdeConnect(client_pid, server, topic, NULL);
2622     ok(hconv != NULL, "Expected non-NULL conversation\n");
2623     ret = DdeGetLastError(client_pid);
2624     ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret);
2625     DdeFreeStringHandle(client_pid, server);
2626
2627     /* Test both A and W data being passed to DdeClientTransaction */
2628     hdata = DdeClientTransaction((LPBYTE)test_cmd_a_to_a, sizeof(test_cmd_a_to_a),
2629             hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
2630     ok(hdata != NULL, "DdeClientTransaction failed\n");
2631     ok(ret == DDE_FACK, "wrong status code %x\n", ret);
2632     err = DdeGetLastError(client_pid);
2633     ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
2634
2635     for (i = 0; i < sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]); i++)
2636     {
2637         hdata = DdeClientTransaction((LPBYTE)test_cmd_w_to_w[i],
2638                                      (lstrlenW(test_cmd_w_to_w[i]) + 1) * sizeof(WCHAR),
2639                                      hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
2640         ok(hdata != NULL, "DdeClientTransaction failed\n");
2641         ok(ret == DDE_FACK, "wrong status code %x\n", ret);
2642         err = DdeGetLastError(client_pid);
2643         ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
2644     }
2645
2646     DdeFreeStringHandle(client_pid, topic);
2647     ret = DdeDisconnect(hconv);
2648     ok(ret == TRUE, "Expected TRUE, got %x\n", ret);
2649
2650     ret = DdeUninitialize(client_pid);
2651     ok(ret == TRUE, "Expected TRUE, got %x\n", ret);
2652
2653 }
2654
2655 static void test_end_to_end_server(HANDLE hproc, HANDLE hthread, BOOL type_a)
2656 {
2657     MSG msg;
2658     HSZ server;
2659     BOOL ret;
2660     DWORD res;
2661     HDDEDATA hdata;
2662     static CHAR test_service[] = "TestDDEService";
2663
2664     trace("start end to end server %s\n", type_a ? "ASCII" : "UNICODE");
2665     server_pid = 0;
2666
2667     if (type_a)
2668         res = DdeInitializeA(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0);
2669     else
2670         res = DdeInitializeW(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0);
2671     ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
2672
2673     server = DdeCreateStringHandleA(server_pid, test_service, CP_WINANSI);
2674     ok(server != NULL, "Expected non-NULL string handle\n");
2675
2676     hdata = DdeNameService(server_pid, server, 0, DNS_REGISTER);
2677     ok(hdata == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", hdata);
2678     ResumeThread( hthread );
2679
2680
2681     while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
2682     {
2683         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2684     }
2685
2686     ret = DdeUninitialize(server_pid);
2687     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2688     GetExitCodeProcess( hproc, &res );
2689     ok( !res, "client failed with %u error(s)\n", res );
2690 }
2691
2692 START_TEST(dde)
2693 {
2694     int argc;
2695     char **argv;
2696     char buffer[MAX_PATH];
2697     STARTUPINFO startup;
2698     PROCESS_INFORMATION proc;
2699
2700     argc = winetest_get_mainargs(&argv);
2701     if (argc == 3)
2702     {
2703         if (!lstrcmpA(argv[2], "ddeml"))
2704             test_ddeml_client();
2705         else if (!lstrcmpA(argv[2], "msg"))
2706             test_msg_client();
2707         else if (!lstrcmpA(argv[2], "enda"))
2708             test_end_to_end_client(TRUE);
2709         else if (!lstrcmpA(argv[2], "endw"))
2710             test_end_to_end_client(FALSE);
2711
2712         return;
2713     }
2714
2715     test_initialisation();
2716
2717     ZeroMemory(&startup, sizeof(STARTUPINFO));
2718     sprintf(buffer, "%s dde ddeml", argv[0]);
2719     startup.cb = sizeof(startup);
2720     startup.dwFlags = STARTF_USESHOWWINDOW;
2721     startup.wShowWindow = SW_SHOWNORMAL;
2722
2723     CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2724                    CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2725
2726     test_msg_server(proc.hProcess, proc.hThread);
2727
2728     sprintf(buffer, "%s dde msg", argv[0]);
2729     CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2730                    0, NULL, NULL, &startup, &proc);
2731
2732     test_ddeml_server(proc.hProcess);
2733
2734     /* Test the combinations of A and W interfaces with A and W data
2735        end to end to ensure that data conversions are accurate */
2736     sprintf(buffer, "%s dde enda", argv[0]);
2737     CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2738                    CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2739
2740     test_end_to_end_server(proc.hProcess, proc.hThread, TRUE);
2741
2742     /* Don't bother testing W interfaces on Win9x/WinMe */
2743     SetLastError(0xdeadbeef);
2744     lstrcmpW(NULL, NULL);
2745     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2746     {
2747         win_skip("Skipping W-interface tests\n");
2748     }
2749     else
2750     {
2751         sprintf(buffer, "%s dde endw", argv[0]);
2752         CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2753                        CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2754
2755         test_end_to_end_server(proc.hProcess, proc.hThread, FALSE);
2756
2757         sprintf(buffer, "%s dde enda", argv[0]);
2758         CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2759                        CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2760
2761         test_end_to_end_server(proc.hProcess, proc.hThread, FALSE);
2762
2763         sprintf(buffer, "%s dde endw", argv[0]);
2764         CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2765                        CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2766
2767         test_end_to_end_server(proc.hProcess, proc.hThread, TRUE);
2768
2769         test_dde_aw_transaction( FALSE, TRUE );
2770         test_dde_aw_transaction( TRUE, FALSE );
2771         test_dde_aw_transaction( TRUE, TRUE );
2772         test_dde_aw_transaction( FALSE, FALSE );
2773
2774         test_dde_aw_transaction( FALSE, TRUE );
2775         test_dde_aw_transaction( TRUE, FALSE );
2776         test_dde_aw_transaction( TRUE, TRUE );
2777     }
2778     test_dde_aw_transaction( FALSE, FALSE );
2779
2780     test_DdeCreateDataHandle();
2781     test_DdeCreateStringHandle();
2782     test_FreeDDElParam();
2783     test_PackDDElParam();
2784     test_UnpackDDElParam();
2785 }