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