1 /*
2 * Unit tests for DDE functions
3 *
4 * Copyright (c) 2004 Dmitry Timoshkov
5 * Copyright (c) 2007 James Hawkins
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "dde.h"
30 #include "ddeml.h"
31 #include "winerror.h"
32
33 #include "wine/test.h"
34
35 static const WCHAR TEST_DDE_SERVICE[] = {'T','e','s','t','D','D','E','S','e','r','v','i','c','e',0};
36
37 static char exec_cmdA[] = "ANSI dde command";
38 static WCHAR exec_cmdW[] = {'u','n','i','c','o','d','e',' ','d','d','e',' ','c','o','m','m','a','n','d',0};
39
40 static WNDPROC old_dde_client_wndproc;
41
42 static const DWORD default_timeout = 200;
43
44 static void flush_events(void)
45 {
46 MSG msg;
47 int diff = default_timeout;
48 int min_timeout = 50;
49 DWORD time = GetTickCount() + diff;
50
51 while (diff > 0)
52 {
53 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
54 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
55 diff = time - GetTickCount();
56 min_timeout = 10;
57 }
58 }
59
60 static void create_dde_window(HWND *hwnd, LPCSTR name, WNDPROC wndproc)
61 {
62 WNDCLASSA wcA;
63
64 memset(&wcA, 0, sizeof(wcA));
65 wcA.lpfnWndProc = wndproc;
66 wcA.lpszClassName = name;
67 wcA.hInstance = GetModuleHandleA(0);
68 assert(RegisterClassA(&wcA));
69
70 *hwnd = CreateWindowExA(0, name, NULL, WS_POPUP,
71 500, 500, CW_USEDEFAULT, CW_USEDEFAULT,
72 GetDesktopWindow(), 0, GetModuleHandleA(0), NULL);
73 assert(*hwnd);
74 }
75
76 static void destroy_dde_window(HWND *hwnd, LPCSTR name)
77 {
78 DestroyWindow(*hwnd);
79 UnregisterClass(name, GetModuleHandleA(0));
80 }
81
82 static LRESULT WINAPI dde_server_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
83 {
84 UINT_PTR lo, hi;
85 char str[MAX_PATH], *ptr;
86 HGLOBAL hglobal;
87 DDEDATA *data;
88 DDEPOKE *poke;
89 DWORD size;
90
91 static int msg_index = 0;
92 static HWND client = 0;
93 static BOOL executed = FALSE;
94
95 if (msg < WM_DDE_FIRST || msg > WM_DDE_LAST)
96 return DefWindowProcA(hwnd, msg, wparam, lparam);
97
98 msg_index++;
99
100 switch (msg)
101 {
102 case WM_DDE_INITIATE:
103 {
104 client = (HWND)wparam;
105 ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
106
107 GlobalGetAtomNameA(LOWORD(lparam), str, MAX_PATH);
108 ok(!lstrcmpA(str, "TestDDEService"), "Expected TestDDEService, got %s\n", str);
109
110 GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
111 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
112
113 SendMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
114
115 break;
116 }
117
118 case WM_DDE_REQUEST:
119 {
120 ok((msg_index >= 2 && msg_index <= 4) ||
121 (msg_index >= 7 && msg_index <= 8),
122 "Expected 2, 3, 4, 7 or 8, got %d\n", msg_index);
123 ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
124 ok(LOWORD(lparam) == CF_TEXT, "Expected CF_TEXT, got %d\n", LOWORD(lparam));
125
126 GlobalGetAtomNameA(HIWORD(lparam), str, MAX_PATH);
127 if (msg_index < 8)
128 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
129 else
130 ok(!lstrcmpA(str, "executed"), "Expected executed, got %s\n", str);
131
132 if (msg_index == 8)
133 {
134 if (executed)
135 lstrcpyA(str, "command executed\r\n");
136 else
137 lstrcpyA(str, "command not executed\r\n");
138 }
139 else
140 lstrcpyA(str, "requested data\r\n");
141
142 size = sizeof(DDEDATA) + lstrlenA(str) + 1;
143 hglobal = GlobalAlloc(GMEM_MOVEABLE, size);
144 ok(hglobal != NULL, "Expected non-NULL hglobal\n");
145
146 data = GlobalLock(hglobal);
147 ZeroMemory(data, size);
148
149 /* setting fResponse to FALSE at this point destroys
150 * the internal messaging state of native dde
151 */
152 data->fResponse = TRUE;
153
154 if (msg_index == 2)
155 data->fRelease = TRUE;
156 else if (msg_index == 3)
157 data->fAckReq = TRUE;
158
159 data->cfFormat = CF_TEXT;
160 lstrcpyA((LPSTR)data->Value, str);
161 GlobalUnlock(hglobal);
162
163 lparam = PackDDElParam(WM_DDE_ACK, (UINT)hglobal, HIWORD(lparam));
164 PostMessageA(client, WM_DDE_DATA, (WPARAM)hwnd, lparam);
165
166 break;
167 }
168
169 case WM_DDE_POKE:
170 {
171 ok(msg_index == 5 || msg_index == 6, "Expected 5 or 6, got %d\n", msg_index);
172 ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
173
174 UnpackDDElParam(WM_DDE_POKE, lparam, &lo, &hi);
175
176 GlobalGetAtomNameA(hi, str, MAX_PATH);
177 ok(!lstrcmpA(str, "poker"), "Expected poker, got %s\n", str);
178
179 poke = GlobalLock((HGLOBAL)lo);
180 ok(poke != NULL, "Expected non-NULL poke\n");
181 ok(poke->fReserved == 0, "Expected 0, got %d\n", poke->fReserved);
182 ok(poke->unused == 0, "Expected 0, got %d\n", poke->unused);
183 ok(poke->fRelease == TRUE, "Expected TRUE, got %d\n", poke->fRelease);
184 ok(poke->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", poke->cfFormat);
185
186 if (msg_index == 5)
187 {
188 size = GlobalSize((HGLOBAL)lo);
189 ok(size == 4, "got %d\n", size);
190 }
191 else
192 ok(!lstrcmpA((LPSTR)poke->Value, "poke data\r\n"),
193 "Expected 'poke data\\r\\n', got %s\n", poke->Value);
194
195 GlobalUnlock((HGLOBAL)lo);
196
197 lparam = PackDDElParam(WM_DDE_ACK, DDE_FACK, hi);
198 PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
199
200 break;
201 }
202
203 case WM_DDE_EXECUTE:
204 {
205 ok(msg_index == 7, "Expected 7, got %d\n", msg_index);
206 ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
207
208 ptr = GlobalLock((HGLOBAL)lparam);
209 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected [Command(Var)], got %s\n", ptr);
210 GlobalUnlock((HGLOBAL)lparam);
211
212 executed = TRUE;
213
214 lparam = ReuseDDElParam(lparam, WM_DDE_EXECUTE, WM_DDE_ACK, DDE_FACK, HIWORD(lparam));
215 PostMessageA(client, WM_DDE_ACK, (WPARAM)hwnd, lparam);
216
217 break;
218 }
219
220 case WM_DDE_TERMINATE:
221 {
222 ok(msg_index == 9, "Expected 9, got %d\n", msg_index);
223 ok(wparam == (WPARAM)client, "Expected client hwnd, got %08lx\n", wparam);
224 ok(lparam == 0, "Expected 0, got %08lx\n", lparam);
225
226 PostMessageA(client, WM_DDE_TERMINATE, (WPARAM)hwnd, 0);
227
228 break;
229 }
230
231 default:
232 ok(FALSE, "Unhandled msg: %08x\n", msg);
233 }
234
235 return DefWindowProcA(hwnd, msg, wparam, lparam);
236 }
237
238 static void test_msg_server(HANDLE hproc, HANDLE hthread)
239 {
240 MSG msg;
241 HWND hwnd;
242 DWORD res;
243
244 create_dde_window(&hwnd, "dde_server", dde_server_wndproc);
245 ResumeThread( hthread );
246
247 while (MsgWaitForMultipleObjects( 1, &hproc, FALSE, INFINITE, QS_ALLINPUT ) != 0)
248 {
249 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
250 }
251
252 destroy_dde_window(&hwnd, "dde_server");
253 GetExitCodeProcess( hproc, &res );
254 ok( !res, "client failed with %u error(s)\n", res );
255 }
256
257 static HDDEDATA CALLBACK client_ddeml_callback(UINT uType, UINT uFmt, HCONV hconv,
258 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
259 ULONG_PTR dwData1, ULONG_PTR dwData2)
260 {
261 ok(FALSE, "Unhandled msg: %08x\n", uType);
262 return 0;
263 }
264
265 static void test_ddeml_client(void)
266 {
267 UINT ret;
268 char buffer[32];
269 LPSTR str;
270 DWORD size, res;
271 HDDEDATA hdata, op;
272 HSZ server, topic, item;
273 DWORD client_pid;
274 HCONV conversation;
275
276 client_pid = 0;
277 ret = DdeInitializeA(&client_pid, client_ddeml_callback, APPCMD_CLIENTONLY, 0);
278 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
279
280 /* FIXME: make these atoms global and check them in the server */
281
282 server = DdeCreateStringHandleA(client_pid, "TestDDEService", CP_WINANSI);
283 topic = DdeCreateStringHandleA(client_pid, "TestDDETopic", CP_WINANSI);
284
285 DdeGetLastError(client_pid);
286 conversation = DdeConnect(client_pid, server, topic, NULL);
287 ok(conversation != NULL, "Expected non-NULL conversation\n");
288 ret = DdeGetLastError(client_pid);
289 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
290
291 DdeFreeStringHandle(client_pid, server);
292
293 item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI);
294
295 /* XTYP_REQUEST, fRelease = TRUE */
296 res = 0xdeadbeef;
297 DdeGetLastError(client_pid);
298 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
299 ret = DdeGetLastError(client_pid);
300 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
301 ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %08x\n", res);
302 if (hdata == NULL)
303 ok(FALSE, "hdata is NULL\n");
304 else
305 {
306 str = (LPSTR)DdeAccessData(hdata, &size);
307 ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
308 ok(size == 19, "Expected 19, got %d\n", size);
309
310 ret = DdeUnaccessData(hdata);
311 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
312 }
313
314 /* XTYP_REQUEST, fAckReq = TRUE */
315 res = 0xdeadbeef;
316 DdeGetLastError(client_pid);
317 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
318 ret = DdeGetLastError(client_pid);
319 ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res);
320 todo_wine
321 ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
322 if (hdata == NULL)
323 ok(FALSE, "hdata is NULL\n");
324 else
325 {
326 str = (LPSTR)DdeAccessData(hdata, &size);
327 ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
328 ok(size == 19, "Expected 19, got %d\n", size);
329
330 ret = DdeUnaccessData(hdata);
331 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
332 }
333
334 /* XTYP_REQUEST, all params normal */
335 res = 0xdeadbeef;
336 DdeGetLastError(client_pid);
337 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
338 ret = DdeGetLastError(client_pid);
339 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
340 ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res);
341 if (hdata == NULL)
342 ok(FALSE, "hdata is NULL\n");
343 else
344 {
345 str = (LPSTR)DdeAccessData(hdata, &size);
346 ok(!lstrcmpA(str, "requested data\r\n"), "Expected 'requested data\\r\\n', got %s\n", str);
347 ok(size == 19, "Expected 19, got %d\n", size);
348
349 ret = DdeUnaccessData(hdata);
350 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
351 }
352
353 /* XTYP_REQUEST, no item */
354 res = 0xdeadbeef;
355 DdeGetLastError(client_pid);
356 hdata = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
357 ret = DdeGetLastError(client_pid);
358 ok(hdata == NULL, "Expected NULL hdata, got %p\n", hdata);
359 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %08x\n", res);
360 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
361
362 DdeFreeStringHandle(client_pid, item);
363
364 item = DdeCreateStringHandleA(client_pid, "poker", CP_WINANSI);
365
366 lstrcpyA(buffer, "poke data\r\n");
367 hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
368 0, item, CF_TEXT, 0);
369 ok(hdata != NULL, "Expected non-NULL hdata\n");
370
371 /* XTYP_POKE, no item */
372 res = 0xdeadbeef;
373 DdeGetLastError(client_pid);
374 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
375 ret = DdeGetLastError(client_pid);
376 ok(op == NULL, "Expected NULL, got %p\n", op);
377 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
378 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
379
380 /* XTYP_POKE, no data */
381 res = 0xdeadbeef;
382 DdeGetLastError(client_pid);
383 op = DdeClientTransaction(NULL, 0, conversation, 0, CF_TEXT, XTYP_POKE, default_timeout, &res);
384 ret = DdeGetLastError(client_pid);
385 ok(op == NULL, "Expected NULL, got %p\n", op);
386 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
387 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
388
389 /* XTYP_POKE, wrong size */
390 res = 0xdeadbeef;
391 DdeGetLastError(client_pid);
392 op = DdeClientTransaction((LPBYTE)hdata, 0, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
393 ret = DdeGetLastError(client_pid);
394 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
395 ok(res == DDE_FACK, "Expected DDE_FACK, got %d\n", res);
396 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
397
398 /* XTYP_POKE, correct params */
399 res = 0xdeadbeef;
400 DdeGetLastError(client_pid);
401 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, item, CF_TEXT, XTYP_POKE, default_timeout, &res);
402 ret = DdeGetLastError(client_pid);
403 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
404 ok(res == DDE_FACK, "Expected DDE_FACK, got %d\n", res);
405 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
406
407 DdeFreeDataHandle(hdata);
408
409 lstrcpyA(buffer, "[Command(Var)]");
410 hdata = DdeCreateDataHandle(client_pid, (LPBYTE)buffer, lstrlenA(buffer) + 1,
411 0, NULL, CF_TEXT, 0);
412 ok(hdata != NULL, "Expected non-NULL hdata\n");
413
414 /* XTYP_EXECUTE, correct params */
415 res = 0xdeadbeef;
416 DdeGetLastError(client_pid);
417 op = DdeClientTransaction((LPBYTE)hdata, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
418 ret = DdeGetLastError(client_pid);
419 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
420 ok(op == (HDDEDATA)TRUE, "Expected TRUE, got %p\n", op);
421 ok(res == DDE_FACK, "Expected DDE_FACK, got %d\n", res);
422
423 /* XTYP_EXECUTE, no data */
424 res = 0xdeadbeef;
425 DdeGetLastError(client_pid);
426 op = DdeClientTransaction(NULL, 0, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
427 ret = DdeGetLastError(client_pid);
428 ok(op == NULL, "Expected NULL, got %p\n", op);
429 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
430 todo_wine
431 {
432 ok(ret == DMLERR_MEMORY_ERROR, "Expected DMLERR_MEMORY_ERROR, got %d\n", ret);
433 }
434
435 /* XTYP_EXECUTE, no data, -1 size */
436 res = 0xdeadbeef;
437 DdeGetLastError(client_pid);
438 op = DdeClientTransaction(NULL, -1, conversation, NULL, 0, XTYP_EXECUTE, default_timeout, &res);
439 ret = DdeGetLastError(client_pid);
440 ok(op == NULL, "Expected NULL, got %p\n", op);
441 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
442 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
443
444 DdeFreeStringHandle(client_pid, topic);
445 DdeFreeDataHandle(hdata);
446
447 item = DdeCreateStringHandleA(client_pid, "executed", CP_WINANSI);
448
449 /* verify the execute */
450 res = 0xdeadbeef;
451 DdeGetLastError(client_pid);
452 hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res);
453 ret = DdeGetLastError(client_pid);
454 ok(ret == DMLERR_NO_ERROR, "Expected DMLERR_NO_ERROR, got %d\n", ret);
455 ok(res == DDE_FNOTPROCESSED, "Expected DDE_FNOTPROCESSED, got %d\n", res);
456 if (hdata == NULL)
457 ok(FALSE, "hdata is NULL\n");
458 else
459 {
460 str = (LPSTR)DdeAccessData(hdata, &size);
461 ok(!lstrcmpA(str, "command executed\r\n"), "Expected 'command executed\\r\\n', got %s\n", str);
462 ok(size == 21, "Expected 21, got %d\n", size);
463
464 ret = DdeUnaccessData(hdata);
465 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
466 }
467
468 /* invalid transactions */
469 res = 0xdeadbeef;
470 DdeGetLastError(client_pid);
471 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ADVREQ, default_timeout, &res);
472 ret = DdeGetLastError(client_pid);
473 ok(op == NULL, "Expected NULL, got %p\n", op);
474 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
475 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
476
477 res = 0xdeadbeef;
478 DdeGetLastError(client_pid);
479 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT, default_timeout, &res);
480 ret = DdeGetLastError(client_pid);
481 ok(op == NULL, "Expected NULL, got %p\n", op);
482 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
483 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
484
485 res = 0xdeadbeef;
486 DdeGetLastError(client_pid);
487 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_CONNECT_CONFIRM, default_timeout, &res);
488 ret = DdeGetLastError(client_pid);
489 ok(op == NULL, "Expected NULL, got %p\n", op);
490 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
491 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
492
493 res = 0xdeadbeef;
494 DdeGetLastError(client_pid);
495 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_DISCONNECT, default_timeout, &res);
496 ret = DdeGetLastError(client_pid);
497 ok(op == NULL, "Expected NULL, got %p\n", op);
498 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
499 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
500
501 res = 0xdeadbeef;
502 DdeGetLastError(client_pid);
503 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_ERROR, default_timeout, &res);
504 ret = DdeGetLastError(client_pid);
505 ok(op == NULL, "Expected NULL, got %p\n", op);
506 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
507 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
508
509 res = 0xdeadbeef;
510 DdeGetLastError(client_pid);
511 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_MONITOR, default_timeout, &res);
512 ret = DdeGetLastError(client_pid);
513 ok(op == NULL, "Expected NULL, got %p\n", op);
514 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
515 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
516
517 res = 0xdeadbeef;
518 DdeGetLastError(client_pid);
519 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REGISTER, default_timeout, &res);
520 ret = DdeGetLastError(client_pid);
521 ok(op == NULL, "Expected NULL, got %p\n", op);
522 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
523 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
524
525 res = 0xdeadbeef;
526 DdeGetLastError(client_pid);
527 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_UNREGISTER, default_timeout, &res);
528 ret = DdeGetLastError(client_pid);
529 ok(op == NULL, "Expected NULL, got %p\n", op);
530 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
531 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
532
533 res = 0xdeadbeef;
534 DdeGetLastError(client_pid);
535 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_WILDCONNECT, default_timeout, &res);
536 ret = DdeGetLastError(client_pid);
537 ok(op == NULL, "Expected NULL, got %p\n", op);
538 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
539 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
540
541 res = 0xdeadbeef;
542 DdeGetLastError(client_pid);
543 op = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_XACT_COMPLETE, default_timeout, &res);
544 ret = DdeGetLastError(client_pid);
545 ok(op == NULL, "Expected NULL, got %p\n", op);
546 ok(res == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", res);
547 ok(ret == DMLERR_INVALIDPARAMETER, "Expected DMLERR_INVALIDPARAMETER, got %d\n", ret);
548
549 DdeFreeStringHandle(client_pid, item);
550
551 ret = DdeDisconnect(conversation);
552 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
553
554 ret = DdeUninitialize(client_pid);
555 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
556 }
557
558 static DWORD server_pid;
559
560 static HDDEDATA CALLBACK server_ddeml_callback(UINT uType, UINT uFmt, HCONV hconv,
561 HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
562 ULONG_PTR dwData1, ULONG_PTR dwData2)
563 {
564 char str[MAX_PATH], *ptr;
565 HDDEDATA ret;
566 DWORD size;
567
568 static int msg_index = 0;
569 static HCONV conversation = 0;
570
571 msg_index++;
572
573 switch (uType)
574 {
575 case XTYP_REGISTER:
576 {
577 ok(msg_index == 1, "Expected 1, got %d\n", msg_index);
578 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
579 ok(hconv == 0, "Expected 0, got %p\n", hconv);
580 ok(hdata == 0, "Expected 0, got %p\n", hdata);
581 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
582 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
583
584 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
585 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
586 ok(size == 13, "Expected 13, got %d\n", size);
587
588 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
589 ok(!strncmp(str, "TestDDEServer(", 14), "Expected TestDDEServer(, got %s\n", str);
590 ok(str[size - 1] == ')', "Expected ')', got %c\n", str[size - 1]);
591 ok(size == 25, "Expected 25, got %d\n", size);
592
593 return (HDDEDATA)TRUE;
594 }
595
596 case XTYP_CONNECT:
597 {
598 ok(msg_index == 2, "Expected 2, 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 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
604
605 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
606 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
607 ok(size == 12, "Expected 12, got %d\n", size);
608
609 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
610 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
611 ok(size == 13, "Expected 13, got %d\n", size);
612
613 return (HDDEDATA)TRUE;
614 }
615
616 case XTYP_CONNECT_CONFIRM:
617 {
618 conversation = hconv;
619
620 ok(msg_index == 3, "Expected 3, got %d\n", msg_index);
621 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
622 ok(hconv != NULL, "Expected non-NULL hconv\n");
623 ok(hdata == 0, "Expected 0, got %p\n", hdata);
624 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
625 ok(dwData2 == FALSE, "Expected FALSE, got %08lx\n", dwData2);
626
627 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
628 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
629 ok(size == 12, "Expected 12, got %d\n", size);
630
631 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
632 ok(!lstrcmpA(str, "TestDDEServer"), "Expected TestDDEServer, got %s\n", str);
633 ok(size == 13, "Expected 13, got %d\n", size);
634
635 return (HDDEDATA)TRUE;
636 }
637
638 case XTYP_REQUEST:
639 {
640 ok(msg_index == 4 || msg_index == 5 || msg_index == 6,
641 "Expected 4, 5 or 6, got %d\n", msg_index);
642 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
643 ok(hdata == 0, "Expected 0, got %p\n", hdata);
644 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
645 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
646
647 if (msg_index == 4)
648 ok(uFmt == 0xbeef, "Expected 0xbeef, got %08x\n", uFmt);
649 else
650 ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %08x\n", uFmt);
651
652 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
653 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
654 ok(size == 12, "Expected 12, got %d\n", size);
655
656 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
657
658 if (msg_index == 5)
659 {
660 {
661 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
662 ok(size == 1, "Expected 1, got %d\n", size);
663 }
664 }
665 else if (msg_index == 6)
666 {
667 ok(!lstrcmpA(str, "request"), "Expected request, got %s\n", str);
668 ok(size == 7, "Expected 7, got %d\n", size);
669 }
670
671 if (msg_index == 6)
672 {
673 lstrcpyA(str, "requested data\r\n");
674 return DdeCreateDataHandle(server_pid, (LPBYTE)str, lstrlenA(str) + 1,
675 0, hsz2, CF_TEXT, 0);
676 }
677
678 return NULL;
679 }
680
681 case XTYP_POKE:
682 {
683 ok(msg_index == 7 || msg_index == 8, "Expected 7 or 8, got %d\n", msg_index);
684 ok(uFmt == CF_TEXT, "Expected CF_TEXT, got %d\n", uFmt);
685 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
686 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
687 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
688
689 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
690 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
691 ok(size == 12, "Expected 12, got %d\n", size);
692
693 ptr = (LPSTR)DdeAccessData(hdata, &size);
694 ok(!lstrcmpA(ptr, "poke data\r\n"), "Expected 'poke data\\r\\n', got %s\n", ptr);
695 ok(size == 12, "Expected 12, got %d\n", size);
696 DdeUnaccessData(hdata);
697
698 size = DdeQueryStringA(server_pid, hsz2, str, MAX_PATH, CP_WINANSI);
699 if (msg_index == 7)
700 {
701 {
702 ok(!lstrcmpA(str, ""), "Expected empty string, got %s\n", str);
703 ok(size == 1, "Expected 1, got %d\n", size);
704 }
705 }
706 else
707 {
708 ok(!lstrcmpA(str, "poke"), "Expected poke, got %s\n", str);
709 ok(size == 4, "Expected 4, got %d\n", size);
710 }
711
712 return (HDDEDATA)DDE_FACK;
713 }
714
715 case XTYP_EXECUTE:
716 {
717 ok(msg_index == 9 || msg_index == 10, "Expected 9 or 10, got %d\n", msg_index);
718 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
719 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
720 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
721 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
722 ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
723
724 size = DdeQueryStringA(server_pid, hsz1, str, MAX_PATH, CP_WINANSI);
725 ok(!lstrcmpA(str, "TestDDETopic"), "Expected TestDDETopic, got %s\n", str);
726 ok(size == 12, "Expected 12, got %d\n", size);
727
728 ptr = (LPSTR)DdeAccessData(hdata, &size);
729
730 if (msg_index == 9)
731 {
732 ok(!lstrcmpA(ptr, "[Command(Var)]"), "Expected '[Command(Var)]', got %s\n", ptr);
733 ok(size == 15, "Expected 15, got %d\n", size);
734 ret = (HDDEDATA)DDE_FACK;
735 }
736 else
737 {
738 ok(!lstrcmpA(ptr, "[BadCommand(Var)]"), "Expected '[BadCommand(Var)]', got %s\n", ptr);
739 ok(size == 18, "Expected 18, got %d\n", size);
740 ret = (HDDEDATA)DDE_FNOTPROCESSED;
741 }
742
743 DdeUnaccessData(hdata);
744
745 return ret;
746 }
747
748 case XTYP_DISCONNECT:
749 {
750 ok(msg_index == 11, "Expected 11, got %d\n", msg_index);
751 ok(uFmt == 0, "Expected 0, got %d\n", uFmt);
752 ok(hconv == conversation, "Expected conversation handle, got %p\n", hconv);
753 ok(dwData1 == 0, "Expected 0, got %08lx\n", dwData1);
754 ok(dwData2 == 0, "Expected 0, got %08lx\n", dwData2);
755 ok(hsz1 == 0, "Expected 0, got %p\n", hsz2);
756 ok(hsz2 == 0, "Expected 0, got %p\n", hsz2);
757
758 return 0;
759 }
760