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