1 /* Unit test suite for SHLWAPI ordinal functions 2 * 3 * Copyright 2004 Jon Griffiths 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include <stdio.h> 21 22 #define COBJMACROS 23 #define CONST_VTABLE 24 #include "wine/test.h" 25 #include "winbase.h" 26 #include "winerror.h" 27 #include "winuser.h" 28 #include "ole2.h" 29 #include "oaidl.h" 30 #include "ocidl.h" 31 #include "mlang.h" 32 #include "shlwapi.h" 33 #include "docobj.h" 34 #include "shobjidl.h" 35 #include "shlobj.h" 36 #ifdef __REACTOS__ 37 #include <shlwapi_undoc.h> 38 #endif 39 40 /* Function ptrs for ordinal calls */ 41 static HMODULE hShlwapi; 42 43 static int (WINAPI *pSHSearchMapInt)(const int*,const int*,int,int); 44 static HRESULT (WINAPI *pGetAcceptLanguagesA)(LPSTR,LPDWORD); 45 46 static HANDLE (WINAPI *pSHAllocShared)(LPCVOID,DWORD,DWORD); 47 static LPVOID (WINAPI *pSHLockShared)(HANDLE,DWORD); 48 static BOOL (WINAPI *pSHUnlockShared)(LPVOID); 49 static BOOL (WINAPI *pSHFreeShared)(HANDLE,DWORD); 50 static HANDLE (WINAPI *pSHMapHandle)(HANDLE,DWORD,DWORD,DWORD,DWORD); 51 static HRESULT(WINAPIV *pSHPackDispParams)(DISPPARAMS*,VARIANTARG*,UINT,...); 52 static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,DISPPARAMS*); 53 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD); 54 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **); 55 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG); 56 static LONG (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT); 57 static INT (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT); 58 static INT (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT); 59 static DWORD (WINAPI *pSHGetObjectCompatFlags)(IUnknown*, const CLSID*); 60 static BOOL (WINAPI *pGUIDFromStringA)(LPSTR, CLSID *); 61 static HRESULT (WINAPI *pIUnknown_QueryServiceExec)(IUnknown*, REFIID, const GUID*, DWORD, DWORD, VARIANT*, VARIANT*); 62 static HRESULT (WINAPI *pIUnknown_ProfferService)(IUnknown*, REFGUID, IServiceProvider*, DWORD*); 63 static HWND (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU, LONG_PTR); 64 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**); 65 static DWORD (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR); 66 static BOOL (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR); 67 static HKEY (WINAPI *pSHGetShellKey)(DWORD, LPCWSTR, BOOL); 68 static HRESULT (WINAPI *pSKGetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void*, DWORD*); 69 static HRESULT (WINAPI *pSKSetValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD, void*, DWORD); 70 static HRESULT (WINAPI *pSKDeleteValueW)(DWORD, LPCWSTR, LPCWSTR); 71 static HRESULT (WINAPI *pSKAllocValueW)(DWORD, LPCWSTR, LPCWSTR, DWORD*, void**, DWORD*); 72 static HWND (WINAPI *pSHSetParentHwnd)(HWND, HWND); 73 static HRESULT (WINAPI *pIUnknown_GetClassID)(IUnknown*, CLSID*); 74 static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO2*); 75 76 typedef struct SHELL_USER_SID { 77 SID_IDENTIFIER_AUTHORITY sidAuthority; 78 DWORD dwUserGroupID; 79 DWORD dwUserID; 80 } SHELL_USER_SID, *PSHELL_USER_SID; 81 typedef struct SHELL_USER_PERMISSION { 82 83 SHELL_USER_SID susID; 84 DWORD dwAccessType; 85 BOOL fInherit; 86 DWORD dwAccessMask; 87 DWORD dwInheritMask; 88 DWORD dwInheritAccessMask; 89 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION; 90 91 static SECURITY_DESCRIPTOR* (WINAPI *pGetShellSecurityDescriptor)(const SHELL_USER_PERMISSION**,int); 92 93 static const CHAR ie_international[] = { 94 'S','o','f','t','w','a','r','e','\\', 95 'M','i','c','r','o','s','o','f','t','\\', 96 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\', 97 'I','n','t','e','r','n','a','t','i','o','n','a','l',0}; 98 static const CHAR acceptlanguage[] = { 99 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0}; 100 101 static int strcmp_wa(LPCWSTR strw, const char *stra) 102 { 103 CHAR buf[512]; 104 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); 105 return lstrcmpA(stra, buf); 106 } 107 108 typedef struct { 109 int id; 110 const void *args[5]; 111 } call_entry_t; 112 113 typedef struct { 114 call_entry_t *calls; 115 int count; 116 int alloc; 117 } call_trace_t; 118 119 static void init_call_trace(call_trace_t *ctrace) 120 { 121 ctrace->alloc = 10; 122 ctrace->count = 0; 123 ctrace->calls = HeapAlloc(GetProcessHeap(), 0, sizeof(call_entry_t) * ctrace->alloc); 124 } 125 126 static void free_call_trace(const call_trace_t *ctrace) 127 { 128 HeapFree(GetProcessHeap(), 0, ctrace->calls); 129 } 130 131 static void add_call(call_trace_t *ctrace, int id, const void *arg0, 132 const void *arg1, const void *arg2, const void *arg3, const void *arg4) 133 { 134 call_entry_t call; 135 136 call.id = id; 137 call.args[0] = arg0; 138 call.args[1] = arg1; 139 call.args[2] = arg2; 140 call.args[3] = arg3; 141 call.args[4] = arg4; 142 143 if (ctrace->count == ctrace->alloc) 144 { 145 ctrace->alloc *= 2; 146 ctrace->calls = HeapReAlloc(GetProcessHeap(),0, ctrace->calls, ctrace->alloc*sizeof(call_entry_t)); 147 } 148 149 ctrace->calls[ctrace->count++] = call; 150 } 151 152 static void ok_trace_(call_trace_t *texpected, call_trace_t *tgot, int line) 153 { 154 if (texpected->count == tgot->count) 155 { 156 INT i; 157 /* compare */ 158 for (i = 0; i < texpected->count; i++) 159 { 160 call_entry_t *expected = &texpected->calls[i]; 161 call_entry_t *got = &tgot->calls[i]; 162 INT j; 163 164 ok_(__FILE__, line)(expected->id == got->id, "got different ids %d: %d, %d\n", i+1, expected->id, got->id); 165 166 for (j = 0; j < 5; j++) 167 { 168 ok_(__FILE__, line)(expected->args[j] == got->args[j], "got different args[%d] for %d: %p, %p\n", j, i+1, 169 expected->args[j], got->args[j]); 170 } 171 } 172 } 173 else 174 ok_(__FILE__, line)(0, "traces length mismatch\n"); 175 } 176 177 #define ok_trace(a, b) ok_trace_(a, b, __LINE__) 178 179 /* trace of actually made calls */ 180 static call_trace_t trace_got; 181 182 static void test_GetAcceptLanguagesA(void) 183 { 184 static LPCSTR table[] = {"de,en-gb;q=0.7,en;q=0.3", 185 "de,en;q=0.3,en-gb;q=0.7", /* sorting is ignored */ 186 "winetest", /* content is ignored */ 187 "de-de,de;q=0.5", 188 "de", 189 NULL}; 190 191 DWORD exactsize; 192 char original[512]; 193 char language[32]; 194 char buffer[64]; 195 HKEY hroot = NULL; 196 LONG res_query = ERROR_SUCCESS; 197 LONG lres; 198 HRESULT hr; 199 DWORD maxlen = sizeof(buffer) - 2; 200 DWORD len; 201 LCID lcid; 202 LPCSTR entry; 203 INT i = 0; 204 205 lcid = GetUserDefaultLCID(); 206 207 /* Get the original Value */ 208 lres = RegOpenKeyA(HKEY_CURRENT_USER, ie_international, &hroot); 209 if (lres) { 210 skip("RegOpenKey(%s) failed: %d\n", ie_international, lres); 211 return; 212 } 213 len = sizeof(original); 214 original[0] = 0; 215 res_query = RegQueryValueExA(hroot, acceptlanguage, 0, NULL, (PBYTE)original, &len); 216 217 RegDeleteValueA(hroot, acceptlanguage); 218 219 /* Some windows versions use "lang-COUNTRY" as default */ 220 memset(language, 0, sizeof(language)); 221 len = GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, language, sizeof(language)); 222 223 if (len) { 224 lstrcatA(language, "-"); 225 memset(buffer, 0, sizeof(buffer)); 226 len = GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, buffer, sizeof(buffer) - len - 1); 227 lstrcatA(language, buffer); 228 } 229 else 230 { 231 /* LOCALE_SNAME has additional parts in some languages. Try only as last chance */ 232 memset(language, 0, sizeof(language)); 233 len = GetLocaleInfoA(lcid, LOCALE_SNAME, language, sizeof(language)); 234 } 235 236 /* get the default value */ 237 len = maxlen; 238 memset(buffer, '#', maxlen); 239 buffer[maxlen] = 0; 240 hr = pGetAcceptLanguagesA( buffer, &len); 241 242 if (hr != S_OK) { 243 win_skip("GetAcceptLanguagesA failed with 0x%x\n", hr); 244 goto restore_original; 245 } 246 247 if (lstrcmpA(buffer, language)) { 248 /* some windows versions use "lang" or "lang-country" as default */ 249 language[0] = 0; 250 hr = LcidToRfc1766A(lcid, language, sizeof(language)); 251 ok(hr == S_OK, "LcidToRfc1766A returned 0x%x and %s\n", hr, language); 252 } 253 254 ok(!lstrcmpA(buffer, language), 255 "have '%s' (searching for '%s')\n", language, buffer); 256 257 if (lstrcmpA(buffer, language)) { 258 win_skip("no more ideas, how to build the default language '%s'\n", buffer); 259 goto restore_original; 260 } 261 262 trace("detected default: %s\n", language); 263 while ((entry = table[i])) { 264 265 exactsize = lstrlenA(entry); 266 267 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) entry, exactsize + 1); 268 ok(!lres, "got %d for RegSetValueExA: %s\n", lres, entry); 269 270 /* len includes space for the terminating 0 before vista/w2k8 */ 271 len = exactsize + 2; 272 memset(buffer, '#', maxlen); 273 buffer[maxlen] = 0; 274 hr = pGetAcceptLanguagesA( buffer, &len); 275 ok(((hr == E_INVALIDARG) && (len == 0)) || 276 (SUCCEEDED(hr) && 277 ((len == exactsize) || (len == exactsize+1)) && 278 !lstrcmpA(buffer, entry)), 279 "+2_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 280 281 len = exactsize + 1; 282 memset(buffer, '#', maxlen); 283 buffer[maxlen] = 0; 284 hr = pGetAcceptLanguagesA( buffer, &len); 285 ok(((hr == E_INVALIDARG) && (len == 0)) || 286 (SUCCEEDED(hr) && 287 ((len == exactsize) || (len == exactsize+1)) && 288 !lstrcmpA(buffer, entry)), 289 "+1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 290 291 len = exactsize; 292 memset(buffer, '#', maxlen); 293 buffer[maxlen] = 0; 294 hr = pGetAcceptLanguagesA( buffer, &len); 295 296 /* There is no space for the string in the registry. 297 When the buffer is large enough, the default language is returned 298 299 When the buffer is too small for that fallback, win7_32 and w2k8_64 300 fail with E_NOT_SUFFICIENT_BUFFER, win8 fails with HRESULT_FROM_WIN32(ERROR_MORE_DATA), 301 other versions succeed and return a partial result while older os succeed 302 and overflow the buffer */ 303 304 ok(((hr == E_INVALIDARG) && (len == 0)) || 305 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) || 306 ((hr == S_OK) && !memcmp(buffer, language, len)) || 307 ((hr == E_NOT_SUFFICIENT_BUFFER) && !len) || 308 ((hr == __HRESULT_FROM_WIN32(ERROR_MORE_DATA)) && len == exactsize)), 309 "==_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 310 311 if (exactsize > 1) { 312 len = exactsize - 1; 313 memset(buffer, '#', maxlen); 314 buffer[maxlen] = 0; 315 hr = pGetAcceptLanguagesA( buffer, &len); 316 ok(((hr == E_INVALIDARG) && (len == 0)) || 317 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) || 318 ((hr == S_OK) && !memcmp(buffer, language, len)) || 319 ((hr == E_NOT_SUFFICIENT_BUFFER) && !len) || 320 ((hr == __HRESULT_FROM_WIN32(ERROR_MORE_DATA)) && len == exactsize - 1)), 321 "-1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 322 } 323 324 len = 1; 325 memset(buffer, '#', maxlen); 326 buffer[maxlen] = 0; 327 hr = pGetAcceptLanguagesA( buffer, &len); 328 ok(((hr == E_INVALIDARG) && (len == 0)) || 329 (((hr == S_OK) && !lstrcmpA(buffer, language) && (len == lstrlenA(language))) || 330 ((hr == S_OK) && !memcmp(buffer, language, len)) || 331 ((hr == E_NOT_SUFFICIENT_BUFFER) && !len) || 332 ((hr == __HRESULT_FROM_WIN32(ERROR_MORE_DATA)) && len == 1)), 333 "=1_#%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 334 335 len = maxlen; 336 hr = pGetAcceptLanguagesA( NULL, &len); 337 338 /* w2k3 and below: E_FAIL and untouched len, 339 since w2k8: S_OK and needed size (excluding 0), win8 S_OK and size including 0. */ 340 ok( ((hr == S_OK) && ((len == exactsize) || (len == exactsize + 1))) || 341 ((hr == E_FAIL) && (len == maxlen)), 342 "NULL,max #%d: got 0x%x with %d and %s\n", i, hr, len, buffer); 343 344 i++; 345 } 346 347 /* without a value in the registry, a default language is returned */ 348 RegDeleteValueA(hroot, acceptlanguage); 349 350 len = maxlen; 351 memset(buffer, '#', maxlen); 352 buffer[maxlen] = 0; 353 hr = pGetAcceptLanguagesA( buffer, &len); 354 ok( ((hr == S_OK) && (len == lstrlenA(language))), 355 "max: got 0x%x with %d and %s (expected S_OK with %d and '%s'\n", 356 hr, len, buffer, lstrlenA(language), language); 357 358 len = 2; 359 memset(buffer, '#', maxlen); 360 buffer[maxlen] = 0; 361 hr = pGetAcceptLanguagesA( buffer, &len); 362 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) || 363 ((hr == E_NOT_SUFFICIENT_BUFFER) && !len) || 364 ((hr == __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY)) && !len), 365 "=2: got 0x%x with %d and %s\n", hr, len, buffer); 366 367 len = 1; 368 memset(buffer, '#', maxlen); 369 buffer[maxlen] = 0; 370 hr = pGetAcceptLanguagesA( buffer, &len); 371 /* When the buffer is too small, win7_32 and w2k8_64 and above fail with 372 E_NOT_SUFFICIENT_BUFFER, win8 ERROR_CANNOT_COPY, 373 other versions succeed and return a partial 0 terminated result while other versions 374 fail with E_INVALIDARG and return a partial unterminated result */ 375 ok( (((hr == S_OK) || (hr == E_INVALIDARG)) && !memcmp(buffer, language, len)) || 376 ((hr == E_NOT_SUFFICIENT_BUFFER) && !len) || 377 ((hr == __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY)) && !len), 378 "=1: got 0x%x with %d and %s\n", hr, len, buffer); 379 380 len = 0; 381 memset(buffer, '#', maxlen); 382 buffer[maxlen] = 0; 383 hr = pGetAcceptLanguagesA( buffer, &len); 384 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG, win8 ERROR_CANNOT_COPY */ 385 ok((hr == E_FAIL) || (hr == E_INVALIDARG) || (hr == __HRESULT_FROM_WIN32(ERROR_CANNOT_COPY)), 386 "got 0x%x\n", hr); 387 388 memset(buffer, '#', maxlen); 389 buffer[maxlen] = 0; 390 hr = pGetAcceptLanguagesA( buffer, NULL); 391 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */ 392 ok((hr == E_FAIL) || (hr == E_INVALIDARG), 393 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr); 394 395 396 hr = pGetAcceptLanguagesA( NULL, NULL); 397 /* w2k3 and below: E_FAIL, since w2k8: E_INVALIDARG */ 398 ok((hr == E_FAIL) || (hr == E_INVALIDARG), 399 "got 0x%x (expected E_FAIL or E_INVALIDARG)\n", hr); 400 401 restore_original: 402 if (!res_query) { 403 len = lstrlenA(original); 404 lres = RegSetValueExA(hroot, acceptlanguage, 0, REG_SZ, (const BYTE *) original, len ? len + 1: 0); 405 ok(!lres, "RegSetValueEx(%s) failed: %d\n", original, lres); 406 } 407 else 408 { 409 RegDeleteValueA(hroot, acceptlanguage); 410 } 411 RegCloseKey(hroot); 412 } 413 414 static void test_SHSearchMapInt(void) 415 { 416 int keys[8], values[8]; 417 int i = 0; 418 419 if (!pSHSearchMapInt) 420 return; 421 422 memset(keys, 0, sizeof(keys)); 423 memset(values, 0, sizeof(values)); 424 keys[0] = 99; values[0] = 101; 425 426 /* NULL key/value lists crash native, so skip testing them */ 427 428 /* 1 element */ 429 i = pSHSearchMapInt(keys, values, 1, keys[0]); 430 ok(i == values[0], "Len 1, expected %d, got %d\n", values[0], i); 431 432 /* Key doesn't exist */ 433 i = pSHSearchMapInt(keys, values, 1, 100); 434 ok(i == -1, "Len 1 - bad key, expected -1, got %d\n", i); 435 436 /* Len = 0 => not found */ 437 i = pSHSearchMapInt(keys, values, 0, keys[0]); 438 ok(i == -1, "Len 1 - passed len 0, expected -1, got %d\n", i); 439 440 /* 2 elements, len = 1 */ 441 keys[1] = 98; values[1] = 102; 442 i = pSHSearchMapInt(keys, values, 1, keys[1]); 443 ok(i == -1, "Len 1 - array len 2, expected -1, got %d\n", i); 444 445 /* 2 elements, len = 2 */ 446 i = pSHSearchMapInt(keys, values, 2, keys[1]); 447 ok(i == values[1], "Len 2, expected %d, got %d\n", values[1], i); 448 449 /* Searches forward */ 450 keys[2] = 99; values[2] = 103; 451 i = pSHSearchMapInt(keys, values, 3, keys[0]); 452 ok(i == values[0], "Len 3, expected %d, got %d\n", values[0], i); 453 } 454 455 struct shared_struct 456 { 457 DWORD value; 458 HANDLE handle; 459 }; 460 461 static void test_alloc_shared(int argc, char **argv) 462 { 463 char cmdline[MAX_PATH]; 464 PROCESS_INFORMATION pi; 465 STARTUPINFOA si = { 0 }; 466 DWORD procid; 467 HANDLE hmem, hmem2 = 0; 468 struct shared_struct val, *p; 469 BOOL ret; 470 471 procid=GetCurrentProcessId(); 472 hmem=pSHAllocShared(NULL,10,procid); 473 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError()); 474 ret = pSHFreeShared(hmem, procid); 475 ok( ret, "SHFreeShared failed: %u\n", GetLastError()); 476 477 val.value = 0x12345678; 478 val.handle = 0; 479 hmem = pSHAllocShared(&val, sizeof(val), procid); 480 ok(hmem!=NULL,"SHAllocShared(NULL...) failed: %u\n", GetLastError()); 481 482 p=pSHLockShared(hmem,procid); 483 ok(p!=NULL,"SHLockShared failed: %u\n", GetLastError()); 484 if (p!=NULL) 485 ok(p->value == 0x12345678, "Wrong value in shared memory: %d instead of %d\n", p->value, 0x12345678); 486 ret = pSHUnlockShared(p); 487 ok( ret, "SHUnlockShared failed: %u\n", GetLastError()); 488 489 sprintf(cmdline, "%s %s %d %p", argv[0], argv[1], procid, hmem); 490 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 491 ok(ret, "could not create child process error: %u\n", GetLastError()); 492 if (ret) 493 { 494 winetest_wait_child_process(pi.hProcess); 495 CloseHandle(pi.hThread); 496 CloseHandle(pi.hProcess); 497 498 p = pSHLockShared(hmem, procid); 499 ok(p != NULL,"SHLockShared failed: %u\n", GetLastError()); 500 if (p != NULL && p->value != 0x12345678) 501 { 502 ok(p->value == 0x12345679, "Wrong value in shared memory: %d instead of %d\n", p->value, 0x12345679); 503 hmem2 = p->handle; 504 ok(hmem2 != NULL, "Expected handle in shared memory\n"); 505 } 506 ret = pSHUnlockShared(p); 507 ok(ret, "SHUnlockShared failed: %u\n", GetLastError()); 508 } 509 510 ret = pSHFreeShared(hmem, procid); 511 ok( ret, "SHFreeShared failed: %u\n", GetLastError()); 512 513 if (hmem2) 514 { 515 p = pSHLockShared(hmem2, procid); 516 ok(p != NULL,"SHLockShared failed: %u\n", GetLastError()); 517 if (p != NULL) 518 ok(p->value == 0xDEADBEEF, "Wrong value in shared memory: %d instead of %d\n", p->value, 0xDEADBEEF); 519 ret = pSHUnlockShared(p); 520 ok(ret, "SHUnlockShared failed: %u\n", GetLastError()); 521 522 ret = pSHFreeShared(hmem2, procid); 523 ok(ret, "SHFreeShared failed: %u\n", GetLastError()); 524 } 525 526 SetLastError(0xdeadbeef); 527 ret = pSHFreeShared(NULL, procid); 528 ok(ret, "SHFreeShared failed: %u\n", GetLastError()); 529 ok(GetLastError() == 0xdeadbeef, "last error should not have changed, got %u\n", GetLastError()); 530 } 531 532 static void test_alloc_shared_remote(DWORD procid, HANDLE hmem) 533 { 534 struct shared_struct val, *p; 535 HANDLE hmem2; 536 BOOL ret; 537 538 /* test directly accessing shared memory of a remote process */ 539 p = pSHLockShared(hmem, procid); 540 ok(p != NULL || broken(p == NULL) /* Windows 7/8 */, "SHLockShared failed: %u\n", GetLastError()); 541 if (p == NULL) 542 { 543 win_skip("Subprocess failed to modify shared memory, skipping test\n"); 544 return; 545 } 546 547 ok(p->value == 0x12345678, "Wrong value in shared memory: %d instead of %d\n", p->value, 0x12345678); 548 p->value++; 549 550 val.value = 0xDEADBEEF; 551 val.handle = 0; 552 p->handle = pSHAllocShared(&val, sizeof(val), procid); 553 ok(p->handle != NULL, "SHAllocShared failed: %u\n", GetLastError()); 554 555 ret = pSHUnlockShared(p); 556 ok(ret, "SHUnlockShared failed: %u\n", GetLastError()); 557 558 /* test SHMapHandle */ 559 SetLastError(0xdeadbeef); 560 hmem2 = pSHMapHandle(NULL, procid, GetCurrentProcessId(), 0, 0); 561 ok(hmem2 == NULL, "expected NULL, got new handle\n"); 562 ok(GetLastError() == 0xdeadbeef, "last error should not have changed, got %u\n", GetLastError()); 563 564 hmem2 = pSHMapHandle(hmem, procid, GetCurrentProcessId(), 0, 0); 565 566 /* It seems like Windows Vista/2008 uses a different internal implementation 567 * for shared memory, and calling SHMapHandle fails. */ 568 ok(hmem2 != NULL || broken(hmem2 == NULL), 569 "SHMapHandle failed: %u\n", GetLastError()); 570 if (hmem2 == NULL) 571 { 572 win_skip("Subprocess failed to map shared memory, skipping test\n"); 573 return; 574 } 575 576 p = pSHLockShared(hmem2, GetCurrentProcessId()); 577 ok(p != NULL, "SHLockShared failed: %u\n", GetLastError()); 578 579 if (p != NULL) 580 ok(p->value == 0x12345679, "Wrong value in shared memory: %d instead of %d\n", p->value, 0x12345679); 581 582 ret = pSHUnlockShared(p); 583 ok(ret, "SHUnlockShared failed: %u\n", GetLastError()); 584 585 ret = pSHFreeShared(hmem2, GetCurrentProcessId()); 586 ok(ret, "SHFreeShared failed: %u\n", GetLastError()); 587 } 588 589 static void test_fdsa(void) 590 { 591 typedef struct 592 { 593 DWORD num_items; /* Number of elements inserted */ 594 void *mem; /* Ptr to array */ 595 DWORD blocks_alloced; /* Number of elements allocated */ 596 BYTE inc; /* Number of elements to grow by when we need to expand */ 597 BYTE block_size; /* Size in bytes of an element */ 598 BYTE flags; /* Flags */ 599 } FDSA_info; 600 601 BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem, 602 DWORD init_blocks); 603 BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info); 604 DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, const void *block); 605 BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where); 606 607 FDSA_info info; 608 int block_size = 10, init_blocks = 4, inc = 2; 609 DWORD ret; 610 char *mem; 611 612 pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208); 613 pFDSA_Destroy = (void *)GetProcAddress(hShlwapi, (LPSTR)209); 614 pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210); 615 pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211); 616 617 mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks); 618 memset(&info, 0, sizeof(info)); 619 620 ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n"); 621 ok(info.num_items == 0, "num_items = %d\n", info.num_items); 622 ok(info.mem == mem, "mem = %p\n", info.mem); 623 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced); 624 ok(info.inc == inc, "inc = %d\n", info.inc); 625 ok(info.block_size == block_size, "block_size = %d\n", info.block_size); 626 ok(info.flags == 0, "flags = %d\n", info.flags); 627 628 ret = pFDSA_InsertItem(&info, 1234, "1234567890"); 629 ok(ret == 0, "ret = %d\n", ret); 630 ok(info.num_items == 1, "num_items = %d\n", info.num_items); 631 ok(info.mem == mem, "mem = %p\n", info.mem); 632 ok(info.blocks_alloced == init_blocks, "blocks_alloced = %d\n", info.blocks_alloced); 633 ok(info.inc == inc, "inc = %d\n", info.inc); 634 ok(info.block_size == block_size, "block_size = %d\n", info.block_size); 635 ok(info.flags == 0, "flags = %d\n", info.flags); 636 637 ret = pFDSA_InsertItem(&info, 1234, "abcdefghij"); 638 ok(ret == 1, "ret = %d\n", ret); 639 640 ret = pFDSA_InsertItem(&info, 1, "klmnopqrst"); 641 ok(ret == 1, "ret = %d\n", ret); 642 643 ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD"); 644 ok(ret == 0, "ret = %d\n", ret); 645 ok(info.mem == mem, "mem = %p\n", info.mem); 646 ok(info.flags == 0, "flags = %d\n", info.flags); 647 648 /* This next InsertItem will cause shlwapi to allocate its own mem buffer */ 649 ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN"); 650 ok(ret == 0, "ret = %d\n", ret); 651 ok(info.mem != mem, "mem = %p\n", info.mem); 652 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); 653 ok(info.flags == 0x1, "flags = %d\n", info.flags); 654 655 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem); 656 657 ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n"); 658 ok(info.mem != mem, "mem = %p\n", info.mem); 659 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); 660 ok(info.flags == 0x1, "flags = %d\n", info.flags); 661 662 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem); 663 664 ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n"); 665 ok(info.mem != mem, "mem = %p\n", info.mem); 666 ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %d\n", info.blocks_alloced); 667 ok(info.flags == 0x1, "flags = %d\n", info.flags); 668 669 ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem); 670 671 ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n"); 672 673 /* As shlwapi has allocated memory internally, Destroy will ret FALSE */ 674 ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n"); 675 676 677 /* When Initialize is called with inc = 0, set it to 1 */ 678 ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n"); 679 ok(info.inc == 1, "inc = %d\n", info.inc); 680 681 /* This time, because shlwapi hasn't had to allocate memory 682 internally, Destroy rets non-zero */ 683 ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n"); 684 685 686 HeapFree(GetProcessHeap(), 0, mem); 687 } 688 689 static void test_GetShellSecurityDescriptor(void) 690 { 691 static const SHELL_USER_PERMISSION supCurrentUserFull = { 692 { {SECURITY_NULL_SID_AUTHORITY}, 0, 0 }, 693 ACCESS_ALLOWED_ACE_TYPE, FALSE, 694 GENERIC_ALL, 0, 0 }; 695 #define MY_INHERITANCE 0xBE /* invalid value to proof behavior */ 696 static const SHELL_USER_PERMISSION supEveryoneDenied = { 697 { {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 }, 698 ACCESS_DENIED_ACE_TYPE, TRUE, 699 GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ }; 700 const SHELL_USER_PERMISSION* rgsup[2] = { 701 &supCurrentUserFull, &supEveryoneDenied, 702 }; 703 SECURITY_DESCRIPTOR* psd; 704 705 if(!pGetShellSecurityDescriptor) /* vista and later */ 706 { 707 win_skip("GetShellSecurityDescriptor not available\n"); 708 return; 709 } 710 711 psd = pGetShellSecurityDescriptor(NULL, 2); 712 ok(psd==NULL, "GetShellSecurityDescriptor should fail\n"); 713 psd = pGetShellSecurityDescriptor(rgsup, 0); 714 ok(psd==NULL, "GetShellSecurityDescriptor should fail, got %p\n", psd); 715 716 SetLastError(0xdeadbeef); 717 psd = pGetShellSecurityDescriptor(rgsup, 2); 718 ok(psd!=NULL, "GetShellSecurityDescriptor failed\n"); 719 if (psd!=NULL) 720 { 721 BOOL bHasDacl = FALSE, bDefaulted, ret; 722 PACL pAcl; 723 DWORD dwRev; 724 SECURITY_DESCRIPTOR_CONTROL control; 725 726 ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n"); 727 728 ret = GetSecurityDescriptorControl(psd, &control, &dwRev); 729 ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError()); 730 ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n"); 731 732 ret = GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted); 733 ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError()); 734 735 ok(bHasDacl, "SD has no DACL\n"); 736 if (bHasDacl) 737 { 738 ok(!bDefaulted, "DACL should not be defaulted\n"); 739 740 ok(pAcl != NULL, "NULL DACL!\n"); 741 if (pAcl != NULL) 742 { 743 ACL_SIZE_INFORMATION asiSize; 744 745 ok(IsValidAcl(pAcl), "DACL is not valid\n"); 746 747 ret = GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation); 748 ok(ret, "GetAclInformation failed with error %u\n", GetLastError()); 749 750 ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount); 751 if (asiSize.AceCount == 3) 752 { 753 ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */ 754 755 ret = GetAce(pAcl, 0, (LPVOID*)&paaa); 756 ok(ret, "GetAce failed with error %u\n", GetLastError()); 757 ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, 758 "Invalid ACE type %d\n", paaa->Header.AceType); 759 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags); 760 ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask); 761 762 ret = GetAce(pAcl, 1, (LPVOID*)&paaa); 763 ok(ret, "GetAce failed with error %u\n", GetLastError()); 764 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE, 765 "Invalid ACE type %d\n", paaa->Header.AceType); 766 /* first one of two ACEs generated from inheritable entry - without inheritance */ 767 ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags); 768 ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask); 769 770 ret = GetAce(pAcl, 2, (LPVOID*)&paaa); 771 ok(ret, "GetAce failed with error %u\n", GetLastError()); 772 ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE, 773 "Invalid ACE type %d\n", paaa->Header.AceType); 774 /* second ACE - with inheritance */ 775 ok(paaa->Header.AceFlags == MY_INHERITANCE, 776 "Invalid ACE flags %x\n", paaa->Header.AceFlags); 777 ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask); 778 } 779 } 780 } 781 782 LocalFree(psd); 783 } 784 } 785 786 static void test_SHPackDispParams(void) 787 { 788 DISPPARAMS params; 789 VARIANT vars[10]; 790 HRESULT hres; 791 792 memset(¶ms, 0xc0, sizeof(params)); 793 memset(vars, 0xc0, sizeof(vars)); 794 hres = pSHPackDispParams(¶ms, vars, 1, VT_I4, 0xdeadbeef); 795 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres); 796 ok(params.cArgs == 1, "params.cArgs = %d\n", params.cArgs); 797 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs); 798 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs); 799 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg); 800 ok(V_VT(vars) == VT_I4, "V_VT(var) = %d\n", V_VT(vars)); 801 ok(V_I4(vars) == 0xdeadbeef, "failed %x\n", V_I4(vars)); 802 803 memset(¶ms, 0xc0, sizeof(params)); 804 hres = pSHPackDispParams(¶ms, NULL, 0, 0); 805 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres); 806 ok(params.cArgs == 0, "params.cArgs = %d\n", params.cArgs); 807 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs); 808 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs); 809 ok(params.rgvarg == NULL, "params.rgvarg = %p\n", params.rgvarg); 810 811 memset(vars, 0xc0, sizeof(vars)); 812 memset(¶ms, 0xc0, sizeof(params)); 813 hres = pSHPackDispParams(¶ms, vars, 4, VT_BSTR, (void*)0xdeadbeef, VT_EMPTY, 10, 814 VT_I4, 100, VT_DISPATCH, (void*)0xdeadbeef); 815 ok(hres == S_OK, "SHPackDispParams failed: %08x\n", hres); 816 ok(params.cArgs == 4, "params.cArgs = %d\n", params.cArgs); 817 ok(params.cNamedArgs == 0, "params.cNamedArgs = %d\n", params.cArgs); 818 ok(params.rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", params.rgdispidNamedArgs); 819 ok(params.rgvarg == vars, "params.rgvarg = %p\n", params.rgvarg); 820 ok(V_VT(vars) == VT_DISPATCH, "V_VT(vars[0]) = %x\n", V_VT(vars)); 821 ok(V_I4(vars) == 0xdeadbeef, "V_I4(vars[0]) = %x\n", V_I4(vars)); 822 ok(V_VT(vars+1) == VT_I4, "V_VT(vars[1]) = %d\n", V_VT(vars+1)); 823 ok(V_I4(vars+1) == 100, "V_I4(vars[1]) = %x\n", V_I4(vars+1)); 824 ok(V_VT(vars+2) == VT_I4, "V_VT(vars[2]) = %d\n", V_VT(vars+2)); 825 ok(V_I4(vars+2) == 10, "V_I4(vars[2]) = %x\n", V_I4(vars+2)); 826 ok(V_VT(vars+3) == VT_BSTR, "V_VT(vars[3]) = %d\n", V_VT(vars+3)); 827 ok(V_BSTR(vars+3) == (void*)0xdeadbeef, "V_BSTR(vars[3]) = %p\n", V_BSTR(vars+3)); 828 } 829 830 typedef struct _disp 831 { 832 IDispatch IDispatch_iface; 833 LONG refCount; 834 } Disp; 835 836 static inline Disp *impl_from_IDispatch(IDispatch *iface) 837 { 838 return CONTAINING_RECORD(iface, Disp, IDispatch_iface); 839 } 840 841 typedef struct _contain 842 { 843 IConnectionPointContainer IConnectionPointContainer_iface; 844 LONG refCount; 845 846 UINT ptCount; 847 IConnectionPoint **pt; 848 } Contain; 849 850 static inline Contain *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface) 851 { 852 return CONTAINING_RECORD(iface, Contain, IConnectionPointContainer_iface); 853 } 854 855 typedef struct _cntptn 856 { 857 IConnectionPoint IConnectionPoint_iface; 858 LONG refCount; 859 860 Contain *container; 861 GUID id; 862 UINT sinkCount; 863 IUnknown **sink; 864 } ConPt; 865 866 static inline ConPt *impl_from_IConnectionPoint(IConnectionPoint *iface) 867 { 868 return CONTAINING_RECORD(iface, ConPt, IConnectionPoint_iface); 869 } 870 871 typedef struct _enum 872 { 873 IEnumConnections IEnumConnections_iface; 874 LONG refCount; 875 876 UINT idx; 877 ConPt *pt; 878 } EnumCon; 879 880 static inline EnumCon *impl_from_IEnumConnections(IEnumConnections *iface) 881 { 882 return CONTAINING_RECORD(iface, EnumCon, IEnumConnections_iface); 883 } 884 885 typedef struct _enumpt 886 { 887 IEnumConnectionPoints IEnumConnectionPoints_iface; 888 LONG refCount; 889 890 int idx; 891 Contain *container; 892 } EnumPt; 893 894 static inline EnumPt *impl_from_IEnumConnectionPoints(IEnumConnectionPoints *iface) 895 { 896 return CONTAINING_RECORD(iface, EnumPt, IEnumConnectionPoints_iface); 897 } 898 899 900 static HRESULT WINAPI Disp_QueryInterface( 901 IDispatch* This, 902 REFIID riid, 903 void **ppvObject) 904 { 905 *ppvObject = NULL; 906 907 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) 908 { 909 *ppvObject = This; 910 } 911 912 if (*ppvObject) 913 { 914 IDispatch_AddRef(This); 915 return S_OK; 916 } 917 918 trace("no interface\n"); 919 return E_NOINTERFACE; 920 } 921 922 static ULONG WINAPI Disp_AddRef(IDispatch* This) 923 { 924 Disp *iface = impl_from_IDispatch(This); 925 return InterlockedIncrement(&iface->refCount); 926 } 927 928 static ULONG WINAPI Disp_Release(IDispatch* This) 929 { 930 Disp *iface = impl_from_IDispatch(This); 931 ULONG ret; 932 933 ret = InterlockedDecrement(&iface->refCount); 934 if (ret == 0) 935 HeapFree(GetProcessHeap(),0,This); 936 return ret; 937 } 938 939 static HRESULT WINAPI Disp_GetTypeInfoCount( 940 IDispatch* This, 941 UINT *pctinfo) 942 { 943 return ERROR_SUCCESS; 944 } 945 946 static HRESULT WINAPI Disp_GetTypeInfo( 947 IDispatch* This, 948 UINT iTInfo, 949 LCID lcid, 950 ITypeInfo **ppTInfo) 951 { 952 return ERROR_SUCCESS; 953 } 954 955 static HRESULT WINAPI Disp_GetIDsOfNames( 956 IDispatch* This, 957 REFIID riid, 958 LPOLESTR *rgszNames, 959 UINT cNames, 960 LCID lcid, 961 DISPID *rgDispId) 962 { 963 return ERROR_SUCCESS; 964 } 965 966 static HRESULT WINAPI Disp_Invoke( 967 IDispatch* This, 968 DISPID dispIdMember, 969 REFIID riid, 970 LCID lcid, 971 WORD wFlags, 972 DISPPARAMS *pDispParams, 973 VARIANT *pVarResult, 974 EXCEPINFO *pExcepInfo, 975 UINT *puArgErr) 976 { 977 trace("%p %x %s %x %x %p %p %p %p\n", This, dispIdMember, wine_dbgstr_guid(riid), lcid, wFlags, 978 pDispParams, pVarResult, pExcepInfo, puArgErr); 979 980 ok(dispIdMember == 0xa0 || dispIdMember == 0xa1, "Unknown dispIdMember\n"); 981 ok(pDispParams != NULL, "Invoked with NULL pDispParams\n"); 982 ok(wFlags == DISPATCH_METHOD, "Wrong flags %x\n",wFlags); 983 ok(lcid == 0,"Wrong lcid %x\n",lcid); 984 if (dispIdMember == 0xa0) 985 { 986 ok(pDispParams->cArgs == 0, "params.cArgs = %d\n", pDispParams->cArgs); 987 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs); 988 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs); 989 ok(pDispParams->rgvarg == NULL, "params.rgvarg = %p\n", pDispParams->rgvarg); 990 } 991 else if (dispIdMember == 0xa1) 992 { 993 ok(pDispParams->cArgs == 2, "params.cArgs = %d\n", pDispParams->cArgs); 994 ok(pDispParams->cNamedArgs == 0, "params.cNamedArgs = %d\n", pDispParams->cArgs); 995 ok(pDispParams->rgdispidNamedArgs == NULL, "params.rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs); 996 ok(V_VT(pDispParams->rgvarg) == VT_BSTR, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg)); 997 ok(V_I4(pDispParams->rgvarg) == 0xdeadcafe , "failed %p\n", V_BSTR(pDispParams->rgvarg)); 998 ok(V_VT(pDispParams->rgvarg+1) == VT_I4, "V_VT(var) = %d\n", V_VT(pDispParams->rgvarg+1)); 999 ok(V_I4(pDispParams->rgvarg+1) == 0xdeadbeef, "failed %x\n", V_I4(pDispParams->rgvarg+1)); 1000 } 1001 1002 return ERROR_SUCCESS; 1003 } 1004 1005 static const IDispatchVtbl disp_vtbl = { 1006 Disp_QueryInterface, 1007 Disp_AddRef, 1008 Disp_Release, 1009 1010 Disp_GetTypeInfoCount, 1011 Disp_GetTypeInfo, 1012 Disp_GetIDsOfNames, 1013 Disp_Invoke 1014 }; 1015 1016 static HRESULT WINAPI Enum_QueryInterface( 1017 IEnumConnections* This, 1018 REFIID riid, 1019 void **ppvObject) 1020 { 1021 *ppvObject = NULL; 1022 1023 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnections)) 1024 { 1025 *ppvObject = This; 1026 } 1027 1028 if (*ppvObject) 1029 { 1030 IEnumConnections_AddRef(This); 1031 return S_OK; 1032 } 1033 1034 trace("no interface\n"); 1035 return E_NOINTERFACE; 1036 } 1037 1038 static ULONG WINAPI Enum_AddRef(IEnumConnections* This) 1039 { 1040 EnumCon *iface = impl_from_IEnumConnections(This); 1041 return InterlockedIncrement(&iface->refCount); 1042 } 1043 1044 static ULONG WINAPI Enum_Release(IEnumConnections* This) 1045 { 1046 EnumCon *iface = impl_from_IEnumConnections(This); 1047 ULONG ret; 1048 1049 ret = InterlockedDecrement(&iface->refCount); 1050 if (ret == 0) 1051 HeapFree(GetProcessHeap(),0,This); 1052 return ret; 1053 } 1054 1055 static HRESULT WINAPI Enum_Next( 1056 IEnumConnections* This, 1057 ULONG cConnections, 1058 LPCONNECTDATA rgcd, 1059 ULONG *pcFetched) 1060 { 1061 EnumCon *iface = impl_from_IEnumConnections(This); 1062 1063 if (cConnections > 0 && iface->idx < iface->pt->sinkCount) 1064 { 1065 rgcd->pUnk = iface->pt->sink[iface->idx]; 1066 IUnknown_AddRef(iface->pt->sink[iface->idx]); 1067 rgcd->dwCookie=0xff; 1068 if (pcFetched) 1069 *pcFetched = 1; 1070 iface->idx++; 1071 return S_OK; 1072 } 1073 1074 return E_FAIL; 1075 } 1076 1077 static HRESULT WINAPI Enum_Skip( 1078 IEnumConnections* This, 1079 ULONG cConnections) 1080 { 1081 return E_FAIL; 1082 } 1083 1084 static HRESULT WINAPI Enum_Reset( 1085 IEnumConnections* This) 1086 { 1087 return E_FAIL; 1088 } 1089 1090 static HRESULT WINAPI Enum_Clone( 1091 IEnumConnections* This, 1092 IEnumConnections **ppEnum) 1093 { 1094 return E_FAIL; 1095 } 1096 1097 static const IEnumConnectionsVtbl enum_vtbl = { 1098 1099 Enum_QueryInterface, 1100 Enum_AddRef, 1101 Enum_Release, 1102 Enum_Next, 1103 Enum_Skip, 1104 Enum_Reset, 1105 Enum_Clone 1106 }; 1107 1108 static HRESULT WINAPI ConPt_QueryInterface( 1109 IConnectionPoint* This, 1110 REFIID riid, 1111 void **ppvObject) 1112 { 1113 *ppvObject = NULL; 1114 1115 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPoint)) 1116 { 1117 *ppvObject = This; 1118 } 1119 1120 if (*ppvObject) 1121 { 1122 IConnectionPoint_AddRef(This); 1123 return S_OK; 1124 } 1125 1126 trace("no interface\n"); 1127 return E_NOINTERFACE; 1128 } 1129 1130 static ULONG WINAPI ConPt_AddRef( 1131 IConnectionPoint* This) 1132 { 1133 ConPt *iface = impl_from_IConnectionPoint(This); 1134 return InterlockedIncrement(&iface->refCount); 1135 } 1136 1137 static ULONG WINAPI ConPt_Release( 1138 IConnectionPoint* This) 1139 { 1140 ConPt *iface = impl_from_IConnectionPoint(This); 1141 ULONG ret; 1142 1143 ret = InterlockedDecrement(&iface->refCount); 1144 if (ret == 0) 1145 { 1146 if (iface->sinkCount > 0) 1147 { 1148 int i; 1149 for (i = 0; i < iface->sinkCount; i++) 1150 { 1151 if (iface->sink[i]) 1152 IUnknown_Release(iface->sink[i]); 1153 } 1154 HeapFree(GetProcessHeap(),0,iface->sink); 1155 } 1156 HeapFree(GetProcessHeap(),0,This); 1157 } 1158 return ret; 1159 } 1160 1161 static HRESULT WINAPI ConPt_GetConnectionInterface( 1162 IConnectionPoint* This, 1163 IID *pIID) 1164 { 1165 static int i = 0; 1166 ConPt *iface = impl_from_IConnectionPoint(This); 1167 if (i==0) 1168 { 1169 i++; 1170 return E_FAIL; 1171 } 1172 else 1173 memcpy(pIID,&iface->id,sizeof(GUID)); 1174 return S_OK; 1175 } 1176 1177 static HRESULT WINAPI ConPt_GetConnectionPointContainer( 1178 IConnectionPoint* This, 1179 IConnectionPointContainer **ppCPC) 1180 { 1181 ConPt *iface = impl_from_IConnectionPoint(This); 1182 1183 *ppCPC = &iface->container->IConnectionPointContainer_iface; 1184 return S_OK; 1185 } 1186 1187 static HRESULT WINAPI ConPt_Advise( 1188 IConnectionPoint* This, 1189 IUnknown *pUnkSink, 1190 DWORD *pdwCookie) 1191 { 1192 ConPt *iface = impl_from_IConnectionPoint(This); 1193 1194 if (iface->sinkCount == 0) 1195 iface->sink = HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*)); 1196 else 1197 iface->sink = HeapReAlloc(GetProcessHeap(),0,iface->sink,sizeof(IUnknown*)*(iface->sinkCount+1)); 1198 iface->sink[iface->sinkCount] = pUnkSink; 1199 IUnknown_AddRef(pUnkSink); 1200 iface->sinkCount++; 1201 *pdwCookie = iface->sinkCount; 1202 return S_OK; 1203 } 1204 1205 static HRESULT WINAPI ConPt_Unadvise( 1206 IConnectionPoint* This, 1207 DWORD dwCookie) 1208 { 1209 ConPt *iface = impl_from_IConnectionPoint(This); 1210 1211 if (dwCookie > iface->sinkCount) 1212 return E_FAIL; 1213 else 1214 { 1215 IUnknown_Release(iface->sink[dwCookie-1]); 1216 iface->sink[dwCookie-1] = NULL; 1217 } 1218 return S_OK; 1219 } 1220 1221 static HRESULT WINAPI ConPt_EnumConnections( 1222 IConnectionPoint* This, 1223 IEnumConnections **ppEnum) 1224 { 1225 EnumCon *ec; 1226 1227 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumCon)); 1228 ec->IEnumConnections_iface.lpVtbl = &enum_vtbl; 1229 ec->refCount = 1; 1230 ec->pt = impl_from_IConnectionPoint(This); 1231 ec->idx = 0; 1232 *ppEnum = &ec->IEnumConnections_iface; 1233 1234 return S_OK; 1235 } 1236 1237 static const IConnectionPointVtbl point_vtbl = { 1238 ConPt_QueryInterface, 1239 ConPt_AddRef, 1240 ConPt_Release, 1241 1242 ConPt_GetConnectionInterface, 1243 ConPt_GetConnectionPointContainer, 1244 ConPt_Advise, 1245 ConPt_Unadvise, 1246 ConPt_EnumConnections 1247 }; 1248 1249 static HRESULT WINAPI EnumPt_QueryInterface( 1250 IEnumConnectionPoints* This, 1251 REFIID riid, 1252 void **ppvObject) 1253 { 1254 *ppvObject = NULL; 1255 1256 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumConnectionPoints)) 1257 { 1258 *ppvObject = This; 1259 } 1260 1261 if (*ppvObject) 1262 { 1263 IEnumConnectionPoints_AddRef(This); 1264 return S_OK; 1265 } 1266 1267 trace("no interface\n"); 1268 return E_NOINTERFACE; 1269 } 1270 1271 static ULONG WINAPI EnumPt_AddRef(IEnumConnectionPoints* This) 1272 { 1273 EnumPt *iface = impl_from_IEnumConnectionPoints(This); 1274 return InterlockedIncrement(&iface->refCount); 1275 } 1276 1277 static ULONG WINAPI EnumPt_Release(IEnumConnectionPoints* This) 1278 { 1279 EnumPt *iface = impl_from_IEnumConnectionPoints(This); 1280 ULONG ret; 1281 1282 ret = InterlockedDecrement(&iface->refCount); 1283 if (ret == 0) 1284 HeapFree(GetProcessHeap(),0,This); 1285 return ret; 1286 } 1287 1288 static HRESULT WINAPI EnumPt_Next( 1289 IEnumConnectionPoints* This, 1290 ULONG cConnections, 1291 IConnectionPoint **rgcd, 1292 ULONG *pcFetched) 1293 { 1294 EnumPt *iface = impl_from_IEnumConnectionPoints(This); 1295 1296 if (cConnections > 0 && iface->idx < iface->container->ptCount) 1297 { 1298 *rgcd = iface->container->pt[iface->idx]; 1299 IConnectionPoint_AddRef(iface->container->pt[iface->idx]); 1300 if (pcFetched) 1301 *pcFetched = 1; 1302 iface->idx++; 1303 return S_OK; 1304 } 1305 1306 return E_FAIL; 1307 } 1308 1309 static HRESULT WINAPI EnumPt_Skip( 1310 IEnumConnectionPoints* This, 1311 ULONG cConnections) 1312 { 1313 return E_FAIL; 1314 } 1315 1316 static HRESULT WINAPI EnumPt_Reset( 1317 IEnumConnectionPoints* This) 1318 { 1319 return E_FAIL; 1320 } 1321 1322 static HRESULT WINAPI EnumPt_Clone( 1323 IEnumConnectionPoints* This, 1324 IEnumConnectionPoints **ppEnumPt) 1325 { 1326 return E_FAIL; 1327 } 1328 1329 static const IEnumConnectionPointsVtbl enumpt_vtbl = { 1330 1331 EnumPt_QueryInterface, 1332 EnumPt_AddRef, 1333 EnumPt_Release, 1334 EnumPt_Next, 1335 EnumPt_Skip, 1336 EnumPt_Reset, 1337 EnumPt_Clone 1338 }; 1339 1340 static HRESULT WINAPI Contain_QueryInterface( 1341 IConnectionPointContainer* This, 1342 REFIID riid, 1343 void **ppvObject) 1344 { 1345 *ppvObject = NULL; 1346 1347 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IConnectionPointContainer)) 1348 { 1349 *ppvObject = This; 1350 } 1351 1352 if (*ppvObject) 1353 { 1354 IConnectionPointContainer_AddRef(This); 1355 return S_OK; 1356 } 1357 1358 trace("no interface\n"); 1359 return E_NOINTERFACE; 1360 } 1361 1362 static ULONG WINAPI Contain_AddRef( 1363 IConnectionPointContainer* This) 1364 { 1365 Contain *iface = impl_from_IConnectionPointContainer(This); 1366 return InterlockedIncrement(&iface->refCount); 1367 } 1368 1369 static ULONG WINAPI Contain_Release( 1370 IConnectionPointContainer* This) 1371 { 1372 Contain *iface = impl_from_IConnectionPointContainer(This); 1373 ULONG ret; 1374 1375 ret = InterlockedDecrement(&iface->refCount); 1376 if (ret == 0) 1377 { 1378 if (iface->ptCount > 0) 1379 { 1380 int i; 1381 for (i = 0; i < iface->ptCount; i++) 1382 IConnectionPoint_Release(iface->pt[i]); 1383 HeapFree(GetProcessHeap(),0,iface->pt); 1384 } 1385 HeapFree(GetProcessHeap(),0,This); 1386 } 1387 return ret; 1388 } 1389 1390 static HRESULT WINAPI Contain_EnumConnectionPoints( 1391 IConnectionPointContainer* This, 1392 IEnumConnectionPoints **ppEnum) 1393 { 1394 EnumPt *ec; 1395 1396 ec = HeapAlloc(GetProcessHeap(),0,sizeof(EnumPt)); 1397 ec->IEnumConnectionPoints_iface.lpVtbl = &enumpt_vtbl; 1398 ec->refCount = 1; 1399 ec->idx= 0; 1400 ec->container = impl_from_IConnectionPointContainer(This); 1401 *ppEnum = &ec->IEnumConnectionPoints_iface; 1402 1403 return S_OK; 1404 } 1405 1406 static HRESULT WINAPI Contain_FindConnectionPoint( 1407 IConnectionPointContainer* This, 1408 REFIID riid, 1409 IConnectionPoint **ppCP) 1410 { 1411 Contain *iface = impl_from_IConnectionPointContainer(This); 1412 ConPt *pt; 1413 1414 if (!IsEqualIID(riid, &IID_NULL) || iface->ptCount ==0) 1415 { 1416 pt = HeapAlloc(GetProcessHeap(),0,sizeof(ConPt)); 1417 pt->IConnectionPoint_iface.lpVtbl = &point_vtbl; 1418 pt->refCount = 1; 1419 pt->sinkCount = 0; 1420 pt->sink = NULL; 1421 pt->container = iface; 1422 pt->id = IID_IDispatch; 1423 1424 if (iface->ptCount == 0) 1425 iface->pt =HeapAlloc(GetProcessHeap(),0,sizeof(IUnknown*)); 1426 else 1427 iface->pt = HeapReAlloc(GetProcessHeap(),0,iface->pt,sizeof(IUnknown*)*(iface->ptCount+1)); 1428 iface->pt[iface->ptCount] = &pt->IConnectionPoint_iface; 1429 iface->ptCount++; 1430 1431 *ppCP = &pt->IConnectionPoint_iface; 1432 } 1433 else 1434 { 1435 *ppCP = iface->pt[0]; 1436 IUnknown_AddRef((IUnknown*)*ppCP); 1437 } 1438 1439 return S_OK; 1440 } 1441 1442 static const IConnectionPointContainerVtbl contain_vtbl = { 1443 Contain_QueryInterface, 1444 Contain_AddRef, 1445 Contain_Release, 1446 1447 Contain_EnumConnectionPoints, 1448 Contain_FindConnectionPoint 1449 }; 1450 1451 static void test_IConnectionPoint(void) 1452 { 1453 HRESULT rc; 1454 ULONG ref; 1455 IConnectionPoint *point; 1456 Contain *container; 1457 Disp *dispatch; 1458 DWORD cookie = 0xffffffff; 1459 DISPPARAMS params; 1460 VARIANT vars[10]; 1461 1462 container = HeapAlloc(GetProcessHeap(),0,sizeof(Contain)); 1463 container->IConnectionPointContainer_iface.lpVtbl = &contain_vtbl; 1464 container->refCount = 1; 1465 container->ptCount = 0; 1466 container->pt = NULL; 1467 1468 dispatch = HeapAlloc(GetProcessHeap(),0,sizeof(Disp)); 1469 dispatch->IDispatch_iface.lpVtbl = &disp_vtbl; 1470 dispatch->refCount = 1; 1471 1472 rc = pConnectToConnectionPoint((IUnknown*)dispatch, &IID_NULL, TRUE, (IUnknown*)container, &cookie, &point); 1473 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc); 1474 ok(point != NULL, "returned ConnectionPoint is NULL\n"); 1475 ok(cookie != 0xffffffff, "invalid cookie returned\n"); 1476 1477 rc = pIConnectionPoint_SimpleInvoke(point,0xa0,NULL); 1478 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc); 1479 1480 memset(¶ms, 0xc0, sizeof(params)); 1481 memset(vars, 0xc0, sizeof(vars)); 1482 rc = pSHPackDispParams(¶ms, vars, 2, VT_I4, 0xdeadbeef, VT_BSTR, 0xdeadcafe); 1483 ok(rc == S_OK, "SHPackDispParams failed: %08x\n", rc); 1484 1485 rc = pIConnectionPoint_SimpleInvoke(point,0xa1,¶ms); 1486 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc); 1487 1488 rc = pConnectToConnectionPoint(NULL, &IID_NULL, FALSE, (IUnknown*)container, &cookie, NULL); 1489 ok(rc == S_OK, "pConnectToConnectionPoint failed with %x\n",rc); 1490 1491 /* MSDN says this should be required but it crashs on XP 1492 IUnknown_Release(point); 1493 */ 1494 ref = IUnknown_Release((IUnknown*)container); 1495 ok(ref == 0, "leftover IConnectionPointContainer reference %i\n",ref); 1496 ref = IUnknown_Release((IUnknown*)dispatch); 1497 ok(ref == 0, "leftover IDispatch reference %i\n",ref); 1498 } 1499 1500 typedef struct _propbag 1501 { 1502 IPropertyBag IPropertyBag_iface; 1503 LONG refCount; 1504 1505 } PropBag; 1506 1507 static inline PropBag *impl_from_IPropertyBag(IPropertyBag *iface) 1508 { 1509 return CONTAINING_RECORD(iface, PropBag, IPropertyBag_iface); 1510 } 1511 1512 1513 static HRESULT WINAPI Prop_QueryInterface( 1514 IPropertyBag* This, 1515 REFIID riid, 1516 void **ppvObject) 1517 { 1518 *ppvObject = NULL; 1519 1520 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPropertyBag)) 1521 { 1522 *ppvObject = This; 1523 } 1524 1525 if (*ppvObject) 1526 { 1527 IPropertyBag_AddRef(This); 1528 return S_OK; 1529 } 1530 1531 trace("no interface\n"); 1532 return E_NOINTERFACE; 1533 } 1534 1535 static ULONG WINAPI Prop_AddRef( 1536 IPropertyBag* This) 1537 { 1538 PropBag *iface = impl_from_IPropertyBag(This); 1539 return InterlockedIncrement(&iface->refCount); 1540 } 1541 1542 static ULONG WINAPI Prop_Release( 1543 IPropertyBag* This) 1544 { 1545 PropBag *iface = impl_from_IPropertyBag(This); 1546 ULONG ret; 1547 1548 ret = InterlockedDecrement(&iface->refCount); 1549 if (ret == 0) 1550 HeapFree(GetProcessHeap(),0,This); 1551 return ret; 1552 } 1553 1554 static HRESULT WINAPI Prop_Read( 1555 IPropertyBag* This, 1556 LPCOLESTR pszPropName, 1557 VARIANT *pVar, 1558 IErrorLog *pErrorLog) 1559 { 1560 V_VT(pVar) = VT_BLOB|VT_BYREF; 1561 V_BYREF(pVar) = (LPVOID)0xdeadcafe; 1562 return S_OK; 1563 } 1564 1565 static HRESULT WINAPI Prop_Write( 1566 IPropertyBag* This, 1567 LPCOLESTR pszPropName, 1568 VARIANT *pVar) 1569 { 1570 return S_OK; 1571 } 1572 1573 1574 static const IPropertyBagVtbl prop_vtbl = { 1575 Prop_QueryInterface, 1576 Prop_AddRef, 1577 Prop_Release, 1578 1579 Prop_Read, 1580 Prop_Write 1581 }; 1582 1583 static void test_SHPropertyBag_ReadLONG(void) 1584 { 1585 PropBag *pb; 1586 HRESULT rc; 1587 LONG out; 1588 static const WCHAR szName1[] = {'n','a','m','e','1',0}; 1589 1590 pb = HeapAlloc(GetProcessHeap(),0,sizeof(PropBag)); 1591 pb->refCount = 1; 1592 pb->IPropertyBag_iface.lpVtbl = &prop_vtbl; 1593 1594 out = 0xfeedface; 1595 rc = pSHPropertyBag_ReadLONG(NULL, szName1, &out); 1596 ok(rc == E_INVALIDARG || broken(rc == S_OK), "incorrect return %x\n",rc); 1597 ok(out == 0xfeedface, "value should not have changed\n"); 1598 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, NULL, &out); 1599 ok(rc == E_INVALIDARG || broken(rc == S_OK) || broken(rc == S_FALSE), "incorrect return %x\n",rc); 1600 ok(out == 0xfeedface, "value should not have changed\n"); 1601 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, NULL); 1602 ok(rc == E_INVALIDARG || broken(rc == S_OK) || broken(rc == S_FALSE), "incorrect return %x\n",rc); 1603 rc = pSHPropertyBag_ReadLONG(&pb->IPropertyBag_iface, szName1, &out); 1604 ok(rc == DISP_E_BADVARTYPE || broken(rc == S_OK) || broken(rc == S_FALSE), "incorrect return %x\n",rc); 1605 ok(out == 0xfeedface || broken(out == 0xfeedfa00), "value should not have changed %x\n",out); 1606 IUnknown_Release((IUnknown*)pb); 1607 } 1608 1609 static void test_SHSetWindowBits(void) 1610 { 1611 HWND hwnd; 1612 DWORD style, styleold; 1613 WNDCLASSA clsA; 1614 1615 clsA.style = 0; 1616 clsA.lpfnWndProc = DefWindowProcA; 1617 clsA.cbClsExtra = 0; 1618 clsA.cbWndExtra = 0; 1619 clsA.hInstance = GetModuleHandleA(NULL); 1620 clsA.hIcon = 0; 1621 clsA.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); 1622 clsA.hbrBackground = NULL; 1623 clsA.lpszMenuName = NULL; 1624 clsA.lpszClassName = "Shlwapi test class"; 1625 RegisterClassA(&clsA); 1626 1627 hwnd = CreateWindowA("Shlwapi test class", "Test", WS_VISIBLE, 0, 0, 100, 100, 1628 NULL, NULL, GetModuleHandleA(NULL), 0); 1629 ok(IsWindow(hwnd), "failed to create window\n"); 1630 1631 /* null window */ 1632 SetLastError(0xdeadbeef); 1633 style = pSHSetWindowBits(NULL, GWL_STYLE, 0, 0); 1634 ok(style == 0, "expected 0 retval, got %d\n", style); 1635 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, 1636 "expected ERROR_INVALID_WINDOW_HANDLE, got %d\n", GetLastError()); 1637 1638 /* zero mask, zero flags */ 1639 styleold = GetWindowLongA(hwnd, GWL_STYLE); 1640 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, 0); 1641 ok(styleold == style, "expected old style\n"); 1642 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n"); 1643 1644 /* test mask */ 1645 styleold = GetWindowLongA(hwnd, GWL_STYLE); 1646 ok(styleold & WS_VISIBLE, "expected WS_VISIBLE\n"); 1647 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0); 1648 1649 ok(style == styleold, "expected previous style, got %x\n", style); 1650 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n"); 1651 1652 /* test mask, unset style bit used */ 1653 styleold = GetWindowLongA(hwnd, GWL_STYLE); 1654 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0); 1655 ok(style == styleold, "expected previous style, got %x\n", style); 1656 ok(styleold == GetWindowLongA(hwnd, GWL_STYLE), "expected to keep old style\n"); 1657 1658 /* set back with flags */ 1659 styleold = GetWindowLongA(hwnd, GWL_STYLE); 1660 style = pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, WS_VISIBLE); 1661 ok(style == styleold, "expected previous style, got %x\n", style); 1662 ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "expected updated style\n"); 1663 1664 /* reset and try to set without a mask */ 1665 pSHSetWindowBits(hwnd, GWL_STYLE, WS_VISIBLE, 0); 1666 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n"); 1667 styleold = GetWindowLongA(hwnd, GWL_STYLE); 1668 style = pSHSetWindowBits(hwnd, GWL_STYLE, 0, WS_VISIBLE); 1669 ok(style == styleold, "expected previous style, got %x\n", style); 1670 ok((GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE) == 0, "expected updated style\n"); 1671 1672 DestroyWindow(hwnd); 1673 1674 UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL)); 1675 } 1676 1677 static void test_SHFormatDateTimeA(void) 1678 { 1679 FILETIME UNALIGNED filetime; 1680 CHAR buff[100], buff2[100], buff3[100]; 1681 SYSTEMTIME st; 1682 DWORD flags; 1683 INT ret; 1684 1685 if (0) 1686 { 1687 /* crashes on native */ 1688 pSHFormatDateTimeA(NULL, NULL, NULL, 0); 1689 } 1690 1691 GetLocalTime(&st); 1692 SystemTimeToFileTime(&st, &filetime); 1693 /* SHFormatDateTime expects input as utc */ 1694 LocalFileTimeToFileTime(&filetime, &filetime); 1695 1696 /* no way to get required buffer length here */ 1697 SetLastError(0xdeadbeef); 1698 ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0); 1699 ok(ret == 0, "got %d\n", ret); 1700 ok(GetLastError() == 0xdeadbeef || broken(GetLastError() == ERROR_SUCCESS /* Win7 */), 1701 "expected 0xdeadbeef, got %d\n", GetLastError()); 1702 1703 SetLastError(0xdeadbeef); 1704 buff[0] = 'a'; buff[1] = 0; 1705 ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0); 1706 ok(ret == 0, "got %d\n", ret); 1707 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1708 ok(buff[0] == 'a', "expected same string, got %s\n", buff); 1709 1710 /* flags needs to have FDTF_NOAUTOREADINGORDER for these tests to succeed on Vista+ */ 1711 1712 /* all combinations documented as invalid succeeded */ 1713 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME | FDTF_LONGTIME; 1714 SetLastError(0xdeadbeef); 1715 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1716 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1717 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1718 1719 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGDATE; 1720 SetLastError(0xdeadbeef); 1721 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1722 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1723 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1724 1725 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE; 1726 SetLastError(0xdeadbeef); 1727 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1728 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1729 ok(GetLastError() == 0xdeadbeef, 1730 "expected 0xdeadbeef, got %d\n", GetLastError()); 1731 1732 /* now check returned strings */ 1733 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTTIME; 1734 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1735 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1736 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)); 1737 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1738 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1739 1740 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME; 1741 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1742 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1743 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)); 1744 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1745 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1746 1747 /* both time flags */ 1748 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGTIME | FDTF_SHORTTIME; 1749 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1750 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1751 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)); 1752 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1753 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1754 1755 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE; 1756 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1757 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1758 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); 1759 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1760 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1761 1762 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE; 1763 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1764 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1765 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); 1766 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1767 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1768 1769 /* both date flags */ 1770 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTDATE; 1771 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1772 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1773 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); 1774 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1775 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1776 1777 /* various combinations of date/time flags */ 1778 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_SHORTTIME; 1779 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1780 ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1); 1781 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)); 1782 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); 1783 ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, 1784 "expected (%s), got (%s) for time part\n", 1785 buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); 1786 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); 1787 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1788 buff[lstrlenA(buff2)] = '\0'; 1789 ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", 1790 buff2, buff); 1791 1792 flags = FDTF_NOAUTOREADINGORDER | FDTF_LONGDATE | FDTF_LONGTIME; 1793 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1794 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1795 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)); 1796 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); 1797 ok(lstrcmpA(buff3, buff + lstrlenA(buff) - lstrlenA(buff3)) == 0, 1798 "expected (%s), got (%s) for time part\n", 1799 buff3, buff + lstrlenA(buff) - lstrlenA(buff3)); 1800 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)); 1801 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1802 buff[lstrlenA(buff2)] = '\0'; 1803 ok(lstrcmpA(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", 1804 buff2, buff); 1805 1806 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_SHORTTIME; 1807 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1808 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1809 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); 1810 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1811 strcat(buff2, " "); 1812 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)); 1813 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); 1814 strcat(buff2, buff3); 1815 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1816 1817 flags = FDTF_NOAUTOREADINGORDER | FDTF_SHORTDATE | FDTF_LONGTIME; 1818 ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff)); 1819 ok(ret == lstrlenA(buff)+1, "got %d\n", ret); 1820 ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)); 1821 ok(ret == lstrlenA(buff2)+1, "got %d\n", ret); 1822 strcat(buff2, " "); 1823 ret = GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)); 1824 ok(ret == lstrlenA(buff3)+1, "got %d\n", ret); 1825 strcat(buff2, buff3); 1826 ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff); 1827 } 1828 1829 static void test_SHFormatDateTimeW(void) 1830 { 1831 FILETIME UNALIGNED filetime; 1832 WCHAR buff[100], buff2[100], buff3[100], *p1, *p2; 1833 SYSTEMTIME st; 1834 DWORD flags; 1835 INT ret; 1836 static const WCHAR spaceW[] = {' ',0}; 1837 #define UNICODE_LTR_MARK 0x200e 1838 #define UNICODE_RTL_MARK 0x200f 1839 1840 if (0) 1841 { 1842 /* crashes on native */ 1843 pSHFormatDateTimeW(NULL, NULL, NULL, 0); 1844 } 1845 1846 GetLocalTime(&st); 1847 SystemTimeToFileTime(&st, &filetime); 1848 /* SHFormatDateTime expects input as utc */ 1849 LocalFileTimeToFileTime(&filetime, &filetime); 1850 1851 /* no way to get required buffer length here */ 1852 SetLastError(0xdeadbeef); 1853 ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0); 1854 ok(ret == 0, "expected 0, got %d\n", ret); 1855 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1856 1857 SetLastError(0xdeadbeef); 1858 buff[0] = 'a'; buff[1] = 0; 1859 ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0); 1860 ok(ret == 0, "expected 0, got %d\n", ret); 1861 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1862 ok(buff[0] == 'a', "expected same string\n"); 1863 1864 /* all combinations documented as invalid succeeded */ 1865 flags = FDTF_SHORTTIME | FDTF_LONGTIME; 1866 SetLastError(0xdeadbeef); 1867 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1868 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1869 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1870 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1871 1872 flags = FDTF_SHORTDATE | FDTF_LONGDATE; 1873 SetLastError(0xdeadbeef); 1874 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1875 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1876 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1877 ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError()); 1878 1879 flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE; 1880 SetLastError(0xdeadbeef); 1881 buff[0] = 0; /* NT4 doesn't clear the buffer on failure */ 1882 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1883 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1884 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1885 ok(GetLastError() == 0xdeadbeef, 1886 "expected 0xdeadbeef, got %d\n", GetLastError()); 1887 1888 /* now check returned strings */ 1889 flags = FDTF_SHORTTIME; 1890 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1891 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1892 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1893 SetLastError(0xdeadbeef); 1894 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1895 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1896 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 1897 1898 flags = FDTF_LONGTIME; 1899 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1900 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1901 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1902 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1903 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1904 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 1905 1906 /* both time flags */ 1907 flags = FDTF_LONGTIME | FDTF_SHORTTIME; 1908 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1909 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1910 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1911 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1912 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1913 ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n"); 1914 1915 flags = FDTF_SHORTDATE; 1916 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1917 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1918 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1919 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1920 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1921 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 1922 1923 flags = FDTF_LONGDATE; 1924 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1925 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1926 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1927 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1928 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1929 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 1930 1931 /* both date flags */ 1932 flags = FDTF_LONGDATE | FDTF_SHORTDATE; 1933 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1934 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1935 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1936 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1937 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1938 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 1939 1940 /* various combinations of date/time flags */ 1941 flags = FDTF_LONGDATE | FDTF_SHORTTIME; 1942 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1943 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1944 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1945 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, ARRAY_SIZE(buff3)); 1946 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret); 1947 ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0, 1948 "expected (%s), got (%s) for time part\n", 1949 wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3))); 1950 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1951 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1952 p1 = buff; 1953 p2 = buff2; 1954 while (*p2 != '\0') 1955 { 1956 while (*p1 == UNICODE_LTR_MARK || *p1 == UNICODE_RTL_MARK) 1957 p1++; 1958 while (*p2 == UNICODE_LTR_MARK || *p2 == UNICODE_RTL_MARK) 1959 p2++; 1960 p1++; 1961 p2++; 1962 } 1963 *p1 = '\0'; 1964 ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", 1965 wine_dbgstr_w(buff2), wine_dbgstr_w(buff)); 1966 1967 flags = FDTF_LONGDATE | FDTF_LONGTIME; 1968 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1969 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1970 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1971 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, ARRAY_SIZE(buff3)); 1972 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret); 1973 ok(lstrcmpW(buff3, buff + lstrlenW(buff) - lstrlenW(buff3)) == 0, 1974 "expected (%s), got (%s) for time part\n", 1975 wine_dbgstr_w(buff3), wine_dbgstr_w(buff + lstrlenW(buff) - lstrlenW(buff3))); 1976 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1977 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1978 p1 = buff; 1979 p2 = buff2; 1980 while (*p2 != '\0') 1981 { 1982 while (*p1 == UNICODE_LTR_MARK || *p1 == UNICODE_RTL_MARK) 1983 p1++; 1984 while (*p2 == UNICODE_LTR_MARK || *p2 == UNICODE_RTL_MARK) 1985 p2++; 1986 p1++; 1987 p2++; 1988 } 1989 *p1 = '\0'; 1990 ok(lstrcmpW(buff2, buff) == 0, "expected (%s) got (%s) for date part\n", 1991 wine_dbgstr_w(buff2), wine_dbgstr_w(buff)); 1992 1993 flags = FDTF_SHORTDATE | FDTF_SHORTTIME; 1994 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 1995 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 1996 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 1997 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 1998 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 1999 lstrcatW(buff2, spaceW); 2000 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, ARRAY_SIZE(buff3)); 2001 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret); 2002 lstrcatW(buff2, buff3); 2003 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 2004 2005 flags = FDTF_SHORTDATE | FDTF_LONGTIME; 2006 ret = pSHFormatDateTimeW(&filetime, &flags, buff, ARRAY_SIZE(buff)); 2007 ok(ret == lstrlenW(buff)+1 || ret == lstrlenW(buff), 2008 "expected %d or %d, got %d\n", lstrlenW(buff)+1, lstrlenW(buff), ret); 2009 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, ARRAY_SIZE(buff2)); 2010 ok(ret == lstrlenW(buff2)+1, "expected %d, got %d\n", lstrlenW(buff2)+1, ret); 2011 lstrcatW(buff2, spaceW); 2012 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, ARRAY_SIZE(buff3)); 2013 ok(ret == lstrlenW(buff3)+1, "expected %d, got %d\n", lstrlenW(buff3)+1, ret); 2014 lstrcatW(buff2, buff3); 2015 ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n"); 2016 } 2017 2018 static void test_SHGetObjectCompatFlags(void) 2019 { 2020 struct compat_value { 2021 CHAR nameA[30]; 2022 DWORD value; 2023 }; 2024 2025 struct compat_value values[] = { 2026 { "OTNEEDSSFCACHE", 0x1 }, 2027 { "NO_WEBVIEW", 0x2 }, 2028 { "UNBINDABLE", 0x4 }, 2029 { "PINDLL", 0x8 }, 2030 { "NEEDSFILESYSANCESTOR", 0x10 }, 2031 { "NOTAFILESYSTEM", 0x20 }, 2032 { "CTXMENU_NOVERBS", 0x40 }, 2033 { "CTXMENU_LIMITEDQI", 0x80 }, 2034 { "COCREATESHELLFOLDERONLY", 0x100 }, 2035 { "NEEDSSTORAGEANCESTOR", 0x200 }, 2036 { "NOLEGACYWEBVIEW", 0x400 }, 2037 { "CTXMENU_XPQCMFLAGS", 0x1000 }, 2038 { "NOIPROPERTYSTORE", 0x2000 } 2039 }; 2040 2041 static const char compat_path[] = "Software\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Objects"; 2042 CHAR keyA[39]; /* {CLSID} */ 2043 HKEY root; 2044 DWORD ret; 2045 int i; 2046 2047 /* null args */ 2048 ret = pSHGetObjectCompatFlags(NULL, NULL); 2049 ok(ret == 0, "got %d\n", ret); 2050 2051 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, compat_path, &root); 2052 if (ret != ERROR_SUCCESS) 2053 { 2054 skip("No compatibility class data found\n"); 2055 return; 2056 } 2057 2058 for (i = 0; RegEnumKeyA(root, i, keyA, sizeof(keyA)) == ERROR_SUCCESS; i++) 2059 { 2060 HKEY clsid_key; 2061 2062 if (RegOpenKeyA(root, keyA, &clsid_key) == ERROR_SUCCESS) 2063 { 2064 CHAR valueA[30]; 2065 DWORD expected = 0, got, length = sizeof(valueA); 2066 CLSID clsid; 2067 int v; 2068 2069 for (v = 0; RegEnumValueA(clsid_key, v, valueA, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; v++) 2070 { 2071 int j; 2072 2073 for (j = 0; j < ARRAY_SIZE(values); j++) 2074 if (lstrcmpA(values[j].nameA, valueA) == 0) 2075 { 2076 expected |= values[j].value; 2077 break; 2078 } 2079 2080 length = sizeof(valueA); 2081 } 2082 2083 pGUIDFromStringA(keyA, &clsid); 2084 got = pSHGetObjectCompatFlags(NULL, &clsid); 2085 ok(got == expected, "got 0x%08x, expected 0x%08x. Key %s\n", got, expected, keyA); 2086 2087 RegCloseKey(clsid_key); 2088 } 2089 } 2090 2091 RegCloseKey(root); 2092 } 2093 2094 typedef struct { 2095 IOleCommandTarget IOleCommandTarget_iface; 2096 LONG ref; 2097 } IOleCommandTargetImpl; 2098 2099 static inline IOleCommandTargetImpl *impl_from_IOleCommandTarget(IOleCommandTarget *iface) 2100 { 2101 return CONTAINING_RECORD(iface, IOleCommandTargetImpl, IOleCommandTarget_iface); 2102 } 2103 2104 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl; 2105 2106 static IOleCommandTarget* IOleCommandTargetImpl_Construct(void) 2107 { 2108 IOleCommandTargetImpl *obj; 2109 2110 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); 2111 obj->IOleCommandTarget_iface.lpVtbl = &IOleCommandTargetImpl_Vtbl; 2112 obj->ref = 1; 2113 2114 return &obj->IOleCommandTarget_iface; 2115 } 2116 2117 static HRESULT WINAPI IOleCommandTargetImpl_QueryInterface(IOleCommandTarget *iface, REFIID riid, void **ppvObj) 2118 { 2119 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface); 2120 2121 if (IsEqualIID(riid, &IID_IUnknown) || 2122 IsEqualIID(riid, &IID_IOleCommandTarget)) 2123 { 2124 *ppvObj = This; 2125 } 2126 2127 if(*ppvObj) 2128 { 2129 IOleCommandTarget_AddRef(iface); 2130 return S_OK; 2131 } 2132 2133 return E_NOINTERFACE; 2134 } 2135 2136 static ULONG WINAPI IOleCommandTargetImpl_AddRef(IOleCommandTarget *iface) 2137 { 2138 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface); 2139 return InterlockedIncrement(&This->ref); 2140 } 2141 2142 static ULONG WINAPI IOleCommandTargetImpl_Release(IOleCommandTarget *iface) 2143 { 2144 IOleCommandTargetImpl *This = impl_from_IOleCommandTarget(iface); 2145 ULONG ref = InterlockedDecrement(&This->ref); 2146 2147 if (!ref) 2148 { 2149 HeapFree(GetProcessHeap(), 0, This); 2150 return 0; 2151 } 2152 return ref; 2153 } 2154 2155 static HRESULT WINAPI IOleCommandTargetImpl_QueryStatus( 2156 IOleCommandTarget *iface, const GUID *group, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText) 2157 { 2158 return E_NOTIMPL; 2159 } 2160 2161 static HRESULT WINAPI IOleCommandTargetImpl_Exec( 2162 IOleCommandTarget *iface, 2163 const GUID *CmdGroup, 2164 DWORD nCmdID, 2165 DWORD nCmdexecopt, 2166 VARIANT *pvaIn, 2167 VARIANT *pvaOut) 2168 { 2169 add_call(&trace_got, 3, CmdGroup, (void*)(DWORD_PTR)nCmdID, (void*)(DWORD_PTR)nCmdexecopt, pvaIn, pvaOut); 2170 return S_OK; 2171 } 2172 2173 static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl = 2174 { 2175 IOleCommandTargetImpl_QueryInterface, 2176 IOleCommandTargetImpl_AddRef, 2177 IOleCommandTargetImpl_Release, 2178 IOleCommandTargetImpl_QueryStatus, 2179 IOleCommandTargetImpl_Exec 2180 }; 2181 2182 typedef struct { 2183 IServiceProvider IServiceProvider_iface; 2184 LONG ref; 2185 } IServiceProviderImpl; 2186 2187 static inline IServiceProviderImpl *impl_from_IServiceProvider(IServiceProvider *iface) 2188 { 2189 return CONTAINING_RECORD(iface, IServiceProviderImpl, IServiceProvider_iface); 2190 } 2191 2192 typedef struct { 2193 IProfferService IProfferService_iface; 2194 LONG ref; 2195 } IProfferServiceImpl; 2196 2197 static inline IProfferServiceImpl *impl_from_IProfferService(IProfferService *iface) 2198 { 2199 return CONTAINING_RECORD(iface, IProfferServiceImpl, IProfferService_iface); 2200 } 2201 2202 2203 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl; 2204 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl; 2205 2206 static IServiceProvider* IServiceProviderImpl_Construct(void) 2207 { 2208 IServiceProviderImpl *obj; 2209 2210 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); 2211 obj->IServiceProvider_iface.lpVtbl = &IServiceProviderImpl_Vtbl; 2212 obj->ref = 1; 2213 2214 return &obj->IServiceProvider_iface; 2215 } 2216 2217 static IProfferService* IProfferServiceImpl_Construct(void) 2218 { 2219 IProfferServiceImpl *obj; 2220 2221 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj)); 2222 obj->IProfferService_iface.lpVtbl = &IProfferServiceImpl_Vtbl; 2223 obj->ref = 1; 2224 2225 return &obj->IProfferService_iface; 2226 } 2227 2228 static HRESULT WINAPI IServiceProviderImpl_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppvObj) 2229 { 2230 IServiceProviderImpl *This = impl_from_IServiceProvider(iface); 2231 2232 if (IsEqualIID(riid, &IID_IUnknown) || 2233 IsEqualIID(riid, &IID_IServiceProvider)) 2234 { 2235 *ppvObj = This; 2236 } 2237 2238 if(*ppvObj) 2239 { 2240 IServiceProvider_AddRef(iface); 2241 /* native uses redefined IID_IServiceProvider symbol, so we can't compare pointers */ 2242 if (IsEqualIID(riid, &IID_IServiceProvider)) 2243 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0); 2244 return S_OK; 2245 } 2246 2247 return E_NOINTERFACE; 2248 } 2249 2250 static ULONG WINAPI IServiceProviderImpl_AddRef(IServiceProvider *iface) 2251 { 2252 IServiceProviderImpl *This = impl_from_IServiceProvider(iface); 2253 return InterlockedIncrement(&This->ref); 2254 } 2255 2256 static ULONG WINAPI IServiceProviderImpl_Release(IServiceProvider *iface) 2257 { 2258 IServiceProviderImpl *This = impl_from_IServiceProvider(iface); 2259 ULONG ref = InterlockedDecrement(&This->ref); 2260 2261 if (!ref) 2262 { 2263 HeapFree(GetProcessHeap(), 0, This); 2264 return 0; 2265 } 2266 return ref; 2267 } 2268 2269 static HRESULT WINAPI IServiceProviderImpl_QueryService( 2270 IServiceProvider *iface, REFGUID service, REFIID riid, void **ppv) 2271 { 2272 /* native uses redefined pointer for IID_IOleCommandTarget, not one from uuid.lib */ 2273 if (IsEqualIID(riid, &IID_IOleCommandTarget)) 2274 { 2275 add_call(&trace_got, 2, iface, service, &IID_IOleCommandTarget, 0, 0); 2276 *ppv = IOleCommandTargetImpl_Construct(); 2277 } 2278 if (IsEqualIID(riid, &IID_IProfferService)) 2279 { 2280 if (IsEqualIID(service, &IID_IProfferService)) 2281 add_call(&trace_got, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0); 2282 *ppv = IProfferServiceImpl_Construct(); 2283 } 2284 return S_OK; 2285 } 2286 2287 static const IServiceProviderVtbl IServiceProviderImpl_Vtbl = 2288 { 2289 IServiceProviderImpl_QueryInterface, 2290 IServiceProviderImpl_AddRef, 2291 IServiceProviderImpl_Release, 2292 IServiceProviderImpl_QueryService 2293 }; 2294 2295 static void test_IUnknown_QueryServiceExec(void) 2296 { 2297 IServiceProvider *provider; 2298 static const GUID dummy_serviceid = { 0xdeadbeef }; 2299 static const GUID dummy_groupid = { 0xbeefbeef }; 2300 call_trace_t trace_expected; 2301 HRESULT hr; 2302 2303 provider = IServiceProviderImpl_Construct(); 2304 2305 /* null source pointer */ 2306 hr = pIUnknown_QueryServiceExec(NULL, &dummy_serviceid, &dummy_groupid, 0, 0, 0, 0); 2307 ok(hr == E_FAIL || 2308 hr == E_NOTIMPL, /* win 8 */ 2309 "got 0x%08x\n", hr); 2310 2311 /* expected trace: 2312 IUnknown_QueryServiceExec( ptr1, serviceid, groupid, arg1, arg2, arg3, arg4); 2313 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &prov ); 2314 -> IServiceProvider_QueryService( prov, serviceid, &IID_IOleCommandTarget, &obj ); 2315 -> IOleCommandTarget_Exec( obj, groupid, arg1, arg2, arg3, arg4 ); 2316 */ 2317 init_call_trace(&trace_expected); 2318 2319 add_call(&trace_expected, 1, provider, &IID_IServiceProvider, 0, 0, 0); 2320 add_call(&trace_expected, 2, provider, &dummy_serviceid, &IID_IOleCommandTarget, 0, 0); 2321 add_call(&trace_expected, 3, &dummy_groupid, (void*)0x1, (void*)0x2, (void*)0x3, (void*)0x4); 2322 2323 init_call_trace(&trace_got); 2324 hr = pIUnknown_QueryServiceExec((IUnknown*)provider, &dummy_serviceid, &dummy_groupid, 0x1, 0x2, (void*)0x3, (void*)0x4); 2325 ok(hr == S_OK, "got 0x%08x\n", hr); 2326 2327 ok_trace(&trace_expected, &trace_got); 2328 2329 free_call_trace(&trace_expected); 2330 free_call_trace(&trace_got); 2331 2332 IServiceProvider_Release(provider); 2333 } 2334 2335 2336 static HRESULT WINAPI IProfferServiceImpl_QueryInterface(IProfferService *iface, REFIID riid, void **ppvObj) 2337 { 2338 IProfferServiceImpl *This = impl_from_IProfferService(iface); 2339 2340 if (IsEqualIID(riid, &IID_IUnknown) || 2341 IsEqualIID(riid, &IID_IProfferService)) 2342 { 2343 *ppvObj = This; 2344 } 2345 else if (IsEqualIID(riid, &IID_IServiceProvider)) 2346 { 2347 *ppvObj = IServiceProviderImpl_Construct(); 2348 add_call(&trace_got, 1, iface, &IID_IServiceProvider, 0, 0, 0); 2349 return S_OK; 2350 } 2351 2352 if(*ppvObj) 2353 { 2354 IProfferService_AddRef(iface); 2355 return S_OK; 2356 } 2357 2358 return E_NOINTERFACE; 2359 } 2360 2361 static ULONG WINAPI IProfferServiceImpl_AddRef(IProfferService *iface) 2362 { 2363 IProfferServiceImpl *This = impl_from_IProfferService(iface); 2364 return InterlockedIncrement(&This->ref); 2365 } 2366 2367 static ULONG WINAPI IProfferServiceImpl_Release(IProfferService *iface) 2368 { 2369 IProfferServiceImpl *This = impl_from_IProfferService(iface); 2370 ULONG ref = InterlockedDecrement(&This->ref); 2371 2372 if (!ref) 2373 { 2374 HeapFree(GetProcessHeap(), 0, This); 2375 return 0; 2376 } 2377 return ref; 2378 } 2379 2380 static HRESULT WINAPI IProfferServiceImpl_ProfferService(IProfferService *iface, 2381 REFGUID service, IServiceProvider *pService, DWORD *pCookie) 2382 { 2383 *pCookie = 0xdeadbeef; 2384 add_call(&trace_got, 3, service, pService, pCookie, 0, 0); 2385 return S_OK; 2386 } 2387 2388 static HRESULT WINAPI IProfferServiceImpl_RevokeService(IProfferService *iface, DWORD cookie) 2389 { 2390 add_call(&trace_got, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0); 2391 return S_OK; 2392 } 2393 2394 static const IProfferServiceVtbl IProfferServiceImpl_Vtbl = 2395 { 2396 IProfferServiceImpl_QueryInterface, 2397 IProfferServiceImpl_AddRef, 2398 IProfferServiceImpl_Release, 2399 IProfferServiceImpl_ProfferService, 2400 IProfferServiceImpl_RevokeService 2401 }; 2402 2403 static void test_IUnknown_ProfferService(void) 2404 { 2405 IServiceProvider *provider; 2406 IProfferService *proff; 2407 static const GUID dummy_serviceid = { 0xdeadbeef }; 2408 call_trace_t trace_expected; 2409 HRESULT hr; 2410 DWORD cookie; 2411 2412 provider = IServiceProviderImpl_Construct(); 2413 proff = IProfferServiceImpl_Construct(); 2414 2415 /* null source pointer */ 2416 hr = pIUnknown_ProfferService(NULL, &dummy_serviceid, 0, 0); 2417 ok(hr == E_FAIL || 2418 hr == E_NOTIMPL, /* win 8 */ 2419 "got 0x%08x\n", hr); 2420 2421 /* expected trace: 2422 IUnknown_ProfferService( ptr1, serviceid, arg1, arg2); 2423 -> IUnknown_QueryInterface( ptr1, &IID_IServiceProvider, &provider ); 2424 -> IServiceProvider_QueryService( provider, &IID_IProfferService, &IID_IProfferService, &proffer ); 2425 2426 if (service pointer not null): 2427 -> IProfferService_ProfferService( proffer, serviceid, arg1, arg2 ); 2428 else 2429 -> IProfferService_RevokeService( proffer, *arg2 ); 2430 */ 2431 init_call_trace(&trace_expected); 2432 2433 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0); 2434 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0); 2435 add_call(&trace_expected, 3, &dummy_serviceid, provider, &cookie, 0, 0); 2436 2437 init_call_trace(&trace_got); 2438 cookie = 0; 2439 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, provider, &cookie); 2440 ok(hr == S_OK, "got 0x%08x\n", hr); 2441 ok(cookie == 0xdeadbeef, "got %x\n", cookie); 2442 2443 ok_trace(&trace_expected, &trace_got); 2444 free_call_trace(&trace_got); 2445 free_call_trace(&trace_expected); 2446 2447 /* same with ::Revoke path */ 2448 init_call_trace(&trace_expected); 2449 2450 add_call(&trace_expected, 1, proff, &IID_IServiceProvider, 0, 0, 0); 2451 add_call(&trace_expected, 2, &IID_IProfferService, &IID_IProfferService, 0, 0, 0); 2452 add_call(&trace_expected, 4, (void*)(DWORD_PTR)cookie, 0, 0, 0, 0); 2453 2454 init_call_trace(&trace_got); 2455 ok(cookie != 0, "got %x\n", cookie); 2456 hr = pIUnknown_ProfferService((IUnknown*)proff, &dummy_serviceid, 0, &cookie); 2457 ok(hr == S_OK, "got 0x%08x\n", hr); 2458 ok(cookie == 0, "got %x\n", cookie); 2459 ok_trace(&trace_expected, &trace_got); 2460 free_call_trace(&trace_got); 2461 free_call_trace(&trace_expected); 2462 2463 IServiceProvider_Release(provider); 2464 IProfferService_Release(proff); 2465 } 2466 2467 static void test_SHCreateWorkerWindowA(void) 2468 { 2469 WNDCLASSA cliA; 2470 char classA[20]; 2471 HWND hwnd; 2472 LONG_PTR ret; 2473 BOOL res; 2474 2475 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0); 2476 ok(hwnd != 0, "expected window\n"); 2477 2478 GetClassNameA(hwnd, classA, 20); 2479 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA); 2480 2481 ret = GetWindowLongPtrA(hwnd, 0); 2482 ok(ret == 0, "got %ld\n", ret); 2483 2484 /* class info */ 2485 memset(&cliA, 0, sizeof(cliA)); 2486 res = GetClassInfoA(GetModuleHandleA("shlwapi.dll"), "WorkerA", &cliA); 2487 ok(res, "failed to get class info\n"); 2488 ok(cliA.style == 0, "got 0x%08x\n", cliA.style); 2489 ok(cliA.cbClsExtra == 0, "got %d\n", cliA.cbClsExtra); 2490 ok(cliA.cbWndExtra == sizeof(LONG_PTR), "got %d\n", cliA.cbWndExtra); 2491 ok(cliA.lpszMenuName == 0, "got %s\n", cliA.lpszMenuName); 2492 2493 DestroyWindow(hwnd); 2494 2495 /* set extra bytes */ 2496 hwnd = pSHCreateWorkerWindowA(0, NULL, 0, 0, 0, 0xdeadbeef); 2497 ok(hwnd != 0, "expected window\n"); 2498 2499 GetClassNameA(hwnd, classA, 20); 2500 ok(lstrcmpA(classA, "WorkerA") == 0, "expected WorkerA class, got %s\n", classA); 2501 2502 ret = GetWindowLongPtrA(hwnd, 0); 2503 ok(ret == 0xdeadbeef, "got %ld\n", ret); 2504 2505 /* test exstyle */ 2506 ret = GetWindowLongA(hwnd, GWL_EXSTYLE); 2507 ok(ret == WS_EX_WINDOWEDGE || 2508 ret == (WS_EX_WINDOWEDGE|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret); 2509 2510 DestroyWindow(hwnd); 2511 2512 hwnd = pSHCreateWorkerWindowA(0, NULL, WS_EX_TOOLWINDOW, 0, 0, 0); 2513 ret = GetWindowLongA(hwnd, GWL_EXSTYLE); 2514 ok(ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW) || 2515 ret == (WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_LAYOUTRTL) /* systems with RTL locale */, "0x%08lx\n", ret); 2516 DestroyWindow(hwnd); 2517 } 2518 2519 static HRESULT WINAPI SF_QueryInterface(IShellFolder *iface, 2520 REFIID riid, void **ppv) 2521 { 2522 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */ 2523 ok(!IsEqualGUID(&IID_IShellFolder, riid), 2524 "Unexpected QI for IShellFolder\n"); 2525 return E_NOINTERFACE; 2526 } 2527 2528 static ULONG WINAPI SF_AddRef(IShellFolder *iface) 2529 { 2530 return 2; 2531 } 2532 2533 static ULONG WINAPI SF_Release(IShellFolder *iface) 2534 { 2535 return 1; 2536 } 2537 2538 static HRESULT WINAPI SF_ParseDisplayName(IShellFolder *iface, 2539 HWND owner, LPBC reserved, LPOLESTR displayName, ULONG *eaten, 2540 LPITEMIDLIST *idl, ULONG *attr) 2541 { 2542 ok(0, "Didn't expect ParseDisplayName\n"); 2543 return E_NOTIMPL; 2544 } 2545 2546 static HRESULT WINAPI SF_EnumObjects(IShellFolder *iface, 2547 HWND owner, SHCONTF flags, IEnumIDList **enm) 2548 { 2549 *enm = (IEnumIDList*)0xcafebabe; 2550 return S_OK; 2551 } 2552 2553 static HRESULT WINAPI SF_BindToObject(IShellFolder *iface, 2554 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj) 2555 { 2556 ok(0, "Didn't expect BindToObject\n"); 2557 return E_NOTIMPL; 2558 } 2559 2560 static HRESULT WINAPI SF_BindToStorage(IShellFolder *iface, 2561 LPCITEMIDLIST idl, LPBC reserved, REFIID riid, void **obj) 2562 { 2563 ok(0, "Didn't expect BindToStorage\n"); 2564 return E_NOTIMPL; 2565 } 2566 2567 static HRESULT WINAPI SF_CompareIDs(IShellFolder *iface, 2568 LPARAM lparam, LPCITEMIDLIST idl1, LPCITEMIDLIST idl2) 2569 { 2570 ok(0, "Didn't expect CompareIDs\n"); 2571 return E_NOTIMPL; 2572 } 2573 2574 static HRESULT WINAPI SF_CreateViewObject(IShellFolder *iface, 2575 HWND owner, REFIID riid, void **out) 2576 { 2577 ok(0, "Didn't expect CreateViewObject\n"); 2578 return E_NOTIMPL; 2579 } 2580 2581 static HRESULT WINAPI SF_GetAttributesOf(IShellFolder *iface, 2582 #ifdef __REACTOS__ 2583 UINT cidl, PCUITEMID_CHILD_ARRAY idl, SFGAOF *inOut) 2584 #else 2585 UINT cidl, LPCITEMIDLIST *idl, SFGAOF *inOut) 2586 #endif 2587 { 2588 ok(0, "Didn't expect GetAttributesOf\n"); 2589 return E_NOTIMPL; 2590 } 2591 2592 static HRESULT WINAPI SF_GetUIObjectOf(IShellFolder *iface, 2593 #ifdef __REACTOS__ 2594 HWND owner, UINT cidl, PCUITEMID_CHILD_ARRAY idls, REFIID riid, UINT *inOut, 2595 #else 2596 HWND owner, UINT cidl, LPCITEMIDLIST *idls, REFIID riid, UINT *inOut, 2597 #endif 2598 void **out) 2599 { 2600 ok(0, "Didn't expect GetUIObjectOf\n"); 2601 return E_NOTIMPL; 2602 } 2603 2604 static HRESULT WINAPI SF_GetDisplayNameOf(IShellFolder *iface, 2605 LPCITEMIDLIST idl, SHGDNF flags, STRRET *name) 2606 { 2607 ok(0, "Didn't expect GetDisplayNameOf\n"); 2608 return E_NOTIMPL; 2609 } 2610 2611 static HRESULT WINAPI SF_SetNameOf(IShellFolder *iface, 2612 HWND hwnd, LPCITEMIDLIST idl, LPCOLESTR name, SHGDNF flags, 2613 LPITEMIDLIST *idlOut) 2614 { 2615 ok(0, "Didn't expect SetNameOf\n"); 2616 return E_NOTIMPL; 2617 } 2618 2619 static IShellFolderVtbl ShellFolderVtbl = { 2620 SF_QueryInterface, 2621 SF_AddRef, 2622 SF_Release, 2623 SF_ParseDisplayName, 2624 SF_EnumObjects, 2625 SF_BindToObject, 2626 SF_BindToStorage, 2627 SF_CompareIDs, 2628 SF_CreateViewObject, 2629 SF_GetAttributesOf, 2630 SF_GetUIObjectOf, 2631 SF_GetDisplayNameOf, 2632 SF_SetNameOf 2633 }; 2634 2635 static IShellFolder ShellFolder = { &ShellFolderVtbl }; 2636 2637 static void test_SHIShellFolder_EnumObjects(void) 2638 { 2639 IEnumIDList *enm; 2640 HRESULT hres; 2641 IShellFolder *folder; 2642 2643 if(!pSHIShellFolder_EnumObjects){ /* win7 and later */ 2644 win_skip("SHIShellFolder_EnumObjects not available\n"); 2645 return; 2646 } 2647 2648 if(0){ 2649 /* NULL object crashes on Windows */ 2650 pSHIShellFolder_EnumObjects(NULL, NULL, 0, NULL); 2651 } 2652 2653 /* SHIShellFolder_EnumObjects doesn't QI the object for IShellFolder */ 2654 enm = (IEnumIDList*)0xdeadbeef; 2655 hres = pSHIShellFolder_EnumObjects(&ShellFolder, NULL, 0, &enm); 2656 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres); 2657 ok(enm == (IEnumIDList*)0xcafebabe, "Didn't get expected enumerator location, instead: %p\n", enm); 2658 2659 /* SHIShellFolder_EnumObjects isn't strict about the IShellFolder object */ 2660 hres = SHGetDesktopFolder(&folder); 2661 ok(hres == S_OK, "SHGetDesktopFolder failed: 0x%08x\n", hres); 2662 2663 enm = NULL; 2664 hres = pSHIShellFolder_EnumObjects(folder, NULL, 0, &enm); 2665 ok(hres == S_OK, "SHIShellFolder_EnumObjects failed: 0x%08x\n", hres); 2666 ok(enm != NULL, "Didn't get an enumerator\n"); 2667 if(enm) 2668 IEnumIDList_Release(enm); 2669 2670 IShellFolder_Release(folder); 2671 } 2672 2673 static BOOL write_inifile(LPCWSTR filename) 2674 { 2675 DWORD written; 2676 HANDLE file; 2677 2678 static const char data[] = 2679 "[TestApp]\r\n" 2680 "AKey=1\r\n" 2681 "AnotherKey=asdf\r\n"; 2682 2683 file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 2684 if(file == INVALID_HANDLE_VALUE) { 2685 win_skip("failed to create ini file at %s\n", wine_dbgstr_w(filename)); 2686 return FALSE; 2687 } 2688 2689 WriteFile(file, data, sizeof(data), &written, NULL); 2690 2691 CloseHandle(file); 2692 2693 return TRUE; 2694 } 2695 2696 #define verify_inifile(f, e) r_verify_inifile(__LINE__, f, e) 2697 static void r_verify_inifile(unsigned l, LPCWSTR filename, LPCSTR exp) 2698 { 2699 HANDLE file; 2700 CHAR buf[1024]; 2701 DWORD read; 2702 2703 file = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 2704 2705 if(file == INVALID_HANDLE_VALUE) 2706 return; 2707 2708 ReadFile(file, buf, sizeof(buf) * sizeof(CHAR), &read, NULL); 2709 buf[read] = '\0'; 2710 2711 CloseHandle(file); 2712 2713 ok_(__FILE__,l)(!strcmp(buf, exp), "Expected:\n%s\nGot:\n%s\n", exp, 2714 buf); 2715 } 2716 2717 static void test_SHGetIniString(void) 2718 { 2719 DWORD ret; 2720 WCHAR out[64] = {0}; 2721 2722 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0}; 2723 static const WCHAR AKeyW[] = {'A','K','e','y',0}; 2724 static const WCHAR AnotherKeyW[] = {'A','n','o','t','h','e','r','K','e','y',0}; 2725 static const WCHAR JunkKeyW[] = {'J','u','n','k','K','e','y',0}; 2726 static const WCHAR testpathW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0}; 2727 WCHAR pathW[MAX_PATH]; 2728 2729 lstrcpyW(pathW, testpathW); 2730 2731 if (!write_inifile(pathW)) 2732 return; 2733 2734 if(0){ 2735 /* these crash on Windows */ 2736 pSHGetIniStringW(NULL, NULL, NULL, 0, NULL); 2737 pSHGetIniStringW(NULL, AKeyW, out, ARRAY_SIZE(out), pathW); 2738 pSHGetIniStringW(TestAppW, AKeyW, NULL, ARRAY_SIZE(out), pathW); 2739 } 2740 2741 ret = pSHGetIniStringW(TestAppW, AKeyW, out, 0, pathW); 2742 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret); 2743 2744 /* valid arguments */ 2745 out[0] = 0; 2746 SetLastError(0xdeadbeef); 2747 ret = pSHGetIniStringW(TestAppW, NULL, out, ARRAY_SIZE(out), pathW); 2748 ok(ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret); 2749 ok(!lstrcmpW(out, AKeyW), "Expected %s, got: %s, %d\n", 2750 wine_dbgstr_w(AKeyW), wine_dbgstr_w(out), GetLastError()); 2751 2752 ret = pSHGetIniStringW(TestAppW, AKeyW, out, ARRAY_SIZE(out), pathW); 2753 ok(ret == 1, "SHGetIniStringW should have given 1, instead: %d\n", ret); 2754 ok(!strcmp_wa(out, "1"), "Expected L\"1\", got: %s\n", wine_dbgstr_w(out)); 2755 2756 ret = pSHGetIniStringW(TestAppW, AnotherKeyW, out, ARRAY_SIZE(out), pathW); 2757 ok(ret == 4, "SHGetIniStringW should have given 4, instead: %d\n", ret); 2758 ok(!strcmp_wa(out, "asdf"), "Expected L\"asdf\", got: %s\n", wine_dbgstr_w(out)); 2759 2760 out[0] = 1; 2761 ret = pSHGetIniStringW(TestAppW, JunkKeyW, out, ARRAY_SIZE(out), pathW); 2762 ok(ret == 0, "SHGetIniStringW should have given 0, instead: %d\n", ret); 2763 ok(*out == 0, "Expected L\"\", got: %s\n", wine_dbgstr_w(out)); 2764 2765 DeleteFileW(pathW); 2766 } 2767 2768 static void test_SHSetIniString(void) 2769 { 2770 BOOL ret; 2771 2772 static const WCHAR TestAppW[] = {'T','e','s','t','A','p','p',0}; 2773 static const WCHAR AnotherAppW[] = {'A','n','o','t','h','e','r','A','p','p',0}; 2774 static const WCHAR TestIniW[] = {'C',':','\\','t','e','s','t','.','i','n','i',0}; 2775 static const WCHAR AKeyW[] = {'A','K','e','y',0}; 2776 static const WCHAR NewKeyW[] = {'N','e','w','K','e','y',0}; 2777 static const WCHAR AValueW[] = {'A','V','a','l','u','e',0}; 2778 2779 if (!write_inifile(TestIniW)) 2780 return; 2781 2782 ret = pSHSetIniStringW(TestAppW, AKeyW, AValueW, TestIniW); 2783 ok(ret == TRUE, "SHSetIniStringW should not have failed\n"); 2784 todo_wine /* wine sticks an extra \r\n at the end of the file */ 2785 verify_inifile(TestIniW, "[TestApp]\r\nAKey=AValue\r\nAnotherKey=asdf\r\n"); 2786 2787 ret = pSHSetIniStringW(TestAppW, AKeyW, NULL, TestIniW); 2788 ok(ret == TRUE, "SHSetIniStringW should not have failed\n"); 2789 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n"); 2790 2791 ret = pSHSetIniStringW(AnotherAppW, NewKeyW, AValueW, TestIniW); 2792 ok(ret == TRUE, "SHSetIniStringW should not have failed\n"); 2793 verify_inifile(TestIniW, "[TestApp]\r\nAnotherKey=asdf\r\n[AnotherApp]\r\nNewKey=AValue\r\n"); 2794 2795 ret = pSHSetIniStringW(TestAppW, NULL, AValueW, TestIniW); 2796 ok(ret == TRUE, "SHSetIniStringW should not have failed\n"); 2797 verify_inifile(TestIniW, "[AnotherApp]\r\nNewKey=AValue\r\n"); 2798 2799 DeleteFileW(TestIniW); 2800 } 2801 2802 #ifndef __REACTOS__ 2803 enum _shellkey_flags { 2804 SHKEY_Root_HKCU = 0x1, 2805 SHKEY_Root_HKLM = 0x2, 2806 SHKEY_Key_Explorer = 0x00, 2807 SHKEY_Key_Shell = 0x10, 2808 SHKEY_Key_ShellNoRoam = 0x20, 2809 SHKEY_Key_Classes = 0x30, 2810 SHKEY_Subkey_Default = 0x0000, 2811 SHKEY_Subkey_ResourceName = 0x1000, 2812 SHKEY_Subkey_Handlers = 0x2000, 2813 SHKEY_Subkey_Associations = 0x3000, 2814 SHKEY_Subkey_Volatile = 0x4000, 2815 SHKEY_Subkey_MUICache = 0x5000, 2816 SHKEY_Subkey_FileExts = 0x6000 2817 }; 2818 #endif 2819 2820 static void test_SHGetShellKey(void) 2821 { 2822 static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 }; 2823 static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 }; 2824 2825 DWORD *alloc_data, data, size; 2826 HKEY hkey; 2827 HRESULT hres; 2828 2829 /* Vista+ limits SHKEY enumeration values */ 2830 SetLastError(0xdeadbeef); 2831 hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE); 2832 if (hkey) 2833 { 2834 /* Tests not working on Vista+ */ 2835 RegCloseKey(hkey); 2836 2837 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Classes, NULL, FALSE); 2838 ok(hkey != NULL, "hkey = NULL\n"); 2839 RegCloseKey(hkey); 2840 } 2841 2842 hkey = pSHGetShellKey(SHKEY_Root_HKCU|SHKEY_Key_Explorer, ShellFoldersW, FALSE); 2843 ok(hkey != NULL, "hkey = NULL\n"); 2844 RegCloseKey(hkey); 2845 2846 hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Explorer, ShellFoldersW, FALSE); 2847 ok(hkey != NULL, "hkey = NULL\n"); 2848 RegCloseKey(hkey); 2849 2850 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE); 2851 ok(hkey == NULL, "hkey != NULL\n"); 2852 2853 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE); 2854 ok(hkey != NULL, "Can't open key\n"); 2855 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n"); 2856 RegCloseKey(hkey); 2857 2858 hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE); 2859 if (!hkey && GetLastError() == ERROR_ACCESS_DENIED) 2860 { 2861 skip("Not authorized to create keys\n"); 2862 return; 2863 } 2864 ok(hkey != NULL, "Can't create key\n"); 2865 RegCloseKey(hkey); 2866 2867 size = sizeof(data); 2868 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size); 2869 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres); 2870 2871 data = 1234; 2872 hres = pSKSetValueW(SHKEY_Root_HKLM, WineTestW, NULL, REG_DWORD, &data, sizeof(DWORD)); 2873 ok(hres == S_OK, "hres = %x\n", hres); 2874 2875 size = 1; 2876 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, NULL, &size); 2877 ok(hres == S_OK, "hres = %x\n", hres); 2878 ok(size == sizeof(DWORD), "size = %d\n", size); 2879 2880 data = 0xdeadbeef; 2881 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size); 2882 ok(hres == S_OK, "hres = %x\n", hres); 2883 ok(size == sizeof(DWORD), "size = %d\n", size); 2884 ok(data == 1234, "data = %d\n", data); 2885 2886 hres = pSKAllocValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, (void**)&alloc_data, &size); 2887 ok(hres == S_OK, "hres= %x\n", hres); 2888 ok(size == sizeof(DWORD), "size = %d\n", size); 2889 if (SUCCEEDED(hres)) 2890 { 2891 ok(*alloc_data == 1234, "*alloc_data = %d\n", *alloc_data); 2892 LocalFree(alloc_data); 2893 } 2894 2895 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL); 2896 ok(hres == S_OK, "hres = %x\n", hres); 2897 2898 hres = pSKDeleteValueW(SHKEY_Root_HKLM, WineTestW, NULL); 2899 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres); 2900 2901 hres = pSKGetValueW(SHKEY_Root_HKLM, WineTestW, NULL, NULL, &data, &size); 2902 ok(hres == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hres = %x\n", hres); 2903 2904 hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE); 2905 ok(hkey != NULL, "Can't create key\n"); 2906 ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delete key\n"); 2907 RegCloseKey(hkey); 2908 } 2909 2910 static void init_pointers(void) 2911 { 2912 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord))) 2913 MAKEFUNC(SHAllocShared, 7); 2914 MAKEFUNC(SHLockShared, 8); 2915 MAKEFUNC(SHUnlockShared, 9); 2916 MAKEFUNC(SHFreeShared, 10); 2917 MAKEFUNC(SHMapHandle, 11); 2918 MAKEFUNC(GetAcceptLanguagesA, 14); 2919 MAKEFUNC(SHSetWindowBits, 165); 2920 MAKEFUNC(SHSetParentHwnd, 167); 2921 MAKEFUNC(ConnectToConnectionPoint, 168); 2922 MAKEFUNC(IUnknown_GetClassID, 175); 2923 MAKEFUNC(SHSearchMapInt, 198); 2924 MAKEFUNC(SHCreateWorkerWindowA, 257); 2925 MAKEFUNC(GUIDFromStringA, 269); 2926 MAKEFUNC(SHPackDispParams, 282); 2927 MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283); 2928 MAKEFUNC(IConnectionPoint_SimpleInvoke, 284); 2929 MAKEFUNC(SHGetIniStringW, 294); 2930 MAKEFUNC(SHSetIniStringW, 295); 2931 MAKEFUNC(SHFormatDateTimeA, 353); 2932 MAKEFUNC(SHFormatDateTimeW, 354); 2933 MAKEFUNC(SHIShellFolder_EnumObjects, 404); 2934 MAKEFUNC(GetShellSecurityDescriptor, 475); 2935 MAKEFUNC(SHGetObjectCompatFlags, 476); 2936 MAKEFUNC(IUnknown_QueryServiceExec, 484); 2937 MAKEFUNC(SHGetShellKey, 491); 2938 MAKEFUNC(SHPropertyBag_ReadLONG, 496); 2939 MAKEFUNC(IUnknown_ProfferService, 514); 2940 MAKEFUNC(SKGetValueW, 516); 2941 MAKEFUNC(SKSetValueW, 517); 2942 MAKEFUNC(SKDeleteValueW, 518); 2943 MAKEFUNC(SKAllocValueW, 519); 2944 #undef MAKEFUNC 2945 2946 pDllGetVersion = (void*)GetProcAddress(hShlwapi, "DllGetVersion"); 2947 } 2948 2949 static void test_SHSetParentHwnd(void) 2950 { 2951 HWND hwnd, hwnd2, ret; 2952 DWORD style; 2953 2954 hwnd = CreateWindowA("Button", "", WS_VISIBLE, 0, 0, 10, 10, NULL, NULL, NULL, NULL); 2955 ok(hwnd != NULL, "got %p\n", hwnd); 2956 2957 hwnd2 = CreateWindowA("Button", "", WS_VISIBLE | WS_CHILD, 0, 0, 10, 10, hwnd, NULL, NULL, NULL); 2958 ok(hwnd2 != NULL, "got %p\n", hwnd2); 2959 2960 /* null params */ 2961 ret = pSHSetParentHwnd(NULL, NULL); 2962 ok(ret == NULL, "got %p\n", ret); 2963 2964 /* set to no parent while already no parent present */ 2965 ret = GetParent(hwnd); 2966 ok(ret == NULL, "got %p\n", ret); 2967 style = GetWindowLongA(hwnd, GWL_STYLE); 2968 ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style); 2969 ret = pSHSetParentHwnd(hwnd, NULL); 2970 ok(ret == NULL, "got %p\n", ret); 2971 style = GetWindowLongA(hwnd, GWL_STYLE); 2972 ok((style & (WS_POPUP|WS_CHILD)) == 0, "got style 0x%08x\n", style); 2973 2974 /* reset to null parent from not null */ 2975 ret = GetParent(hwnd2); 2976 ok(ret == hwnd, "got %p\n", ret); 2977 style = GetWindowLongA(hwnd2, GWL_STYLE); 2978 ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style); 2979 ret = pSHSetParentHwnd(hwnd2, NULL); 2980 ok(ret == NULL, "got %p\n", ret); 2981 style = GetWindowLongA(hwnd2, GWL_STYLE); 2982 ok((style & (WS_POPUP|WS_CHILD)) == WS_POPUP, "got style 0x%08x\n", style); 2983 ret = GetParent(hwnd2); 2984 ok(ret == NULL, "got %p\n", ret); 2985 2986 /* set parent back */ 2987 style = GetWindowLongA(hwnd2, GWL_STYLE); 2988 SetWindowLongA(hwnd2, GWL_STYLE, style & ~(WS_CHILD|WS_POPUP)); 2989 style = GetWindowLongA(hwnd2, GWL_STYLE); 2990 ok((style & (WS_CHILD|WS_POPUP)) == 0, "got 0x%08x\n", style); 2991 2992 ret = pSHSetParentHwnd(hwnd2, hwnd); 2993 todo_wine ok(ret == NULL, "got %p\n", ret); 2994 2995 style = GetWindowLongA(hwnd2, GWL_STYLE); 2996 ok((style & (WS_POPUP|WS_CHILD)) == WS_CHILD, "got style 0x%08x\n", style); 2997 ret = GetParent(hwnd2); 2998 ok(ret == hwnd, "got %p\n", ret); 2999 3000 /* try to set same parent again */ 3001 /* with WS_POPUP */ 3002 style = GetWindowLongA(hwnd2, GWL_STYLE); 3003 SetWindowLongA(hwnd2, GWL_STYLE, style | WS_POPUP); 3004 ret = pSHSetParentHwnd(hwnd2, hwnd); 3005 todo_wine ok(ret == NULL, "got %p\n", ret); 3006 style = GetWindowLongA(hwnd2, GWL_STYLE); 3007 ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style); 3008 ret = GetParent(hwnd2); 3009 ok(ret == hwnd, "got %p\n", ret); 3010 3011 /* without WS_POPUP */ 3012 style = GetWindowLongA(hwnd2, GWL_STYLE); 3013 SetWindowLongA(hwnd2, GWL_STYLE, style | ~WS_POPUP); 3014 ret = pSHSetParentHwnd(hwnd2, hwnd); 3015 todo_wine ok(ret == hwnd, "got %p\n", ret); 3016 style = GetWindowLongA(hwnd2, GWL_STYLE); 3017 ok((style & (WS_CHILD|WS_POPUP)) == WS_CHILD, "got 0x%08x\n", style); 3018 ret = GetParent(hwnd2); 3019 ok(ret == hwnd, "got %p\n", ret); 3020 3021 DestroyWindow(hwnd); 3022 DestroyWindow(hwnd2); 3023 } 3024 3025 static HRESULT WINAPI testpersist_QI(IPersist *iface, REFIID riid, void **obj) 3026 { 3027 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPersist)) { 3028 *obj = iface; 3029 IPersist_AddRef(iface); 3030 return S_OK; 3031 } 3032 3033 *obj = NULL; 3034 return E_NOINTERFACE; 3035 } 3036 3037 static HRESULT WINAPI testpersist_QI2(IPersist *iface, REFIID riid, void **obj) 3038 { 3039 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPersistFolder)) { 3040 *obj = iface; 3041 IPersist_AddRef(iface); 3042 return S_OK; 3043 } 3044 3045 *obj = NULL; 3046 return E_NOINTERFACE; 3047 } 3048 3049 static ULONG WINAPI testpersist_AddRef(IPersist *iface) 3050 { 3051 return 2; 3052 } 3053 3054 static ULONG WINAPI testpersist_Release(IPersist *iface) 3055 { 3056 return 1; 3057 } 3058 3059 static HRESULT WINAPI testpersist_GetClassID(IPersist *iface, CLSID *clsid) 3060 { 3061 memset(clsid, 0xab, sizeof(*clsid)); 3062 return 0x8fff2222; 3063 } 3064 3065 static IPersistVtbl testpersistvtbl = { 3066 testpersist_QI, 3067 testpersist_AddRef, 3068 testpersist_Release, 3069 testpersist_GetClassID 3070 }; 3071 3072 static IPersistVtbl testpersist2vtbl = { 3073 testpersist_QI2, 3074 testpersist_AddRef, 3075 testpersist_Release, 3076 testpersist_GetClassID 3077 }; 3078 3079 static IPersist testpersist = { &testpersistvtbl }; 3080 static IPersist testpersist2 = { &testpersist2vtbl }; 3081 3082 static void test_IUnknown_GetClassID(void) 3083 { 3084 CLSID clsid, clsid2, clsid3; 3085 HRESULT hr; 3086 3087 if (0) /* crashes on native systems */ 3088 hr = pIUnknown_GetClassID(NULL, NULL); 3089 3090 memset(&clsid, 0xcc, sizeof(clsid)); 3091 memset(&clsid3, 0xcc, sizeof(clsid3)); 3092 hr = pIUnknown_GetClassID(NULL, &clsid); 3093 ok(hr == E_FAIL, "got 0x%08x\n", hr); 3094 ok(IsEqualCLSID(&clsid, &CLSID_NULL) || broken(IsEqualCLSID(&clsid, &clsid3)) /* win2k, winxp, win2k3 */, 3095 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 3096 3097 memset(&clsid, 0xcc, sizeof(clsid)); 3098 memset(&clsid2, 0xab, sizeof(clsid2)); 3099 hr = pIUnknown_GetClassID((IUnknown*)&testpersist, &clsid); 3100 ok(hr == 0x8fff2222, "got 0x%08x\n", hr); 3101 ok(IsEqualCLSID(&clsid, &clsid2) || broken(IsEqualCLSID(&clsid, &clsid3)) /* win2k3 */, 3102 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 3103 3104 /* IPersistFolder is also supported */ 3105 memset(&clsid, 0xcc, sizeof(clsid)); 3106 memset(&clsid2, 0xab, sizeof(clsid2)); 3107 memset(&clsid3, 0xcc, sizeof(clsid3)); 3108 hr = pIUnknown_GetClassID((IUnknown*)&testpersist2, &clsid); 3109 ok(hr == 0x8fff2222, "got 0x%08x\n", hr); 3110 ok(IsEqualCLSID(&clsid, &clsid2) || broken(IsEqualCLSID(&clsid, &clsid3)) /* win2k3 */, 3111 "got wrong clsid %s\n", wine_dbgstr_guid(&clsid)); 3112 } 3113 3114 static void test_DllGetVersion(void) 3115 { 3116 HRESULT hr; 3117 3118 hr = pDllGetVersion(NULL); 3119 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 3120 } 3121 3122 START_TEST(ordinal) 3123 { 3124 char **argv; 3125 int argc; 3126 3127 hShlwapi = GetModuleHandleA("shlwapi.dll"); 3128 3129 init_pointers(); 3130 3131 argc = winetest_get_mainargs(&argv); 3132 if (argc >= 4) 3133 { 3134 DWORD procid; 3135 HANDLE hmem; 3136 sscanf(argv[2], "%d", &procid); 3137 sscanf(argv[3], "%p", &hmem); 3138 test_alloc_shared_remote(procid, hmem); 3139 return; 3140 } 3141 3142 test_GetAcceptLanguagesA(); 3143 test_SHSearchMapInt(); 3144 test_alloc_shared(argc, argv); 3145 test_fdsa(); 3146 test_GetShellSecurityDescriptor(); 3147 test_SHPackDispParams(); 3148 test_IConnectionPoint(); 3149 test_SHPropertyBag_ReadLONG(); 3150 test_SHSetWindowBits(); 3151 test_SHFormatDateTimeA(); 3152 test_SHFormatDateTimeW(); 3153 test_SHGetObjectCompatFlags(); 3154 test_IUnknown_QueryServiceExec(); 3155 test_IUnknown_ProfferService(); 3156 test_SHCreateWorkerWindowA(); 3157 test_SHIShellFolder_EnumObjects(); 3158 test_SHGetIniString(); 3159 test_SHSetIniString(); 3160 test_SHGetShellKey(); 3161 test_SHSetParentHwnd(); 3162 test_IUnknown_GetClassID(); 3163 test_DllGetVersion(); 3164 } 3165