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