setupapi/tests: Add tests for dirid values.
[wine.git] / dlls / user32 / tests / dde.c
blob984076bbcdb501824621c8ee84303d405f295e06
1 /*
2 * Unit tests for DDE functions
4 * Copyright (c) 2004 Dmitry Timoshkov
5 * Copyright (c) 2007 James Hawkins
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.
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.
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
22 #include <stdarg.h>
23 #include <stdio.h>
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"
33 #include "wine/test.h"
35 static const WCHAR TEST_DDE_SERVICE[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};
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";
42 static WNDPROC old_dde_client_wndproc;
44 static const DWORD default_timeout = 200;
46 static void flush_events(void)
48 MSG msg;
49 int diff = default_timeout;
50 int min_timeout = 50;
51 DWORD time = GetTickCount() + diff;
53 while (diff > 0)
55 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
56 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
57 diff = time - GetTickCount();
58 min_timeout = 10;
62 static void create_dde_window(HWND *hwnd, LPCSTR name, WNDPROC wndproc)
64 WNDCLASSA wcA;
65 ATOM aclass;
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");
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");
80 static void destroy_dde_window(HWND *hwnd, LPCSTR name)
82 DestroyWindow(*hwnd);
83 UnregisterClassA(name, GetModuleHandleA(NULL));
86 static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
88 UINT_PTR lo, hi;
89 char str[MAX_PATH], *ptr;
90 HGLOBAL hglobal;
91 DDEDATA *data;
92 DDEPOKE *poke;
93 DWORD size;
95 static int msg_index = 0;
96 static HWND client = 0;
97 static BOOL executed = FALSE;
99 if (msg < WM_DDE_FIRST || msg > WM_DDE_LAST)
100 return DefWindowProcA(hwnd, msg, wparam, lparam);
102 msg_index++;
104 switch (msg)
106 case WM_DDE_INITIATE:
108 client = (HWND)wparam;
109 ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
111 GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
112 ok(!lstrcmpA(str, "TestDDEService"), "Expected TestDDEService, got %s\n", str);
114 GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
115 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
117 SendMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
119 break;
122 case WM_DDE_REQUEST:
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));
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);
136 if (msg_index == 8)
138 if (executed)
139 lstrcpyA(str, "command executed\r\n");
140 else
141 lstrcpyA(str, "command not executed\r\n");
143 else
144 lstrcpyA(str, "requested data\r\n");
146 size = FIELD_OFFSET(DDEDATA, Value[lstrlenA(str) + 1]);
147 hglobal = GlobalAlloc(GMEM_MOVEABLE, size);
148 ok(hglobal != NULL, "Expected non-NULL hglobal\n");
150 data = GlobalLock(hglobal);
151 ZeroMemory(data, size);
153 /* setting fResponse to FALSE at this point destroys
154 * the internal messaging state of native dde
156 data->fResponse = TRUE;
158 if (msg_index == 2)
159 data->fRelease = TRUE;
160 else if (msg_index == 3)
161 data->fAckReq = TRUE;
163 data->cfFormat = CF_TEXT;
164 lstrcpyA((LPSTR)data->Value, str);
165 GlobalUnlock(hglobal);
167 lparam = PackDDElParam(WM_DDE_DATA, (UINT_PTR)hglobal, HIWORD(lparam));
168 PostMessageA(client, WM_DDE_DATA, (WPARAM)hwnd, lparam);
170 break;
173 case WM_DDE_POKE:
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);
178 UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi);
180 GlobalGetAtomNameA(hi, str, MAX_PATH);
181 ok(!lstrcmpA(str, "poker"), "Expected poker, got %s\n", str);
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);
190 if (msg_index == 5)
192 size = GlobalSize((HGLOBAL)lo);
193 ok(size == 4 || broken(size == 32), /* sizes are rounded up on win9x */ "got %d\n", size);
195 else
196 ok(!lstrcmpA((LPSTR)poke->Value, "poke data\r\n"),
197 "Expected 'poke data\\r\\n', got %s\n", poke->Value);
199 GlobalUnlock((HGLOBAL)lo);
201 lparam = PackDDElParam(WM_DDE_ACK, DDE_FACK, hi);
202 PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
204 break;
207 case WM_DDE_EXECUTE:
209 ok(msg_index == 7, "Expected 7, got %d\n", msg_index);
210 ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
212 ptr = GlobalLock((HGLOBAL)lparam);
213 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected [Command(Var)], got %s\n", ptr);
214 GlobalUnlock((HGLOBAL)lparam);
216 executed = TRUE;
218 lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, DDE_FACK, lparam);
219 PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
221 break;
224 case WM_DDE_TERMINATE:
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);
230 PostMessageA(client, WM_DDE_TERMINATE, (WPARAM)hwnd, 0);
232 break;
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;
240 default:
241 ok(FALSE, "Unhandled msg: %08x\n", msg);
244 return DefWindowProcA(hwnd, msg, wparam, lparam);
247 static void test_msg_server(HANDLE hproc, HANDLE hthread)
249 MSG msg;
250 HWND hwnd;
251 DWORD res;
253 create_dde_window(&hwnd, "dde_server", dde_server_wndproc);
254 ResumeThread( hthread );
256 while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
258 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
261 destroy_dde_window(&hwnd, "dde_server");
262 GetExitCodeProcess( hproc, &res );
263 ok( !res, "client failed with %u error(s)\n", res );
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)
270 ok(FALSE, "Unhandled msg: %08x\n", uType);
271 return 0;
274 static void test_ddeml_client(void)
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;
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);
289 /* FIXME: make these atoms global and check them in the server */
291 server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI);
292 topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI);
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);
300 DdeFreeStringHandle(client_pid, server);
302 item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI);
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)
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 == 17, "Expected 17, got %d\n", size);
319 ret = DdeUnaccessData(hdata);
320 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
323 /* XTYP_REQUEST, fAckReq = TRUE */
324 res = 0xdeadbeef;
325 DdeGetLastError(client_pid);
326 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
327 ret = DdeGetLastError(client_pid);
328 ok(res == DDE_FNOTPROCESSED || broken(res == 0xdeadbeef), /* win9x */
329 "Expected DDE_FNOTPROCESSED, got %x\n", res);
330 todo_wine
331 ok(ret == DMLERR_MEMORY_ERROR || broken(ret == 0), /* win9x */
332 "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
333 ok( hdata != NULL, "hdata is NULL\n" );
334 if (hdata)
336 str = (LPSTR)DdeAccessData(hdata, &size);
337 ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
338 ok(size == 17, "Expected 17, got %d\n", size);
340 ret = DdeUnaccessData(hdata);
341 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
344 /* XTYP_REQUEST, all params normal */
345 res = 0xdeadbeef;
346 DdeGetLastError(client_pid);
347 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
348 ret = DdeGetLastError(client_pid);
349 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
350 ok(res == DDE_FNOTPROCESSED || broken(res == 0xdeadbeef), /* win9x */
351 "Expected DDE_FNOTPROCESSED, got %x\n", res);
352 if (hdata == NULL)
353 ok(FALSE, "hdata is NULL\n");
354 else
356 str = (LPSTR)DdeAccessData(hdata, &size);
357 ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
358 ok(size == 17, "Expected 17, got %d\n", size);
360 ret = DdeUnaccessData(hdata);
361 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
364 /* XTYP_REQUEST, no item */
365 res = 0xdeadbeef;
366 DdeGetLastError(client_pid);
367 hdata = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
368 ret = DdeGetLastError(client_pid);
369 ok(hdata == NULL, "Expected NULL hdata, got %p\n", hdata);
370 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res);
371 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
373 DdeFreeStringHandle(client_pid, item);
375 item = DdeCreateStringHandleA(client_pid, "poker", CP_WINANSI);
377 lstrcpyA(buffer, "poke data\r\n");
378 hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
379 0, item, CF_TEXT, 0);
380 ok(hdata != NULL, "Expected non-NULL hdata\n");
382 /* XTYP_POKE, no item */
383 res = 0xdeadbeef;
384 DdeGetLastError(client_pid);
385 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
386 ret = DdeGetLastError(client_pid);
387 ok(op == NULL, "Expected NULL, got %p\n", op);
388 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
389 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
391 /* XTYP_POKE, no data */
392 res = 0xdeadbeef;
393 DdeGetLastError(client_pid);
394 op = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
395 ret = DdeGetLastError(client_pid);
396 ok(op == NULL, "Expected NULL, got %p\n", op);
397 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
398 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
400 /* XTYP_POKE, wrong size */
401 res = 0xdeadbeef;
402 DdeGetLastError(client_pid);
403 op = DdeClientTransaction((LPBYTE)hdata, 0, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
404 ret = DdeGetLastError(client_pid);
405 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
406 ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
407 "Expected DDE_FACK, got %x\n", res);
408 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
410 /* XTYP_POKE, correct params */
411 res = 0xdeadbeef;
412 DdeGetLastError(client_pid);
413 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
414 ret = DdeGetLastError(client_pid);
415 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
416 ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
417 "Expected DDE_FACK, got %x\n", res);
418 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
420 DdeFreeDataHandle(hdata);
422 lstrcpyA(buffer, "[Command(Var)]");
423 hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
424 0, NULL, CF_TEXT, 0);
425 ok(hdata != NULL, "Expected non-NULL hdata\n");
427 /* XTYP_EXECUTE, correct params */
428 res = 0xdeadbeef;
429 DdeGetLastError(client_pid);
430 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
431 ret = DdeGetLastError(client_pid);
432 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
433 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
434 ok(res == DDE_FACK || broken(res == (0xdead0000 | DDE_FACK)), /* win9x */
435 "Expected DDE_FACK, got %x\n", res);
437 /* XTYP_EXECUTE, no data */
438 res = 0xdeadbeef;
439 DdeGetLastError(client_pid);
440 op = DdeClientTransaction(NULL, 0, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
441 ret = DdeGetLastError(client_pid);
442 ok(op == NULL || broken(op == (HDDEDATA)TRUE), /* win9x */ "Expected NULL, got %p\n", op);
443 if (!op)
445 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
446 ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
448 else /* win9x */
450 ok(res == (0xdead0000 | DDE_FACK), "Expected DDE_FACK, got %x\n", res);
451 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
454 /* XTYP_EXECUTE, no data, -1 size */
455 res = 0xdeadbeef;
456 DdeGetLastError(client_pid);
457 op = DdeClientTransaction(NULL, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
458 ret = DdeGetLastError(client_pid);
459 ok(op == NULL, "Expected NULL, got %p\n", op);
460 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
461 ok(ret == DMLERR_INVALIDPARAMETER || broken(ret == DMLERR_NO_ERROR), /* win9x */
462 "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
464 DdeFreeStringHandle(client_pid, topic);
465 DdeFreeDataHandle(hdata);
467 item = DdeCreateStringHandleA(client_pid, "executed", CP_WINANSI);
469 /* verify the execute */
470 res = 0xdeadbeef;
471 DdeGetLastError(client_pid);
472 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
473 ret = DdeGetLastError(client_pid);
474 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
475 ok(res == DDE_FNOTPROCESSED || broken(res == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
476 "Expected DDE_FNOTPROCESSED, got %d\n", res);
477 if (hdata == NULL)
478 ok(FALSE, "hdata is NULL\n");
479 else
481 str = (LPSTR)DdeAccessData(hdata, &size);
482 ok(!lstrcmpA(str, "command executed\r\n"), "Expected 'command executed\\r\\n', got %s\n", str);
483 ok(size == 19, "Expected 19, got %d\n", size);
485 ret = DdeUnaccessData(hdata);
486 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
489 /* invalid transactions */
490 res = 0xdeadbeef;
491 DdeGetLastError(client_pid);
492 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ADVREQ, default_timeout, &res);
493 ret = DdeGetLastError(client_pid);
494 ok(op == NULL, "Expected NULL, got %p\n", op);
495 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
496 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
498 res = 0xdeadbeef;
499 DdeGetLastError(client_pid);
500 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT, default_timeout, &res);
501 ret = DdeGetLastError(client_pid);
502 ok(op == NULL, "Expected NULL, got %p\n", op);
503 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
504 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
506 res = 0xdeadbeef;
507 DdeGetLastError(client_pid);
508 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT_CONFIRM, default_timeout, &res);
509 ret = DdeGetLastError(client_pid);
510 ok(op == NULL, "Expected NULL, got %p\n", op);
511 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
512 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
514 res = 0xdeadbeef;
515 DdeGetLastError(client_pid);
516 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_DISCONNECT, default_timeout, &res);
517 ret = DdeGetLastError(client_pid);
518 ok(op == NULL, "Expected NULL, got %p\n", op);
519 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
520 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
522 res = 0xdeadbeef;
523 DdeGetLastError(client_pid);
524 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ERROR, default_timeout, &res);
525 ret = DdeGetLastError(client_pid);
526 ok(op == NULL, "Expected NULL, got %p\n", op);
527 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
528 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
530 res = 0xdeadbeef;
531 DdeGetLastError(client_pid);
532 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_MONITOR, default_timeout, &res);
533 ret = DdeGetLastError(client_pid);
534 ok(op == NULL, "Expected NULL, got %p\n", op);
535 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
536 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
538 res = 0xdeadbeef;
539 DdeGetLastError(client_pid);
540 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REGISTER, default_timeout, &res);
541 ret = DdeGetLastError(client_pid);
542 ok(op == NULL, "Expected NULL, got %p\n", op);
543 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
544 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
546 res = 0xdeadbeef;
547 DdeGetLastError(client_pid);
548 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_UNREGISTER, default_timeout, &res);
549 ret = DdeGetLastError(client_pid);
550 ok(op == NULL, "Expected NULL, got %p\n", op);
551 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
552 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
554 res = 0xdeadbeef;
555 DdeGetLastError(client_pid);
556 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_WILDCONNECT, default_timeout, &res);
557 ret = DdeGetLastError(client_pid);
558 ok(op == NULL, "Expected NULL, got %p\n", op);
559 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
560 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
562 res = 0xdeadbeef;
563 DdeGetLastError(client_pid);
564 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_XACT_COMPLETE, default_timeout, &res);
565 ret = DdeGetLastError(client_pid);
566 ok(op == NULL, "Expected NULL, got %p\n", op);
567 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
568 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
570 DdeFreeStringHandle(client_pid, item);
572 ret = DdeDisconnect(conversation);
573 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
575 ret = DdeUninitialize(client_pid);
576 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
579 static DWORD server_pid;
581 static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hconv,
582 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
583 ULONG_PTR dwData1, ULONG_PTR dwData2)
585 char str[MAX_PATH], *ptr;
586 HDDEDATA ret = NULL;
587 DWORD size;
589 static int msg_index = 0;
590 static HCONV conversation = 0;
592 msg_index++;
594 switch (uType)
596 case XTYP_REGISTER:
598 ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
599 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
600 ok(hconv == 0, "Expected 0, got %p\n", hconv);
601 ok(hdata == 0, "Expected 0, got %p\n", hdata);
602 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
603 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
605 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
606 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
607 ok(size == 13, "Expected 13, got %d\n", size);
609 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
610 if (!strncmp( str, "TestDDEServer:(", 15 )) /* win9x style */
612 ok(size == 16 + 2*sizeof(WORD), "Got size %d for %s\n", size, str);
614 else
616 ok(!strncmp(str, "TestDDEServer(", 14), "Expected TestDDEServer(, got %s\n", str);
617 ok(size == 17 + 2*sizeof(ULONG_PTR), "Got size %d for %s\n", size, str);
619 ok(str[size - 1] == ')', "Expected ')', got %c\n", str[size - 1]);
621 return (HDDEDATA)TRUE;
624 case XTYP_CONNECT:
626 ok(msg_index == 2, "Expected 2, got %d\n", msg_index);
627 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
628 ok(hconv == 0, "Expected 0, got %p\n", hconv);
629 ok(hdata == 0, "Expected 0, got %p\n", hdata);
630 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
631 ok(dwData2 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
633 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
634 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
635 ok(size == 12, "Expected 12, got %d\n", size);
637 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
638 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
639 ok(size == 13, "Expected 13, got %d\n", size);
641 return (HDDEDATA)TRUE;
644 case XTYP_CONNECT_CONFIRM:
646 conversation = hconv;
648 ok(msg_index == 3, "Expected 3, got %d\n", msg_index);
649 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
650 ok(hconv != NULL, "Expected non-NULL hconv\n");
651 ok(hdata == 0, "Expected 0, got %p\n", hdata);
652 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
653 ok(dwData2 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
655 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
656 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
657 ok(size == 12, "Expected 12, got %d\n", size);
659 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
660 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
661 ok(size == 13, "Expected 13, got %d\n", size);
663 return (HDDEDATA)TRUE;
666 case XTYP_REQUEST:
668 ok(msg_index == 4 || msg_index == 5 || msg_index == 6,
669 "Expected 4, 5 or 6, got %d\n", msg_index);
670 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
671 ok(hdata == 0, "Expected 0, got %p\n", hdata);
672 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
673 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
675 if (msg_index == 4)
676 ok(uFmt == 0xbeef, "Expected 0xbeef, got %08x\n", uFmt);
677 else
678 ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %08x\n", uFmt);
680 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
681 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
682 ok(size == 12, "Expected 12, got %d\n", size);
684 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
686 if (msg_index == 5)
689 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
690 ok(size == 1, "Expected 1, got %d\n", size);
693 else if (msg_index == 6)
695 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
696 ok(size == 7, "Expected 7, got %d\n", size);
699 if (msg_index == 6)
701 lstrcpyA(str, "requested data\r\n");
702 return DdeCreateDataHandle(server_pid, (LPBYTE)str, lstrlenA(str) + 1,
703 0, hsz2, CF_TEXT, 0);
706 return NULL;
709 case XTYP_POKE:
711 ok(msg_index == 7 || msg_index == 8, "Expected 7 or 8, got %d\n", msg_index);
712 ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %d\n", uFmt);
713 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
714 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
715 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
717 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
718 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
719 ok(size == 12, "Expected 12, got %d\n", size);
721 ptr = (LPSTR)DdeAccessData(hdata, &size);
722 ok(!lstrcmpA(ptr, "poke data\r\n"), "Expected 'poke data\\r\\n', got %s\n", ptr);
723 ok(size == 12 || broken(size == 28), /* sizes are rounded up on win9x */
724 "Expected 12, got %d\n", size);
725 DdeUnaccessData(hdata);
727 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
728 if (msg_index == 7)
731 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
732 ok(size == 1, "Expected 1, got %d\n", size);
735 else
737 ok(!lstrcmpA(str, "poke"), "Expected poke, got %s\n", str);
738 ok(size == 4, "Expected 4, got %d\n", size);
741 return (HDDEDATA)DDE_FACK;
744 case XTYP_EXECUTE:
746 ok(msg_index >= 9 && msg_index <= 11, "Expected 9 or 11, got %d\n", msg_index);
747 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
748 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
749 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
750 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
751 ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
753 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
754 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
755 ok(size == 12, "Expected 12, got %d\n", size);
757 if (msg_index == 9 || msg_index == 11)
759 ptr = (LPSTR)DdeAccessData(hdata, &size);
761 if (msg_index == 9)
763 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected '[Command(Var)]', got %s\n", ptr);
764 ok(size == 15, "Expected 15, got %d\n", size);
765 ret = (HDDEDATA)DDE_FACK;
767 else
769 ok(!lstrcmpA(ptr, "[BadCommand(Var)]"), "Expected '[BadCommand(Var)]', got %s\n", ptr);
770 ok(size == 18, "Expected 18, got %d\n", size);
771 ret = DDE_FNOTPROCESSED;
774 DdeUnaccessData(hdata);
776 else if (msg_index == 10)
778 DWORD rsize = 0;
780 size = DdeGetData(hdata, NULL, 0, 0);
781 ok(size == 17, "DdeGetData should have returned 17 not %d\n", size);
782 ptr = HeapAlloc(GetProcessHeap(), 0, size);
783 ok(ptr != NULL,"HeapAlloc should have returned ptr not NULL\n");
784 rsize = DdeGetData(hdata, (LPBYTE)ptr, size, 0);
785 ok(rsize == size, "DdeGetData did not return %d bytes but %d\n", size, rsize);
787 ok(!lstrcmpA(ptr, "[Command-2(Var)]"), "Expected '[Command-2(Var)]' got %s\n", ptr);
788 ok(size == 17, "Expected 17, got %d\n", size);
789 ret = (HDDEDATA)DDE_FACK;
791 HeapFree(GetProcessHeap(), 0, ptr);
794 return ret;
797 case XTYP_DISCONNECT:
799 ok(msg_index == 12, "Expected 12, got %d\n", msg_index);
800 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
801 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
802 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
803 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
804 ok(hsz1 == 0, "Expected 0, got %p\n", hsz2);
805 ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
807 return 0;
810 default:
811 ok(FALSE, "Unhandled msg: %08x\n", uType);
814 return 0;
817 static void test_ddeml_server(HANDLE hproc)
819 MSG msg;
820 UINT res;
821 BOOL ret;
822 HSZ server;
823 HDDEDATA hdata;
825 /* set up DDE server */
826 server_pid = 0;
827 res = DdeInitializeA(&server_pid, server_ddeml_callback, APPCLASS_STANDARD, 0);
828 ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
830 server = DdeCreateStringHandleA(server_pid, "TestDDEServer", CP_WINANSI);
831 ok(server != NULL, "Expected non-NULL string handle\n");
833 hdata = DdeNameService(server_pid, server, 0, DNS_REGISTER);
834 ok(hdata == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", hdata);
836 while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
838 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
840 ret = DdeUninitialize(server_pid);
841 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
842 GetExitCodeProcess( hproc, &res );
843 ok( !res, "client failed with %u error(s)\n", res );
846 static HWND client_hwnd, server_hwnd;
847 static ATOM server, topic, item;
848 static HGLOBAL execute_hglobal;
850 static LRESULT WINAPI dde_msg_client_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
852 char str[MAX_PATH];
853 UINT_PTR lo, hi;
854 DDEDATA *data;
855 DDEACK *ack;
856 DWORD size;
857 LPSTR ptr;
859 static int msg_index = 0;
861 if (msg < WM_DDE_FIRST || msg > WM_DDE_LAST)
862 return DefWindowProcA(hwnd, msg, wparam, lparam);
864 msg_index++;
866 switch (msg)
868 case WM_DDE_INITIATE:
870 ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
871 ok(wparam == (WPARAM)client_hwnd, "Expected client hwnd, got %08lx\n", wparam);
873 size = GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
874 ok(LOWORD(lparam) == server, "Expected server atom, got %08x\n", LOWORD(lparam));
875 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
876 ok(size == 13, "Expected 13, got %d\n", size);
878 size = GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
879 ok(HIWORD(lparam) == topic, "Expected topic atom, got %08x\n", HIWORD(lparam));
880 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
881 ok(size == 12, "Expected 12, got %d\n", size);
883 break;
886 case WM_DDE_ACK:
888 ok((msg_index >= 2 && msg_index <= 4) || (msg_index >= 6 && msg_index <= 11),
889 "Expected 2, 3, 4, 6, 7, 8, 9, 10 or 11, got %d\n", msg_index);
891 if (msg_index == 2)
893 server_hwnd = (HWND)wparam;
894 ok(wparam != 0, "Expected non-NULL wparam, got %08lx\n", wparam);
896 size = GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
897 ok(LOWORD(lparam) == server, "Expected server atom, got %08x\n", LOWORD(lparam));
898 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
899 ok(size == 13, "Expected 13, got %d\n", size);
901 size = GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
902 ok(HIWORD(lparam) == topic, "Expected topic atom, got %08x\n", HIWORD(lparam));
903 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
904 ok(size == 12, "Expected 12, got %d\n", size);
906 else if (msg_index >= 9 && msg_index <= 11)
908 ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
910 UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
912 ack = (DDEACK *)&lo;
913 ok(ack->bAppReturnCode == 0, "Expected 0, got %d\n", ack->bAppReturnCode);
914 ok(ack->reserved == 0, "Expected 0, got %d\n", ack->reserved);
915 ok(ack->fBusy == FALSE, "Expected FALSE, got %d\n", ack->fBusy);
917 ok(hi == (UINT_PTR)execute_hglobal, "Expected execute hglobal, got %08lx\n", hi);
918 ptr = GlobalLock((HGLOBAL)hi);
920 if (msg_index == 9)
922 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
923 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected '[Command(Var)]', got %s\n", ptr);
924 } else if (msg_index == 10)
926 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
927 ok(!lstrcmpA(ptr, "[Command-2(Var)]"), "Expected '[Command-2(Var)]', got %s\n", ptr);
929 else
931 ok(ack->fAck == FALSE, "Expected FALSE, got %d\n", ack->fAck);
932 ok(!lstrcmpA(ptr, "[BadCommand(Var)]"), "Expected '[BadCommand(Var)]', got %s\n", ptr);
935 GlobalUnlock((HGLOBAL)hi);
937 else
939 ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
941 UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
943 ack = (DDEACK *)&lo;
944 ok(ack->bAppReturnCode == 0, "Expected 0, got %d\n", ack->bAppReturnCode);
945 ok(ack->reserved == 0, "Expected 0, got %d\n", ack->reserved);
946 ok(ack->fBusy == FALSE, "Expected FALSE, got %d\n", ack->fBusy);
948 if (msg_index >= 7)
949 ok(ack->fAck == TRUE, "Expected TRUE, got %d\n", ack->fAck);
950 else
952 if (msg_index == 6) todo_wine
953 ok(ack->fAck == FALSE, "Expected FALSE, got %d\n", ack->fAck);
956 size = GlobalGetAtomNameA(hi, str, MAX_PATH);
957 if (msg_index == 3)
959 ok(hi == item, "Expected item atom, got %08lx\n", hi);
960 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
961 ok(size == 7, "Expected 7, got %d\n", size);
963 else if (msg_index == 4 || msg_index == 7)
965 ok(hi == 0, "Expected 0, got %08lx\n", hi);
966 ok(size == 0, "Expected empty string, got %d\n", size);
968 else
970 ok(hi == item, "Expected item atom, got %08lx\n", hi);
971 if (msg_index == 6) todo_wine
973 ok(!lstrcmpA(str, "poke"), "Expected poke, got %s\n", str);
974 ok(size == 4, "Expected 4, got %d\n", size);
979 break;
982 case WM_DDE_DATA:
984 ok(msg_index == 5, "Expected 5, got %d\n", msg_index);
985 ok(wparam == (WPARAM)server_hwnd, "Expected server hwnd, got %08lx\n", wparam);
987 UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi);
989 data = GlobalLock((HGLOBAL)lo);
990 ok(data->unused == 0, "Expected 0, got %d\n", data->unused);
991 ok(data->fResponse == TRUE, "Expected TRUE, got %d\n", data->fResponse);
992 todo_wine
994 ok(data->fRelease == TRUE, "Expected TRUE, got %d\n", data->fRelease);
996 ok(data->fAckReq == 0, "Expected 0, got %d\n", data->fAckReq);
997 ok(data->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", data->cfFormat);
998 ok(!lstrcmpA((LPSTR)data->Value, "requested data\r\n"),
999 "Expected 'requested data\\r\\n', got %s\n", data->Value);
1000 GlobalUnlock((HGLOBAL)lo);
1002 size = GlobalGetAtomNameA(hi, str, MAX_PATH);
1003 ok(hi == item, "Expected item atom, got %08x\n", HIWORD(lparam));
1004 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
1005 ok(size == 7, "Expected 7, got %d\n", size);
1007 GlobalFree((HGLOBAL)lo);
1008 GlobalDeleteAtom(hi);
1010 break;
1013 default:
1014 ok(FALSE, "Unhandled msg: %08x\n", msg);
1017 return DefWindowProcA(hwnd, msg, wparam, lparam);
1020 static HGLOBAL create_poke(void)
1022 HGLOBAL hglobal;
1023 DDEPOKE *poke;
1024 DWORD size;
1026 size = FIELD_OFFSET(DDEPOKE, Value[sizeof("poke data\r\n")]);
1027 hglobal = GlobalAlloc(GMEM_DDESHARE, size);
1028 ok(hglobal != 0, "Expected non-NULL hglobal\n");
1030 poke = GlobalLock(hglobal);
1031 poke->unused = 0;
1032 poke->fRelease = TRUE;
1033 poke->fReserved = TRUE;
1034 poke->cfFormat = CF_TEXT;
1035 lstrcpyA((LPSTR)poke->Value, "poke data\r\n");
1036 GlobalUnlock(hglobal);
1038 return hglobal;
1041 static HGLOBAL create_execute(LPCSTR command)
1043 HGLOBAL hglobal;
1044 LPSTR ptr;
1046 hglobal = GlobalAlloc(GMEM_DDESHARE, lstrlenA(command) + 1);
1047 ok(hglobal != 0, "Expected non-NULL hglobal\n");
1049 ptr = GlobalLock(hglobal);
1050 lstrcpyA(ptr, command);
1051 GlobalUnlock(hglobal);
1053 return hglobal;
1056 static void test_msg_client(void)
1058 HGLOBAL hglobal;
1059 LPARAM lparam;
1061 create_dde_window(&client_hwnd, "dde_client", dde_msg_client_wndproc);
1063 server = GlobalAddAtomA("TestDDEServer");
1064 ok(server != 0, "Expected non-NULL server\n");
1066 topic = GlobalAddAtomA("TestDDETopic");
1067 ok(topic != 0, "Expected non-NULL topic\n");
1069 SendMessageA(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)client_hwnd, MAKELONG(server, topic));
1071 GlobalDeleteAtom(server);
1072 GlobalDeleteAtom(topic);
1074 flush_events();
1076 item = GlobalAddAtomA("request");
1077 ok(item != 0, "Expected non-NULL item\n");
1079 /* WM_DDE_REQUEST, bad clipboard format */
1080 lparam = PackDDElParam(WM_DDE_REQUEST, 0xdeadbeef, item);
1081 PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1083 flush_events();
1085 /* WM_DDE_REQUEST, no item */
1086 lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, 0);
1087 PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1089 flush_events();
1091 /* WM_DDE_REQUEST, no client hwnd */
1092 lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, item);
1093 PostMessageA(server_hwnd, WM_DDE_REQUEST, 0, lparam);
1095 flush_events();
1097 /* WM_DDE_REQUEST, correct params */
1098 lparam = PackDDElParam(WM_DDE_REQUEST, CF_TEXT, item);
1099 PostMessageA(server_hwnd, WM_DDE_REQUEST, (WPARAM)client_hwnd, lparam);
1101 flush_events();
1103 GlobalDeleteAtom(item);
1104 item = GlobalAddAtomA("poke");
1105 ok(item != 0, "Expected non-NULL item\n");
1107 hglobal = create_poke();
1109 /* WM_DDE_POKE, no ddepoke */
1110 lparam = PackDDElParam(WM_DDE_POKE, 0, item);
1111 /* win9x returns 0 here and crashes in PostMessageA */
1112 if (lparam) {
1113 PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1114 flush_events();
1116 else
1117 win_skip("no lparam for WM_DDE_POKE\n");
1120 /* WM_DDE_POKE, no item */
1121 lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, 0);
1122 PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1124 flush_events();
1126 hglobal = create_poke();
1128 /* WM_DDE_POKE, no client hwnd */
1129 lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, item);
1130 PostMessageA(server_hwnd, WM_DDE_POKE, 0, lparam);
1132 flush_events();
1134 /* WM_DDE_POKE, all params correct */
1135 lparam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)hglobal, item);
1136 PostMessageA(server_hwnd, WM_DDE_POKE, (WPARAM)client_hwnd, lparam);
1138 flush_events();
1140 execute_hglobal = create_execute("[Command(Var)]");
1142 /* WM_DDE_EXECUTE, no lparam */
1143 PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, 0);
1145 flush_events();
1147 /* WM_DDE_EXECUTE, no hglobal */
1148 lparam = PackDDElParam(WM_DDE_EXECUTE, 0, 0);
1149 PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1151 flush_events();
1153 /* WM_DDE_EXECUTE, no client hwnd */
1154 lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1155 PostMessageA(server_hwnd, WM_DDE_EXECUTE, 0, lparam);
1157 flush_events();
1159 /* WM_DDE_EXECUTE, all params correct */
1160 lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1161 PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1163 flush_events();
1165 GlobalFree(execute_hglobal);
1166 execute_hglobal = create_execute("[Command-2(Var)]");
1168 /* WM_DDE_EXECUTE, all params correct */
1169 lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1170 PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1172 flush_events();
1174 GlobalFree(execute_hglobal);
1175 execute_hglobal = create_execute("[BadCommand(Var)]");
1177 /* WM_DDE_EXECUTE that will get rejected */
1178 lparam = PackDDElParam(WM_DDE_EXECUTE, 0, (UINT_PTR)execute_hglobal);
1179 PostMessageA(server_hwnd, WM_DDE_EXECUTE, (WPARAM)client_hwnd, lparam);
1181 flush_events();
1183 destroy_dde_window(&client_hwnd, "dde_client");
1186 static LRESULT WINAPI hook_dde_client_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1188 UINT_PTR lo, hi;
1190 trace("hook_dde_client_wndprocA: %p %04x %08lx %08lx\n", hwnd, msg, wparam, lparam);
1192 switch (msg)
1194 case WM_DDE_ACK:
1195 UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
1196 trace("WM_DDE_ACK: status %04lx hglobal %p\n", lo, (HGLOBAL)hi);
1197 break;
1199 default:
1200 break;
1202 return CallWindowProcA(old_dde_client_wndproc, hwnd, msg, wparam, lparam);
1205 static LRESULT WINAPI hook_dde_client_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1207 UINT_PTR lo, hi;
1209 trace("hook_dde_client_wndprocW: %p %04x %08lx %08lx\n", hwnd, msg, wparam, lparam);
1211 switch (msg)
1213 case WM_DDE_ACK:
1214 UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
1215 trace("WM_DDE_ACK: status %04lx hglobal %p\n", lo, (HGLOBAL)hi);
1216 break;
1218 default:
1219 break;
1221 return CallWindowProcW(old_dde_client_wndproc, hwnd, msg, wparam, lparam);
1224 static LRESULT WINAPI dde_server_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1226 static BOOL client_unicode, conv_unicode;
1227 static int step;
1229 switch (msg)
1231 case WM_DDE_INITIATE:
1233 ATOM aService = GlobalAddAtomW(TEST_DDE_SERVICE);
1235 trace("server A: got WM_DDE_INITIATE from %p (%s) with %08lx\n",
1236 (HWND)wparam, client_unicode ? "Unicode" : "ANSI", lparam);
1238 if (LOWORD(lparam) == aService)
1240 client_unicode = IsWindowUnicode((HWND)wparam);
1241 conv_unicode = client_unicode;
1242 if (step >= 10) client_unicode = !client_unicode; /* change the client window type */
1244 if (client_unicode)
1245 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrW((HWND)wparam, GWLP_WNDPROC,
1246 (ULONG_PTR)hook_dde_client_wndprocW);
1247 else
1248 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrA((HWND)wparam, GWLP_WNDPROC,
1249 (ULONG_PTR)hook_dde_client_wndprocA);
1250 trace("server: sending WM_DDE_ACK to %p\n", (HWND)wparam);
1251 SendMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, PackDDElParam(WM_DDE_ACK, aService, 0));
1253 else
1254 GlobalDeleteAtom(aService);
1255 return 0;
1258 case WM_DDE_EXECUTE:
1260 DDEACK ack;
1261 WORD status;
1262 LPCSTR cmd;
1263 UINT_PTR lo, hi;
1265 trace("server A: got WM_DDE_EXECUTE from %p with %08lx\n", (HWND)wparam, lparam);
1267 UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
1268 trace("%08lx => lo %04lx hi %04lx\n", lparam, lo, hi);
1270 ack.bAppReturnCode = 0;
1271 ack.reserved = 0;
1272 ack.fBusy = 0;
1273 /* We have to send a negative acknowledge even if we don't
1274 * accept the command, otherwise Windows goes mad and next time
1275 * we send an acknowledge DDEML drops the connection.
1276 * Not sure how to call it: a bug or a feature.
1278 ack.fAck = 0;
1280 if ((cmd = GlobalLock((HGLOBAL)hi)))
1282 ack.fAck = !lstrcmpA(cmd, exec_cmdA) || !lstrcmpW((LPCWSTR)cmd, exec_cmdW);
1284 switch (step % 5)
1286 case 0: /* bad command */
1287 trace( "server A got unhandled command\n" );
1288 break;
1290 case 1: /* ANSI command */
1291 if (!conv_unicode)
1292 ok( !lstrcmpA(cmd, exec_cmdA), "server A got wrong command '%s'\n", cmd );
1293 else /* we get garbage as the A command was mapped W->A */
1294 ok( cmd[0] != exec_cmdA[0], "server A got wrong command '%s'\n", cmd );
1295 break;
1297 case 2: /* ANSI command in Unicode format */
1298 if (conv_unicode)
1299 ok( !lstrcmpA(cmd, exec_cmdA), "server A got wrong command '%s'\n", cmd );
1300 else
1301 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server A got wrong command '%s'\n", cmd );
1302 break;
1304 case 3: /* Unicode command */
1305 if (!conv_unicode)
1306 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server A got wrong command '%s'\n", cmd );
1307 else /* correctly mapped W->A */
1308 ok( !lstrcmpA(cmd, exec_cmdWA), "server A got wrong command '%s'\n", cmd );
1309 break;
1311 case 4: /* Unicode command in ANSI format */
1312 if (!conv_unicode)
1313 ok( !lstrcmpA(cmd, exec_cmdWA), "server A got wrong command '%s'\n", cmd );
1314 else /* we get garbage as the A command was mapped W->A */
1315 ok( cmd[0] != exec_cmdWA[0], "server A got wrong command '%s'\n", cmd );
1316 break;
1318 GlobalUnlock((HGLOBAL)hi);
1320 else ok( 0, "bad command data %lx\n", hi );
1322 step++;
1323 trace("server A: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1325 status = *((WORD *)&ack);
1326 lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, status, hi);
1328 PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1329 return 0;
1332 case WM_DDE_TERMINATE:
1334 DDEACK ack;
1335 WORD status;
1337 trace("server A: got WM_DDE_TERMINATE from %p with %08lx\n", (HWND)wparam, lparam);
1339 ack.bAppReturnCode = 0;
1340 ack.reserved = 0;
1341 ack.fBusy = 0;
1342 ack.fAck = 1;
1344 trace("server A: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1346 status = *((WORD *)&ack);
1347 lparam = PackDDElParam(WM_DDE_ACK, status, 0);
1349 PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1350 return 0;
1353 default:
1354 break;
1357 return DefWindowProcA(hwnd, msg, wparam, lparam);
1360 static LRESULT WINAPI dde_server_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1362 static BOOL client_unicode, conv_unicode;
1363 static int step;
1365 switch (msg)
1367 case WM_DDE_INITIATE:
1369 ATOM aService = GlobalAddAtomW(TEST_DDE_SERVICE);
1371 if (LOWORD(lparam) == aService)
1373 client_unicode = IsWindowUnicode((HWND)wparam);
1374 conv_unicode = client_unicode;
1375 if (step >= 10) client_unicode = !client_unicode; /* change the client window type */
1377 if (client_unicode)
1378 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrW((HWND)wparam, GWLP_WNDPROC,
1379 (ULONG_PTR)hook_dde_client_wndprocW);
1380 else
1381 old_dde_client_wndproc = (WNDPROC)SetWindowLongPtrA((HWND)wparam, GWLP_WNDPROC,
1382 (ULONG_PTR)hook_dde_client_wndprocA);
1383 trace("server W: sending WM_DDE_ACK to %p\n", (HWND)wparam);
1384 SendMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, PackDDElParam(WM_DDE_ACK, aService, 0));
1386 else
1387 GlobalDeleteAtom(aService);
1389 trace("server W: got WM_DDE_INITIATE from %p with %08lx (client %s conv %s)\n", (HWND)wparam,
1390 lparam, client_unicode ? "Unicode" : "ANSI", conv_unicode ? "Unicode" : "ANSI" );
1392 return 0;
1395 case WM_DDE_EXECUTE:
1397 DDEACK ack;
1398 WORD status;
1399 LPCSTR cmd;
1400 UINT_PTR lo, hi;
1402 trace("server W: got WM_DDE_EXECUTE from %p with %08lx\n", (HWND)wparam, lparam);
1404 UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
1405 trace("%08lx => lo %04lx hi %04lx\n", lparam, lo, hi);
1407 ack.bAppReturnCode = 0;
1408 ack.reserved = 0;
1409 ack.fBusy = 0;
1410 /* We have to send a negative acknowledge even if we don't
1411 * accept the command, otherwise Windows goes mad and next time
1412 * we send an acknowledge DDEML drops the connection.
1413 * Not sure how to call it: a bug or a feature.
1415 ack.fAck = 0;
1417 if ((cmd = GlobalLock((HGLOBAL)hi)))
1419 ack.fAck = !lstrcmpA(cmd, exec_cmdA) || !lstrcmpW((LPCWSTR)cmd, exec_cmdW);
1421 switch (step % 5)
1423 case 0: /* bad command */
1424 trace( "server W got unhandled command\n" );
1425 break;
1427 case 1: /* ANSI command */
1428 if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */
1429 ok( cmd[0] != exec_cmdA[0], "server W got wrong command '%s'\n", cmd );
1430 else if (!conv_unicode && client_unicode) /* A->W mapping */
1431 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server W got wrong command '%s'\n", cmd );
1432 else
1433 ok( !lstrcmpA(cmd, exec_cmdA), "server W got wrong command '%s'\n", cmd );
1434 break;
1436 case 2: /* ANSI command in Unicode format */
1437 if (conv_unicode && !client_unicode) /* W->A mapping */
1438 ok( !lstrcmpA(cmd, exec_cmdA), "server W got wrong command '%s'\n", cmd );
1439 else if (!conv_unicode && client_unicode) /* A->W mapping */
1440 ok( *(WCHAR *)cmd == exec_cmdAW[0], "server W got wrong command '%s'\n", cmd );
1441 else
1442 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server W got wrong command '%s'\n", cmd );
1443 break;
1445 case 3: /* Unicode command */
1446 if (conv_unicode && !client_unicode) /* W->A mapping */
1447 ok( !lstrcmpA(cmd, exec_cmdWA), "server W got wrong command '%s'\n", cmd );
1448 else if (!conv_unicode && client_unicode) /* A->W mapping */
1449 ok( *(WCHAR *)cmd == exec_cmdW[0], "server W got wrong command '%s'\n", cmd );
1450 else
1451 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server W got wrong command '%s'\n", cmd );
1452 break;
1454 case 4: /* Unicode command in ANSI format */
1455 if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */
1456 ok( cmd[0] != exec_cmdWA[0], "server W got wrong command '%s'\n", cmd );
1457 else if (!conv_unicode && client_unicode) /* A->W mapping */
1458 ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server W got wrong command '%s'\n", cmd );
1459 else
1460 ok( !lstrcmpA(cmd, exec_cmdWA), "server W got wrong command '%s'\n", cmd );
1461 break;
1463 GlobalUnlock((HGLOBAL)hi);
1465 else ok( 0, "bad command data %lx\n", hi );
1467 step++;
1468 trace("server W: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1470 status = *((WORD *)&ack);
1471 lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, status, hi);
1473 PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1474 return 0;
1477 case WM_DDE_TERMINATE:
1479 DDEACK ack;
1480 WORD status;
1482 trace("server W: got WM_DDE_TERMINATE from %p with %08lx\n", (HWND)wparam, lparam);
1484 ack.bAppReturnCode = 0;
1485 ack.reserved = 0;
1486 ack.fBusy = 0;
1487 ack.fAck = 1;
1489 trace("server W: posting %s WM_DDE_ACK to %p\n", ack.fAck ? "POSITIVE" : "NEGATIVE", (HWND)wparam);
1491 status = *((WORD *)&ack);
1492 lparam = PackDDElParam(WM_DDE_ACK, status, 0);
1494 PostMessageW((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
1495 return 0;
1498 default:
1499 break;
1502 return DefWindowProcW(hwnd, msg, wparam, lparam);
1505 static HWND create_dde_server( BOOL unicode )
1507 WNDCLASSA wcA;
1508 WNDCLASSW wcW;
1509 HWND server;
1510 static const char server_class_nameA[] = "dde_server_windowA";
1511 static const WCHAR server_class_nameW[] = {'d','d','e','_','s','e','r','v','e','r','_','w','i','n','d','o','w','W',0};
1513 if (unicode)
1515 memset(&wcW, 0, sizeof(wcW));
1516 wcW.lpfnWndProc = dde_server_wndprocW;
1517 wcW.lpszClassName = server_class_nameW;
1518 wcW.hInstance = GetModuleHandleA(0);
1519 RegisterClassW(&wcW);
1521 server = CreateWindowExW(0, server_class_nameW, NULL, WS_POPUP,
1522 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1523 GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
1525 else
1527 memset(&wcA, 0, sizeof(wcA));
1528 wcA.lpfnWndProc = dde_server_wndprocA;
1529 wcA.lpszClassName = server_class_nameA;
1530 wcA.hInstance = GetModuleHandleA(0);
1531 RegisterClassA(&wcA);
1533 server = CreateWindowExA(0, server_class_nameA, NULL, WS_POPUP,
1534 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1535 GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
1537 ok(!IsWindowUnicode(server) == !unicode, "wrong unicode type\n");
1538 return server;
1541 static HDDEDATA CALLBACK client_dde_callback(UINT uType, UINT uFmt, HCONV hconv,
1542 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
1543 ULONG_PTR dwData1, ULONG_PTR dwData2)
1545 static const char * const cmd_type[15] = {
1546 "XTYP_ERROR", "XTYP_ADVDATA", "XTYP_ADVREQ", "XTYP_ADVSTART",
1547 "XTYP_ADVSTOP", "XTYP_EXECUTE", "XTYP_CONNECT", "XTYP_CONNECT_CONFIRM",
1548 "XTYP_XACT_COMPLETE", "XTYP_POKE", "XTYP_REGISTER", "XTYP_REQUEST",
1549 "XTYP_DISCONNECT", "XTYP_UNREGISTER", "XTYP_WILDCONNECT" };
1550 UINT type;
1551 const char *cmd_name;
1553 type = (uType & XTYP_MASK) >> XTYP_SHIFT;
1554 cmd_name = (type <= 14) ? cmd_type[type] : "unknown";
1556 trace("client_dde_callback: %04x (%s) %d %p %p %p %p %08lx %08lx\n",
1557 uType, cmd_name, uFmt, hconv, hsz1, hsz2, hdata, dwData1, dwData2);
1558 return 0;
1561 static void test_dde_aw_transaction( BOOL client_unicode, BOOL server_unicode )
1563 HSZ hsz_server;
1564 DWORD dde_inst, ret, err;
1565 HCONV hconv;
1566 HWND hwnd_server;
1567 CONVINFO info;
1568 HDDEDATA hdata;
1569 BOOL conv_unicode = client_unicode;
1570 BOOL got;
1571 static char test_cmd[] = "test dde command";
1573 if (!(hwnd_server = create_dde_server( server_unicode ))) return;
1575 dde_inst = 0;
1576 if (client_unicode)
1577 ret = DdeInitializeW(&dde_inst, client_dde_callback, APPCMD_CLIENTONLY, 0);
1578 else
1579 ret = DdeInitializeA(&dde_inst, client_dde_callback, APPCMD_CLIENTONLY, 0);
1580 ok(ret == DMLERR_NO_ERROR, "DdeInitializeA failed with error %04x (%x)\n",
1581 ret, DdeGetLastError(dde_inst));
1583 hsz_server = DdeCreateStringHandleW(dde_inst, TEST_DDE_SERVICE, CP_WINUNICODE);
1585 hconv = DdeConnect(dde_inst, hsz_server, 0, NULL);
1586 ok(hconv != 0, "DdeConnect error %x\n", DdeGetLastError(dde_inst));
1587 err = DdeGetLastError(dde_inst);
1588 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1590 info.cb = sizeof(info);
1591 ret = DdeQueryConvInfo(hconv, QID_SYNC, &info);
1592 ok(ret, "wrong info size %d, DdeQueryConvInfo error %x\n", ret, DdeGetLastError(dde_inst));
1593 ok(info.ConvCtxt.iCodePage == (client_unicode ? CP_WINUNICODE : CP_WINANSI),
1594 "wrong iCodePage %d\n", info.ConvCtxt.iCodePage);
1595 ok(!info.hConvPartner, "unexpected info.hConvPartner: %p\n", info.hConvPartner);
1596 todo_wine {
1597 ok((info.wStatus & DDE_FACK), "unexpected info.wStatus: %04x\n", info.wStatus);
1599 ok((info.wStatus & (ST_CONNECTED | ST_CLIENT)) == (ST_CONNECTED | ST_CLIENT), "unexpected info.wStatus: %04x\n", info.wStatus);
1600 ok(info.wConvst == XST_CONNECTED, "unexpected info.wConvst: %04x\n", info.wConvst);
1601 ok(info.wType == 0, "unexpected info.wType: %04x\n", info.wType);
1603 client_unicode = IsWindowUnicode( info.hwnd );
1604 trace("hwnd %p, hwndPartner %p, unicode %u\n", info.hwnd, info.hwndPartner, client_unicode);
1606 trace("sending test client transaction command\n");
1607 ret = 0xdeadbeef;
1608 hdata = DdeClientTransaction((LPBYTE)test_cmd, strlen(test_cmd) + 1, hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
1609 ok(!hdata, "DdeClientTransaction succeeded\n");
1610 ok(ret == DDE_FNOTPROCESSED || broken(ret == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
1611 "wrong status code %04x\n", ret);
1612 err = DdeGetLastError(dde_inst);
1613 ok(err == DMLERR_NOTPROCESSED, "wrong dde error %x\n", err);
1615 trace("sending ANSI client transaction command\n");
1616 ret = 0xdeadbeef;
1617 hdata = DdeClientTransaction((LPBYTE)exec_cmdA, lstrlenA(exec_cmdA) + 1, hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1618 err = DdeGetLastError(dde_inst);
1619 if (conv_unicode && (!client_unicode || !server_unicode)) /* W->A mapping -> garbage */
1621 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1622 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1623 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1625 else if (!conv_unicode && client_unicode && server_unicode) /* A->W mapping -> wrong cmd */
1627 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1628 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1629 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1631 else /* no mapping */
1633 ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1634 ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1635 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1638 trace("sending ANSI-as-Unicode client transaction command\n");
1639 ret = 0xdeadbeef;
1640 hdata = DdeClientTransaction((LPBYTE)exec_cmdAW, (lstrlenW(exec_cmdAW) + 1) * sizeof(WCHAR),
1641 hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1642 err = DdeGetLastError(dde_inst);
1643 if (conv_unicode && (!client_unicode || !server_unicode)) /* W->A mapping */
1645 ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1646 ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1647 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1649 else if (!conv_unicode && client_unicode && server_unicode) /* A->W mapping -> garbage */
1651 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1652 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1653 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1655 else /* no mapping */
1657 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1658 ok(ret == DDE_FNOTPROCESSED || broken(ret == (0xdead0000 | DDE_FNOTPROCESSED)), /* win9x */
1659 "wrong status code %04x\n", ret);
1660 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1663 trace("sending unicode client transaction command\n");
1664 ret = 0xdeadbeef;
1665 hdata = DdeClientTransaction((LPBYTE)exec_cmdW, (lstrlenW(exec_cmdW) + 1) * sizeof(WCHAR), hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1666 err = DdeGetLastError(dde_inst);
1667 if (conv_unicode && (!client_unicode || !server_unicode)) /* W->A mapping -> wrong cmd */
1669 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1670 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1671 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1673 else if (!conv_unicode && client_unicode && server_unicode) /* A->W mapping -> garbage */
1675 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1676 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1677 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1679 else /* no mapping */
1681 ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1682 ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1683 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1686 trace("sending Unicode-as-ANSI client transaction command\n");
1687 ret = 0xdeadbeef;
1688 hdata = DdeClientTransaction((LPBYTE)exec_cmdWA, lstrlenA(exec_cmdWA) + 1, hconv, 0, 0, XTYP_EXECUTE, 1000, &ret);
1689 err = DdeGetLastError(dde_inst);
1690 if (conv_unicode && (!client_unicode || !server_unicode)) /* W->A mapping -> garbage */
1692 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1693 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1694 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1696 else if (!conv_unicode && client_unicode && server_unicode) /* A->W mapping */
1698 ok(hdata != 0, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1699 ok(ret == DDE_FACK, "wrong status code %04x\n", ret);
1700 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
1702 else /* no mapping */
1704 ok(!hdata, "DdeClientTransaction returned %p, error %x\n", hdata, err);
1705 ok(ret == DDE_FNOTPROCESSED, "wrong status code %04x\n", ret);
1706 ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err);
1709 got = DdeDisconnect(hconv);
1710 ok(got, "DdeDisconnect error %x\n", DdeGetLastError(dde_inst));
1712 info.cb = sizeof(info);
1713 ret = DdeQueryConvInfo(hconv, QID_SYNC, &info);
1714 ok(!ret, "DdeQueryConvInfo should fail\n");
1715 err = DdeGetLastError(dde_inst);
1716 todo_wine {
1717 ok(err == DMLERR_INVALIDPARAMETER, "wrong dde error %x\n", err);
1720 got = DdeFreeStringHandle(dde_inst, hsz_server);
1721 ok(got, "DdeFreeStringHandle error %x\n", DdeGetLastError(dde_inst));
1723 /* This call hangs on win2k SP4 and XP SP1.
1724 DdeUninitialize(dde_inst);*/
1726 DestroyWindow(hwnd_server);
1729 static void test_initialisation(void)
1731 UINT ret;
1732 DWORD res;
1733 HDDEDATA hdata;
1734 HSZ server, topic, item;
1735 DWORD client_pid;
1736 HCONV conversation;
1738 /* Initialise without a valid server window. */
1739 client_pid = 0;
1740 ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1741 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
1744 server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI);
1745 topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI);
1747 DdeGetLastError(client_pid);
1749 /* There is no server window so no conversation can be extracted */
1750 conversation = DdeConnect(client_pid, server, topic, NULL);
1751 ok(conversation == NULL, "Expected NULL conversation, %p\n", conversation);
1752 ret = DdeGetLastError(client_pid);
1753 ok(ret == DMLERR_NO_CONV_ESTABLISHED, "Expected DMLERR_NO_CONV_ESTABLISHED, got %d\n", ret);
1755 DdeFreeStringHandle(client_pid, server);
1757 item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI);
1759 /* There is no conversation so an invalid parameter results */
1760 res = 0xdeadbeef;
1761 DdeGetLastError(client_pid);
1762 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
1763 ok(hdata == NULL, "Expected NULL, got %p\n", hdata);
1764 ret = DdeGetLastError(client_pid);
1765 todo_wine
1766 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
1767 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res);
1769 DdeFreeStringHandle(client_pid, server);
1770 ret = DdeDisconnect(conversation);
1771 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1773 ret = DdeUninitialize(client_pid);
1774 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1777 static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage)
1779 static const WCHAR dde_string[] = {'D','D','E',' ','S','t','r','i','n','g',0};
1780 HSZ str_handle;
1781 WCHAR bufW[256];
1782 char buf[256];
1783 ATOM atom;
1784 int ret;
1786 str_handle = DdeCreateStringHandleW(dde_inst, dde_string, codepage);
1787 ok(str_handle != 0, "DdeCreateStringHandleW failed with error %08x\n",
1788 DdeGetLastError(dde_inst));
1790 ret = DdeQueryStringW(dde_inst, str_handle, NULL, 0, codepage);
1791 if (codepage == CP_WINANSI)
1792 ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret);
1793 else
1794 ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret);
1796 ret = DdeQueryStringW(dde_inst, str_handle, bufW, 256, codepage);
1797 if (codepage == CP_WINANSI)
1799 ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret);
1800 ok(!lstrcmpA("D", (LPCSTR)bufW), "DdeQueryStringW returned wrong string\n");
1802 else
1804 ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret);
1805 ok(!lstrcmpW(dde_string, bufW), "DdeQueryStringW returned wrong string\n");
1808 ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINANSI);
1809 if (codepage == CP_WINANSI)
1811 ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret);
1812 ok(!lstrcmpA("D", buf), "DdeQueryStringW returned wrong string\n");
1814 else
1816 ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret);
1817 ok(!lstrcmpA("DDE String", buf), "DdeQueryStringA returned wrong string %s\n", buf);
1820 ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINUNICODE);
1821 if (codepage == CP_WINANSI)
1823 ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret);
1824 ok(!lstrcmpA("D", buf), "DdeQueryStringA returned wrong string %s\n", buf);
1826 else
1828 ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret);
1829 ok(!lstrcmpW(dde_string, (LPCWSTR)buf), "DdeQueryStringW returned wrong string\n");
1832 if (codepage == CP_WINANSI)
1834 atom = FindAtomA((LPSTR)dde_string);
1835 ok(atom != 0, "Expected a valid atom\n");
1837 SetLastError(0xdeadbeef);
1838 atom = GlobalFindAtomA((LPSTR)dde_string);
1839 ok(atom == 0, "Expected 0, got %d\n", atom);
1840 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1841 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1843 else
1845 atom = FindAtomW(dde_string);
1846 ok(atom != 0, "Expected a valid atom\n");
1848 SetLastError(0xdeadbeef);
1849 atom = GlobalFindAtomW(dde_string);
1850 ok(atom == 0, "Expected 0, got %d\n", atom);
1851 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1852 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1855 ok(DdeFreeStringHandle(dde_inst, str_handle), "DdeFreeStringHandle failed\n");
1858 static void test_DdeCreateDataHandle(void)
1860 HDDEDATA hdata;
1861 DWORD dde_inst, dde_inst2;
1862 DWORD size;
1863 UINT res, err;
1864 BOOL ret;
1865 HSZ item;
1866 LPBYTE ptr;
1867 WCHAR item_str[] = {'i','t','e','m',0};
1869 dde_inst = 0;
1870 dde_inst2 = 0;
1871 res = DdeInitializeA(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1872 ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
1874 res = DdeInitializeA(&dde_inst2, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
1875 ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
1877 /* 0 instance id
1878 * This block tests an invalid instance Id. The correct behaviour is that if the instance Id
1879 * is invalid then the lastError of all instances is set to the error. There are two instances
1880 * created, lastError is cleared, an error is generated and then both instances are checked to
1881 * ensure that they both have the same error set
1883 item = DdeCreateStringHandleA(0, "item", CP_WINANSI);
1884 ok(item == NULL, "Expected NULL hsz got %p\n", item);
1885 err = DdeGetLastError(dde_inst);
1886 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1887 err = DdeGetLastError(dde_inst2);
1888 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1889 item = DdeCreateStringHandleW(0, item_str, CP_WINUNICODE);
1890 ok(item == NULL, "Expected NULL hsz got %p\n", item);
1891 err = DdeGetLastError(dde_inst);
1892 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1893 err = DdeGetLastError(dde_inst2);
1894 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1896 item = DdeCreateStringHandleA(dde_inst, "item", CP_WINANSI);
1897 ok(item != NULL, "Expected non-NULL hsz\n");
1898 item = DdeCreateStringHandleA(dde_inst2, "item", CP_WINANSI);
1899 ok(item != NULL, "Expected non-NULL hsz\n");
1901 if (0) {
1902 /* do not test with an invalid instance id: that crashes on win9x */
1903 hdata = DdeCreateDataHandle(0xdeadbeef, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0);
1906 /* 0 instance id
1907 * This block tests an invalid instance Id. The correct behaviour is that if the instance Id
1908 * is invalid then the lastError of all instances is set to the error. There are two instances
1909 * created, lastError is cleared, an error is generated and then both instances are checked to
1910 * ensure that they both have the same error set
1912 DdeGetLastError(dde_inst);
1913 DdeGetLastError(dde_inst2);
1914 hdata = DdeCreateDataHandle(0, (LPBYTE)"data", MAX_PATH, 0, item, CF_TEXT, 0);
1915 err = DdeGetLastError(dde_inst);
1916 ok(hdata == NULL, "Expected NULL, got %p\n", hdata);
1917 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1918 err = DdeGetLastError(dde_inst2);
1919 ok(err == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", err);
1921 ret = DdeUninitialize(dde_inst2);
1922 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1925 /* NULL pSrc */
1926 DdeGetLastError(dde_inst);
1927 hdata = DdeCreateDataHandle(dde_inst, NULL, MAX_PATH, 0, item, CF_TEXT, 0);
1928 err = DdeGetLastError(dde_inst);
1929 ok(hdata != NULL, "Expected non-NULL hdata\n");
1930 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1932 ptr = DdeAccessData(hdata, &size);
1933 ok(ptr != NULL, "Expected non-NULL ptr\n");
1934 ok(size == 260, "Expected 260, got %d\n", size);
1936 ret = DdeUnaccessData(hdata);
1937 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1939 ret = DdeFreeDataHandle(hdata);
1940 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1942 /* cb is zero */
1943 DdeGetLastError(dde_inst);
1944 hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", 0, 0, item, CF_TEXT, 0);
1945 err = DdeGetLastError(dde_inst);
1946 ok(hdata != NULL, "Expected non-NULL hdata\n");
1947 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1949 ptr = DdeAccessData(hdata, &size);
1950 ok(ptr != NULL, "Expected non-NULL ptr\n");
1951 ok(size == 0, "Expected 0, got %d\n", size);
1953 ret = DdeUnaccessData(hdata);
1954 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1956 ret = DdeFreeDataHandle(hdata);
1957 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1959 /* cbOff is non-zero */
1960 DdeGetLastError(dde_inst);
1961 hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 2, item, CF_TEXT, 0);
1962 err = DdeGetLastError(dde_inst);
1963 ok(hdata != NULL, "Expected non-NULL hdata\n");
1964 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1966 ptr = DdeAccessData(hdata, &size);
1967 ok(ptr != NULL, "Expected non-NULL ptr\n");
1968 ok(size == 262, "Expected 262, got %d\n", size);
1969 todo_wine
1971 ok(lstrlenA((LPSTR)ptr) == 0, "Expected 0, got %d\n", lstrlenA((LPSTR)ptr));
1974 ret = DdeUnaccessData(hdata);
1975 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1977 ret = DdeFreeDataHandle(hdata);
1978 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1980 /* NULL item */
1981 DdeGetLastError(dde_inst);
1982 hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, 0, CF_TEXT, 0);
1983 err = DdeGetLastError(dde_inst);
1984 ok(hdata != NULL, "Expected non-NULL hdata\n");
1985 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
1987 ptr = DdeAccessData(hdata, &size);
1988 ok(ptr != NULL, "Expected non-NULL ptr\n");
1989 ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
1990 ok(size == 260, "Expected 260, got %d\n", size);
1992 ret = DdeUnaccessData(hdata);
1993 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1995 ret = DdeFreeDataHandle(hdata);
1996 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1998 /* NULL item */
1999 DdeGetLastError(dde_inst);
2000 hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, (HSZ)0xdeadbeef, CF_TEXT, 0);
2001 err = DdeGetLastError(dde_inst);
2002 ok(hdata != NULL, "Expected non-NULL hdata\n");
2003 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
2005 ptr = DdeAccessData(hdata, &size);
2006 ok(ptr != NULL, "Expected non-NULL ptr\n");
2007 ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
2008 ok(size == 260, "Expected 260, got %d\n", size);
2010 ret = DdeUnaccessData(hdata);
2011 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2013 ret = DdeFreeDataHandle(hdata);
2014 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2016 /* invalid clipboard format */
2017 DdeGetLastError(dde_inst);
2018 hdata = DdeCreateDataHandle(dde_inst, (LPBYTE)"data", MAX_PATH, 0, item, 0xdeadbeef, 0);
2019 err = DdeGetLastError(dde_inst);
2020 ok(hdata != NULL, "Expected non-NULL hdata\n");
2021 ok(err == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", err);
2023 ptr = DdeAccessData(hdata, &size);
2024 ok(ptr != NULL, "Expected non-NULL ptr\n");
2025 ok(!lstrcmpA((LPSTR)ptr, "data"), "Expected data, got %s\n", ptr);
2026 ok(size == 260, "Expected 260, got %d\n", size);
2028 ret = DdeUnaccessData(hdata);
2029 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2031 ret = DdeFreeDataHandle(hdata);
2032 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2034 ret = DdeUninitialize(dde_inst);
2035 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2038 static void test_DdeCreateStringHandle(void)
2040 DWORD dde_inst, ret;
2042 dde_inst = 0xdeadbeef;
2043 SetLastError(0xdeadbeef);
2044 ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
2045 ok(ret == DMLERR_INVALIDPARAMETER, "DdeInitializeW should fail, but got %04x instead\n", ret);
2046 ok(DdeGetLastError(dde_inst) == DMLERR_INVALIDPARAMETER, "expected DMLERR_INVALIDPARAMETER\n");
2048 dde_inst = 0;
2049 ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
2050 ok(ret == DMLERR_NO_ERROR, "DdeInitializeW failed with error %04x (%08x)\n",
2051 ret, DdeGetLastError(dde_inst));
2053 test_DdeCreateStringHandleW(dde_inst, 0);
2054 test_DdeCreateStringHandleW(dde_inst, CP_WINUNICODE);
2055 test_DdeCreateStringHandleW(dde_inst, CP_WINANSI);
2057 ok(DdeUninitialize(dde_inst), "DdeUninitialize failed\n");
2060 static void test_FreeDDElParam(void)
2062 HGLOBAL val, hglobal;
2063 BOOL ret;
2065 ret = FreeDDElParam(WM_DDE_INITIATE, 0);
2066 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2068 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2069 ret = FreeDDElParam(WM_DDE_INITIATE, (LPARAM)hglobal);
2070 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2071 val = GlobalFree(hglobal);
2072 ok(val == NULL, "Expected NULL, got %p\n", val);
2074 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2075 ret = FreeDDElParam(WM_DDE_ADVISE, (LPARAM)hglobal);
2076 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2078 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2079 ret = FreeDDElParam(WM_DDE_UNADVISE, (LPARAM)hglobal);
2080 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2081 val = GlobalFree(hglobal);
2082 ok(val == NULL, "Expected NULL, got %p\n", val);
2084 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2085 ret = FreeDDElParam(WM_DDE_ACK, (LPARAM)hglobal);
2086 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2088 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2089 ret = FreeDDElParam(WM_DDE_DATA, (LPARAM)hglobal);
2090 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2092 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2093 ret = FreeDDElParam(WM_DDE_REQUEST, (LPARAM)hglobal);
2094 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2095 val = GlobalFree(hglobal);
2096 ok(val == NULL, "Expected NULL, got %p\n", val);
2098 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2099 ret = FreeDDElParam(WM_DDE_POKE, (LPARAM)hglobal);
2100 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2102 hglobal = GlobalAlloc(GMEM_DDESHARE, 100);
2103 ret = FreeDDElParam(WM_DDE_EXECUTE, (LPARAM)hglobal);
2104 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2105 val = GlobalFree(hglobal);
2106 ok(val == NULL, "Expected NULL, got %p\n", val);
2109 static void test_PackDDElParam(void)
2111 UINT_PTR lo, hi, *ptr;
2112 LPARAM lparam;
2113 BOOL ret;
2115 lparam = PackDDElParam(WM_DDE_INITIATE, 0xcafe, 0xbeef);
2116 /* value gets sign-extended despite being an LPARAM */
2117 ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2119 lo = hi = 0;
2120 ret = UnpackDDElParam(WM_DDE_INITIATE, lparam, &lo, &hi);
2121 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2122 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2123 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2125 ret = FreeDDElParam(WM_DDE_INITIATE, lparam);
2126 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2128 lparam = PackDDElParam(WM_DDE_TERMINATE, 0xcafe, 0xbeef);
2129 ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2131 lo = hi = 0;
2132 ret = UnpackDDElParam(WM_DDE_TERMINATE, lparam, &lo, &hi);
2133 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2134 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2135 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2137 ret = FreeDDElParam(WM_DDE_TERMINATE, lparam);
2138 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2140 lparam = PackDDElParam(WM_DDE_ADVISE, 0xcafe, 0xbeef);
2141 /* win9x returns 0 here */
2142 if (lparam) {
2143 ptr = GlobalLock((HGLOBAL)lparam);
2144 ok(ptr != NULL, "Expected non-NULL ptr\n");
2145 ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2146 ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2148 ret = GlobalUnlock((HGLOBAL)lparam);
2149 ok(ret == 1, "Expected 1, got %d\n", ret);
2151 lo = hi = 0;
2152 ret = UnpackDDElParam(WM_DDE_ADVISE, lparam, &lo, &hi);
2153 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2154 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2155 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2157 else
2158 win_skip("no lparam for WM_DDE_ADVISE\n");
2160 ret = FreeDDElParam(WM_DDE_ADVISE, lparam);
2161 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2163 lparam = PackDDElParam(WM_DDE_UNADVISE, 0xcafe, 0xbeef);
2164 ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2166 lo = hi = 0;
2167 ret = UnpackDDElParam(WM_DDE_UNADVISE, lparam, &lo, &hi);
2168 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2169 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2170 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2172 ret = FreeDDElParam(WM_DDE_UNADVISE, lparam);
2173 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2175 lparam = PackDDElParam(WM_DDE_ACK, 0xcafe, 0xbeef);
2176 /* win9x returns the input (0xbeef<<16 | 0xcafe) here */
2177 if (lparam != (int)0xbeefcafe) {
2178 ptr = GlobalLock((HGLOBAL)lparam);
2179 ok(ptr != NULL, "Expected non-NULL ptr\n");
2180 ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2181 ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2183 ret = GlobalUnlock((HGLOBAL)lparam);
2184 ok(ret == 1, "Expected 1, got %d\n", ret);
2186 lo = hi = 0;
2187 ret = UnpackDDElParam(WM_DDE_ACK, lparam, &lo, &hi);
2188 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2189 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2190 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2192 ret = FreeDDElParam(WM_DDE_ACK, lparam);
2193 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2195 else
2196 win_skip("got lparam 0x%lx for WM_DDE_ACK\n", lparam);
2198 lparam = PackDDElParam(WM_DDE_DATA, 0xcafe, 0xbeef);
2199 /* win9x returns 0 here */
2200 if (lparam) {
2201 ptr = GlobalLock((HGLOBAL)lparam);
2202 ok(ptr != NULL, "Expected non-NULL ptr\n");
2203 ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2204 ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2206 ret = GlobalUnlock((HGLOBAL)lparam);
2207 ok(ret == 1, "Expected 1, got %d\n", ret);
2209 lo = hi = 0;
2210 ret = UnpackDDElParam(WM_DDE_DATA, lparam, &lo, &hi);
2211 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2212 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2213 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2215 else
2216 win_skip("no lparam for WM_DDE_DATA\n");
2218 ret = FreeDDElParam(WM_DDE_DATA, lparam);
2219 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2221 lparam = PackDDElParam(WM_DDE_REQUEST, 0xcafe, 0xbeef);
2222 ok(lparam == (int)0xbeefcafe, "Expected 0xbeefcafe, got %08lx\n", lparam);
2224 lo = hi = 0;
2225 ret = UnpackDDElParam(WM_DDE_REQUEST, lparam, &lo, &hi);
2226 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2227 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2228 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2230 ret = FreeDDElParam(WM_DDE_REQUEST, lparam);
2231 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2233 lparam = PackDDElParam(WM_DDE_POKE, 0xcafe, 0xbeef);
2234 /* win9x returns 0 here */
2235 if (lparam) {
2236 ptr = GlobalLock((HGLOBAL)lparam);
2237 ok(ptr != NULL, "Expected non-NULL ptr\n");
2238 ok(ptr[0] == 0xcafe, "Expected 0xcafe, got %08lx\n", ptr[0]);
2239 ok(ptr[1] == 0xbeef, "Expected 0xbeef, got %08lx\n", ptr[1]);
2241 ret = GlobalUnlock((HGLOBAL)lparam);
2242 ok(ret == 1, "Expected 1, got %d\n", ret);
2244 lo = hi = 0;
2245 ret = UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi);
2246 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2247 ok(lo == 0xcafe, "Expected 0xcafe, got %08lx\n", lo);
2248 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2250 else
2251 win_skip("no lparam for WM_DDE_POKE\n");
2253 ret = FreeDDElParam(WM_DDE_POKE, lparam);
2254 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2256 lparam = PackDDElParam(WM_DDE_EXECUTE, 0xcafe, 0xbeef);
2257 ok(lparam == 0xbeef, "Expected 0xbeef, got %08lx\n", lparam);
2259 lo = hi = 0;
2260 ret = UnpackDDElParam(WM_DDE_EXECUTE, lparam, &lo, &hi);
2261 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2262 ok(lo == 0, "Expected 0, got %08lx\n", lo);
2263 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2265 ret = FreeDDElParam(WM_DDE_EXECUTE, lparam);
2266 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2269 static void test_UnpackDDElParam(void)
2271 UINT_PTR lo, hi, *ptr;
2272 HGLOBAL hglobal;
2273 BOOL ret;
2275 /* NULL lParam */
2276 lo = 0xdead;
2277 hi = 0xbeef;
2278 ret = UnpackDDElParam(WM_DDE_INITIATE, 0, &lo, &hi);
2279 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2280 ok(lo == 0, "Expected 0, got %08lx\n", lo);
2281 ok(hi == 0, "Expected 0, got %08lx\n", hi);
2283 /* NULL lo */
2284 lo = 0xdead;
2285 hi = 0xbeef;
2286 ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, NULL, &hi);
2287 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2288 ok(lo == 0xdead, "Expected 0xdead, got %08lx\n", lo);
2289 ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2291 /* NULL hi */
2292 lo = 0xdead;
2293 hi = 0xbeef;
2294 ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, &lo, NULL);
2295 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2296 ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2297 ok(hi == 0xbeef, "Expected 0xbeef, got %08lx\n", hi);
2299 lo = 0xdead;
2300 hi = 0xbeef;
2301 ret = UnpackDDElParam(WM_DDE_INITIATE, 0xcafebabe, &lo, &hi);
2302 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2303 ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2304 ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2306 lo = 0xdead;
2307 hi = 0xbeef;
2308 ret = UnpackDDElParam(WM_DDE_TERMINATE, 0xcafebabe, &lo, &hi);
2309 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2310 ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2311 ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2313 lo = 0xdead;
2314 hi = 0xbeef;
2315 ret = UnpackDDElParam(WM_DDE_ADVISE, 0, &lo, &hi);
2316 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
2317 ok(lo == 0 ||
2318 broken(lo == 0xdead), /* win2k */
2319 "Expected 0, got %08lx\n", lo);
2320 ok(hi == 0 ||
2321 broken(hi == 0xbeef), /* win2k */
2322 "Expected 0, got %08lx\n", hi);
2324 hglobal = GlobalAlloc(GMEM_DDESHARE, 2 * sizeof(*ptr));
2325 ptr = GlobalLock(hglobal);
2326 ptr[0] = 0xcafebabe;
2327 ptr[1] = 0xdeadbeef;
2328 GlobalUnlock(hglobal);
2330 lo = 0xdead;
2331 hi = 0xbeef;
2332 ret = UnpackDDElParam(WM_DDE_ADVISE, (LPARAM)hglobal, &lo, &hi);
2333 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2334 ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2335 ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2337 lo = 0xdead;
2338 hi = 0xbeef;
2339 ret = UnpackDDElParam(WM_DDE_UNADVISE, 0xcafebabe, &lo, &hi);
2340 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2341 ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2342 ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2344 lo = 0xdead;
2345 hi = 0xbeef;
2346 ret = UnpackDDElParam(WM_DDE_ACK, (LPARAM)hglobal, &lo, &hi);
2347 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2348 ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2349 ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2351 lo = 0xdead;
2352 hi = 0xbeef;
2353 ret = UnpackDDElParam(WM_DDE_DATA, (LPARAM)hglobal, &lo, &hi);
2354 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2355 ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2356 ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2358 lo = 0xdead;
2359 hi = 0xbeef;
2360 ret = UnpackDDElParam(WM_DDE_REQUEST, 0xcafebabe, &lo, &hi);
2361 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2362 ok(lo == 0xbabe, "Expected 0xbabe, got %08lx\n", lo);
2363 ok(hi == 0xcafe, "Expected 0xcafe, got %08lx\n", hi);
2365 lo = 0xdead;
2366 hi = 0xbeef;
2367 ret = UnpackDDElParam(WM_DDE_POKE, (LPARAM)hglobal, &lo, &hi);
2368 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2369 ok(lo == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", lo);
2370 ok(hi == 0xdeadbeef, "Expected 0xdeadbeef, got %08lx\n", hi);
2372 lo = 0xdead;
2373 hi = 0xbeef;
2374 ret = UnpackDDElParam(WM_DDE_EXECUTE, 0xcafebabe, &lo, &hi);
2375 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2376 ok(lo == 0, "Expected 0, got %08lx\n", lo);
2377 ok(hi == 0xcafebabe, "Expected 0xcafebabe, got %08lx\n", hi);
2379 GlobalFree(hglobal);
2382 static char test_cmd_a_to_a[] = "Test dde command";
2383 static WCHAR test_cmd_w_to_w[][32] = {
2384 {'t','e','s','t',' ','d','d','e',' ','c','o','m','m','a','n','d',0},
2385 { 0x2018, 0x2019, 0x0161, 0x0041, 0x02dc, 0 }, /* some chars that should map properly to CP1252 */
2386 { 0x2026, 0x2020, 0x2021, 0x0d0a, 0 }, /* false negative for IsTextUnicode */
2387 { 0x4efa, 0x4efc, 0x0061, 0x4efe, 0 }, /* some Chinese chars */
2389 static const int nb_callbacks = 5 + sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]);
2391 static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv,
2392 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
2393 ULONG_PTR dwData1, ULONG_PTR dwData2)
2395 DWORD size, rsize;
2396 char str[MAX_PATH];
2397 static int msg_index = 0;
2398 static HCONV conversation = 0;
2399 static const char test_service [] = "TestDDEService";
2400 static const char test_topic [] = "TestDDETopic";
2402 msg_index++;
2404 switch (uType)
2406 case XTYP_REGISTER:
2408 ok(msg_index % nb_callbacks == 1, "Expected 1 modulo %u, got %d\n", nb_callbacks, msg_index);
2409 return (HDDEDATA)TRUE;
2412 case XTYP_CONNECT:
2414 ok(msg_index % nb_callbacks == 2, "Expected 2 modulo %u, got %d\n", nb_callbacks, msg_index);
2415 ok(uFmt == 0, "Expected 0, got %d, msg_index=%d\n", uFmt, msg_index);
2416 ok(hconv == 0, "Expected 0, got %p, msg_index=%d\n", hconv, msg_index);
2417 ok(hdata == 0, "Expected 0, got %p, msg_index=%d\n", hdata, msg_index);
2418 ok(dwData1 != 0, "Expected not 0, got %08lx, msg_index=%d\n", dwData1, msg_index);
2419 ok(dwData2 == FALSE, "Expected FALSE, got %08lx, msg_index=%d\n", dwData2, msg_index);
2421 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
2422 ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n",
2423 test_topic, str, msg_index);
2424 ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index);
2426 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
2427 ok(!lstrcmpA(str, test_service), "Expected %s, got %s, msg_index=%d\n",
2428 test_service, str, msg_index);
2429 ok(size == 14, "Expected 14, got %d, msg_index=%d\n", size, msg_index);
2431 return (HDDEDATA) TRUE;
2433 case XTYP_CONNECT_CONFIRM:
2435 ok(msg_index % nb_callbacks == 3, "Expected 3 modulo %u, got %d\n", nb_callbacks, msg_index);
2436 conversation = hconv;
2437 return (HDDEDATA) TRUE;
2439 case XTYP_EXECUTE:
2441 BYTE *buffer = NULL;
2442 WCHAR *cmd_w;
2443 char test_cmd_w_to_a[64];
2444 WCHAR test_cmd_a_to_w[64];
2445 DWORD size_a, size_w, size_w_to_a, size_a_to_w;
2446 BOOL unicode_server, unicode_client, str_index;
2448 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
2449 ok(hconv == conversation, "Expected conversation handle, got %p, msg_index=%d\n",
2450 hconv, msg_index);
2451 ok(dwData1 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData1, msg_index);
2452 ok(dwData2 == 0, "Expected 0, got %08lx, msg_index=%d\n", dwData2, msg_index);
2453 ok(hsz2 == 0, "Expected 0, got %p, msg_index=%d\n", hsz2, msg_index);
2454 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
2455 ok(!lstrcmpA(str, test_topic), "Expected %s, got %s, msg_index=%d\n",
2456 test_topic, str, msg_index);
2457 ok(size == 12, "Expected 12, got %d, msg_index=%d\n", size, msg_index);
2459 size = DdeGetData(hdata, NULL, 0, 0);
2460 ok((buffer = HeapAlloc(GetProcessHeap(), 0, size)) != NULL, "should not be null\n");
2461 rsize = DdeGetData(hdata, buffer, size, 0);
2462 ok(rsize == size, "Incorrect size returned, expected %d got %d, msg_index=%d\n",
2463 size, rsize, msg_index);
2464 trace("msg %u strA \"%s\" strW %s\n", msg_index, buffer, wine_dbgstr_w((WCHAR*)buffer));
2466 unicode_server = (msg_index / nb_callbacks == 1 || msg_index / nb_callbacks == 2);
2467 unicode_client = (msg_index / nb_callbacks == 1 || msg_index / nb_callbacks == 3);
2468 str_index = msg_index % nb_callbacks - 4;
2469 cmd_w = test_cmd_w_to_w[str_index - 1];
2470 size_a = strlen(test_cmd_a_to_a) + 1;
2471 size_w = (lstrlenW(cmd_w) + 1) * sizeof(WCHAR);
2472 size_a_to_w = MultiByteToWideChar( CP_ACP, 0, test_cmd_a_to_a, -1, test_cmd_a_to_w,
2473 sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
2474 size_w_to_a = WideCharToMultiByte( CP_ACP, 0, cmd_w, -1,
2475 test_cmd_w_to_a, sizeof(test_cmd_w_to_a), NULL, NULL );
2476 switch (str_index)
2478 case 0: /* ASCII string */
2479 if (unicode_server)
2481 ok(size == size_a_to_w, "Wrong size %d/%d, msg_index=%d\n", size, size_a_to_w, msg_index);
2482 ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w),
2483 "Expected %s, msg_index=%d\n", wine_dbgstr_w(test_cmd_a_to_w), msg_index);
2485 else if (unicode_client)
2487 /* ASCII string mapped W->A -> garbage */
2489 else
2491 ok(size == size_a, "Wrong size %d/%d, msg_index=%d\n", size, size_a, msg_index);
2492 ok(!lstrcmpA((CHAR*)buffer, test_cmd_a_to_a), "Expected %s, got %s, msg_index=%d\n",
2493 test_cmd_a_to_a, buffer, msg_index);
2495 break;
2497 case 1: /* Unicode string with only 8-bit chars */
2498 if (unicode_server)
2500 ok(size == size_w, "Wrong size %d/%d, msg_index=%d\n", size, size_w, msg_index);
2501 ok(!lstrcmpW((WCHAR*)buffer, cmd_w),
2502 "Expected %s, msg_index=%d\n", wine_dbgstr_w(cmd_w), msg_index);
2504 else if (unicode_client)
2506 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n", size, size_w_to_a, msg_index);
2507 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2508 test_cmd_w_to_a, buffer, msg_index);
2510 else
2512 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n",
2513 size, size_w_to_a, msg_index);
2514 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2515 test_cmd_w_to_a, buffer, msg_index);
2517 break;
2519 case 2: /* normal Unicode string */
2520 case 3: /* IsTextUnicode false negative */
2521 case 4: /* Chinese chars */
2522 if (unicode_server)
2524 /* double A->W mapping */
2525 /* NT uses the full size, XP+ only until the first null */
2526 DWORD nt_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, size_w, test_cmd_a_to_w,
2527 sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR);
2528 DWORD xp_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, -1, NULL, 0 ) * sizeof(WCHAR);
2529 ok(size == xp_size || broken(size == nt_size) ||
2530 broken(str_index == 4 && IsDBCSLeadByte(cmd_w[0])) /* East Asian */,
2531 "Wrong size %d/%d, msg_index=%d\n", size, size_a_to_w, msg_index);
2532 ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w),
2533 "Expected %s, msg_index=%d\n", wine_dbgstr_w(test_cmd_a_to_w), msg_index);
2535 else if (unicode_client)
2537 ok(size == size_w_to_a, "Wrong size %d/%d, msg_index=%d\n", size, size_w_to_a, msg_index);
2538 ok(!lstrcmpA((CHAR*)buffer, test_cmd_w_to_a), "Expected %s, got %s, msg_index=%d\n",
2539 test_cmd_w_to_a, buffer, msg_index);
2541 else
2543 ok(size == size_w, "Wrong size %d/%d, msg_index=%d\n", size, size_w, msg_index);
2544 ok(!lstrcmpW((WCHAR*)buffer, cmd_w),
2545 "Expected %s, msg_index=%d\n", wine_dbgstr_w(cmd_w), msg_index);
2547 break;
2549 default:
2550 ok( 0, "Invalid message %u\n", msg_index );
2551 break;
2553 return (HDDEDATA) DDE_FACK;
2555 case XTYP_DISCONNECT:
2556 return (HDDEDATA) TRUE;
2558 default:
2559 ok(FALSE, "Unhandled msg: %08x, msg_index=%d\n", uType, msg_index);
2562 return NULL;
2565 static HDDEDATA CALLBACK client_end_to_end_callback(UINT uType, UINT uFmt, HCONV hconv,
2566 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
2567 ULONG_PTR dwData1, ULONG_PTR dwData2)
2569 switch (uType)
2571 case XTYP_DISCONNECT:
2572 return (HDDEDATA) TRUE;
2574 default:
2575 ok(FALSE, "Unhandled msg: %08x\n", uType);
2578 return NULL;
2581 static void test_end_to_end_client(BOOL type_a)
2583 DWORD i, ret, err;
2584 DWORD client_pid = 0;
2585 HSZ server, topic;
2586 HCONV hconv;
2587 HDDEDATA hdata;
2588 static const char test_service[] = "TestDDEService";
2589 static const WCHAR test_service_w[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};
2590 static const char test_topic[] = "TestDDETopic";
2591 static const WCHAR test_topic_w[] = {'T','e','s','t','D','D','E','T','o','p','i','c',0};
2593 trace("Start end to end client %s\n", type_a ? "ASCII" : "UNICODE");
2595 if (type_a)
2596 ret = DdeInitializeA(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0);
2597 else
2598 ret = DdeInitializeW(&client_pid, client_end_to_end_callback, APPCMD_CLIENTONLY, 0);
2599 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret);
2601 if (type_a)
2603 server = DdeCreateStringHandleA(client_pid, test_service, CP_WINANSI);
2604 topic = DdeCreateStringHandleA(client_pid, test_topic, CP_WINANSI);
2606 else {
2607 server = DdeCreateStringHandleW(client_pid, test_service_w, CP_WINUNICODE);
2608 topic = DdeCreateStringHandleW(client_pid, test_topic_w, CP_WINUNICODE);
2611 DdeGetLastError(client_pid);
2612 hconv = DdeConnect(client_pid, server, topic, NULL);
2613 ok(hconv != NULL, "Expected non-NULL conversation\n");
2614 ret = DdeGetLastError(client_pid);
2615 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %x\n", ret);
2616 DdeFreeStringHandle(client_pid, server);
2618 /* Test both A and W data being passed to DdeClientTransaction */
2619 hdata = DdeClientTransaction((LPBYTE)test_cmd_a_to_a, sizeof(test_cmd_a_to_a),
2620 hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
2621 ok(hdata != NULL, "DdeClientTransaction failed\n");
2622 ok(ret == DDE_FACK, "wrong status code %x\n", ret);
2623 err = DdeGetLastError(client_pid);
2624 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
2626 for (i = 0; i < sizeof(test_cmd_w_to_w)/sizeof(test_cmd_w_to_w[0]); i++)
2628 hdata = DdeClientTransaction((LPBYTE)test_cmd_w_to_w[i],
2629 (lstrlenW(test_cmd_w_to_w[i]) + 1) * sizeof(WCHAR),
2630 hconv, (HSZ)0xdead, 0xbeef, XTYP_EXECUTE, 1000, &ret);
2631 ok(hdata != NULL, "DdeClientTransaction failed\n");
2632 ok(ret == DDE_FACK, "wrong status code %x\n", ret);
2633 err = DdeGetLastError(client_pid);
2634 ok(err == DMLERR_NO_ERROR, "wrong dde error %x\n", err);
2637 DdeFreeStringHandle(client_pid, topic);
2638 ret = DdeDisconnect(hconv);
2639 ok(ret == TRUE, "Expected TRUE, got %x\n", ret);
2641 ret = DdeUninitialize(client_pid);
2642 ok(ret == TRUE, "Expected TRUE, got %x\n", ret);
2646 static void test_end_to_end_server(HANDLE hproc, HANDLE hthread, BOOL type_a)
2648 MSG msg;
2649 HSZ server;
2650 BOOL ret;
2651 DWORD res;
2652 HDDEDATA hdata;
2653 static const char test_service[] = "TestDDEService";
2655 trace("start end to end server %s\n", type_a ? "ASCII" : "UNICODE");
2656 server_pid = 0;
2658 if (type_a)
2659 res = DdeInitializeA(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0);
2660 else
2661 res = DdeInitializeW(&server_pid, server_end_to_end_callback, APPCLASS_STANDARD, 0);
2662 ok(res == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", res);
2664 server = DdeCreateStringHandleA(server_pid, test_service, CP_WINANSI);
2665 ok(server != NULL, "Expected non-NULL string handle\n");
2667 hdata = DdeNameService(server_pid, server, 0, DNS_REGISTER);
2668 ok(hdata == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", hdata);
2669 ResumeThread( hthread );
2672 while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
2674 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2677 ret = DdeUninitialize(server_pid);
2678 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
2679 GetExitCodeProcess( hproc, &res );
2680 ok( !res, "client failed with %u error(s)\n", res );
2683 START_TEST(dde)
2685 int argc;
2686 char **argv;
2687 char buffer[MAX_PATH];
2688 STARTUPINFOA startup;
2689 PROCESS_INFORMATION proc;
2690 DWORD dde_inst = 0xdeadbeef;
2692 argc = winetest_get_mainargs(&argv);
2693 if (argc == 3)
2695 if (!lstrcmpA(argv[2], "ddeml"))
2696 test_ddeml_client();
2697 else if (!lstrcmpA(argv[2], "msg"))
2698 test_msg_client();
2699 else if (!lstrcmpA(argv[2], "enda"))
2700 test_end_to_end_client(TRUE);
2701 else if (!lstrcmpA(argv[2], "endw"))
2702 test_end_to_end_client(FALSE);
2704 return;
2707 test_initialisation();
2709 SetLastError(0xdeadbeef);
2710 DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
2711 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2713 win_skip("Skipping tests on win9x because of brokenness\n");
2714 return;
2717 ZeroMemory(&startup, sizeof(STARTUPINFOA));
2718 sprintf(buffer, "%s dde ddeml", argv[0]);
2719 startup.cb = sizeof(startup);
2720 startup.dwFlags = STARTF_USESHOWWINDOW;
2721 startup.wShowWindow = SW_SHOWNORMAL;
2723 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2724 CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2726 test_msg_server(proc.hProcess, proc.hThread);
2728 sprintf(buffer, "%s dde msg", argv[0]);
2729 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2730 0, NULL, NULL, &startup, &proc);
2732 test_ddeml_server(proc.hProcess);
2734 /* Test the combinations of A and W interfaces with A and W data
2735 end to end to ensure that data conversions are accurate */
2736 sprintf(buffer, "%s dde enda", argv[0]);
2737 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2738 CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2740 test_end_to_end_server(proc.hProcess, proc.hThread, TRUE);
2742 /* Don't bother testing W interfaces on Win9x/WinMe */
2743 SetLastError(0xdeadbeef);
2744 lstrcmpW(NULL, NULL);
2745 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2747 win_skip("Skipping W-interface tests\n");
2749 else
2751 sprintf(buffer, "%s dde endw", argv[0]);
2752 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2753 CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2755 test_end_to_end_server(proc.hProcess, proc.hThread, FALSE);
2757 sprintf(buffer, "%s dde enda", argv[0]);
2758 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2759 CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2761 test_end_to_end_server(proc.hProcess, proc.hThread, FALSE);
2763 sprintf(buffer, "%s dde endw", argv[0]);
2764 CreateProcessA(NULL, buffer, NULL, NULL, FALSE,
2765 CREATE_SUSPENDED, NULL, NULL, &startup, &proc);
2767 test_end_to_end_server(proc.hProcess, proc.hThread, TRUE);
2769 test_dde_aw_transaction( FALSE, TRUE );
2770 test_dde_aw_transaction( TRUE, FALSE );
2771 test_dde_aw_transaction( TRUE, TRUE );
2772 test_dde_aw_transaction( FALSE, FALSE );
2774 test_dde_aw_transaction( FALSE, TRUE );
2775 test_dde_aw_transaction( TRUE, FALSE );
2776 test_dde_aw_transaction( TRUE, TRUE );
2778 test_dde_aw_transaction( FALSE, FALSE );
2780 test_DdeCreateDataHandle();
2781 test_DdeCreateStringHandle();
2782 test_FreeDDElParam();
2783 test_PackDDElParam();
2784 test_UnpackDDElParam();