kernel32/tests/pipe: Enable compilation with long types.
[wine.git] / dlls / shcore / tests / shcore.c
blobaf6b3b392f37dd7f6840ab80bc8887467eb3822b
1 /*
2 * Copyright 2018 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include <windows.h>
24 #include "initguid.h"
25 #include "objidl.h"
26 #include "shlwapi.h"
28 #include "wine/test.h"
30 static HRESULT (WINAPI *pGetProcessReference)(IUnknown **);
31 static void (WINAPI *pSetProcessReference)(IUnknown *);
32 static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown **);
33 static int (WINAPI *pSHUnicodeToAnsi)(const WCHAR *, char *, int);
34 static int (WINAPI *pSHAnsiToUnicode)(const char *, WCHAR *, int);
35 static int (WINAPI *pSHAnsiToAnsi)(const char *, char *, int);
36 static int (WINAPI *pSHUnicodeToUnicode)(const WCHAR *, WCHAR *, int);
37 static HKEY (WINAPI *pSHRegDuplicateHKey)(HKEY);
38 static DWORD (WINAPI *pSHDeleteKeyA)(HKEY, const char *);
39 static DWORD (WINAPI *pSHGetValueA)(HKEY, const char *, const char *, DWORD *, void *, DWORD *);
40 static LSTATUS (WINAPI *pSHRegGetValueA)(HKEY, const char *, const char *, SRRF, DWORD *, void *, DWORD *);
41 static DWORD (WINAPI *pSHQueryValueExA)(HKEY, const char *, DWORD *, DWORD *, void *buff, DWORD *buff_len);
42 static DWORD (WINAPI *pSHRegGetPathA)(HKEY, const char *, const char *, char *, DWORD);
43 static DWORD (WINAPI *pSHCopyKeyA)(HKEY, const char *, HKEY, DWORD);
44 static HRESULT (WINAPI *pSHCreateStreamOnFileA)(const char *path, DWORD mode, IStream **stream);
45 static HRESULT (WINAPI *pIStream_Size)(IStream *stream, ULARGE_INTEGER *size);
47 /* Keys used for testing */
48 #define REG_TEST_KEY "Software\\Wine\\Test"
49 #define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
51 static const char test_path1[] = "%LONGSYSTEMVAR%\\subdir1";
52 static const char test_path2[] = "%FOO%\\subdir1";
54 static const char * test_envvar1 = "bar";
55 static const char * test_envvar2 = "ImARatherLongButIndeedNeededString";
56 static char test_exp_path1[MAX_PATH];
57 static char test_exp_path2[MAX_PATH];
58 static DWORD exp_len1;
59 static DWORD exp_len2;
60 static const char * initial_buffer ="0123456789";
62 static void init(HMODULE hshcore)
64 #define X(f) p##f = (void*)GetProcAddress(hshcore, #f)
65 X(GetProcessReference);
66 X(SetProcessReference);
67 X(SHUnicodeToAnsi);
68 X(SHAnsiToUnicode);
69 X(SHAnsiToAnsi);
70 X(SHUnicodeToUnicode);
71 X(SHRegDuplicateHKey);
72 X(SHDeleteKeyA);
73 X(SHGetValueA);
74 X(SHRegGetValueA);
75 X(SHQueryValueExA);
76 X(SHRegGetPathA);
77 X(SHCopyKeyA);
78 X(SHCreateStreamOnFileA);
79 X(IStream_Size);
80 #undef X
83 static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
85 if (IsEqualIID(riid, &IID_IUnknown))
87 *obj = iface;
88 IUnknown_AddRef(iface);
89 return S_OK;
92 *obj = NULL;
93 return E_NOINTERFACE;
96 struct test_unk
98 IUnknown IUnknown_iface;
99 LONG refcount;
102 static struct test_unk *impl_from_IUnknown(IUnknown *iface)
104 return CONTAINING_RECORD(iface, struct test_unk, IUnknown_iface);
107 static ULONG WINAPI unk_AddRef(IUnknown *iface)
109 struct test_unk *obj = impl_from_IUnknown(iface);
110 return InterlockedIncrement(&obj->refcount);
113 static ULONG WINAPI unk_Release(IUnknown *iface)
115 struct test_unk *obj = impl_from_IUnknown(iface);
116 return InterlockedDecrement(&obj->refcount);
119 static const IUnknownVtbl testunkvtbl =
121 unk_QI,
122 unk_AddRef,
123 unk_Release,
126 static void test_unk_init(struct test_unk *testunk)
128 testunk->IUnknown_iface.lpVtbl = &testunkvtbl;
129 testunk->refcount = 1;
132 static void test_process_reference(void)
134 struct test_unk test_unk, test_unk2;
135 IUnknown *obj;
136 HMODULE hmod;
137 HRESULT hr;
139 obj = (void *)0xdeadbeef;
140 hr = pGetProcessReference(&obj);
141 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
142 ok(obj == NULL, "Unexpected pointer.\n");
144 test_unk_init(&test_unk);
145 test_unk_init(&test_unk2);
147 pSetProcessReference(&test_unk.IUnknown_iface);
148 ok(test_unk.refcount == 1, "Unexpected refcount %lu.\n", test_unk.refcount);
149 pSetProcessReference(&test_unk2.IUnknown_iface);
150 ok(test_unk.refcount == 1, "Unexpected refcount %lu.\n", test_unk.refcount);
151 ok(test_unk2.refcount == 1, "Unexpected refcount %lu.\n", test_unk2.refcount);
153 hr = pGetProcessReference(&obj);
154 ok(hr == S_OK, "Failed to get reference, hr %#lx.\n", hr);
155 ok(obj == &test_unk2.IUnknown_iface, "Unexpected pointer.\n");
156 ok(test_unk2.refcount == 2, "Unexpected refcount %lu.\n", test_unk2.refcount);
158 hmod = LoadLibraryA("shell32.dll");
160 pSHGetInstanceExplorer = (void *)GetProcAddress(hmod, "SHGetInstanceExplorer");
161 hr = pSHGetInstanceExplorer(&obj);
162 ok(hr == S_OK, "Failed to get reference, hr %#lx.\n", hr);
163 ok(obj == &test_unk2.IUnknown_iface, "Unexpected pointer.\n");
164 ok(test_unk2.refcount == 3, "Unexpected refcount %lu.\n", test_unk2.refcount);
167 static void test_SHUnicodeToAnsi(void)
169 char buff[16];
170 int ret;
172 ret = pSHUnicodeToAnsi(NULL, NULL, 0);
173 ok(ret == 0, "Unexpected return value %d.\n", ret);
175 strcpy(buff, "abc");
176 ret = pSHUnicodeToAnsi(NULL, buff, 2);
177 ok(ret == 1, "Unexpected return value %d.\n", ret);
178 ok(buff[0] == 0 && buff[1] == 'b', "Unexpected buffer contents.\n");
180 buff[0] = 1;
181 ret = pSHUnicodeToAnsi(NULL, buff, 0);
182 ok(ret == 0, "Unexpected return value %d.\n", ret);
183 ok(buff[0] == 1, "Unexpected buffer contents.\n");
185 buff[0] = 1;
186 strcpy(buff, "test");
187 ret = pSHUnicodeToAnsi(L"", buff, 1);
188 ok(ret == 1, "Unexpected return value %d.\n", ret);
189 ok(*buff == 0, "Unexpected buffer contents.\n");
191 buff[0] = 1;
192 ret = pSHUnicodeToAnsi(L"test", buff, 0);
193 ok(ret == 0, "Unexpected return value %d.\n", ret);
194 ok(buff[0] == 1, "Unexpected buffer contents.\n");
196 buff[0] = 1;
197 ret = pSHUnicodeToAnsi(L"test", buff, 1);
198 ok(ret == 1, "Unexpected return value %d.\n", ret);
199 ok(*buff == 0, "Unexpected buffer contents.\n");
201 ret = pSHUnicodeToAnsi(L"test", buff, 16);
202 ok(ret == 5, "Unexpected return value %d.\n", ret);
203 ok(!strcmp(buff, "test"), "Unexpected buffer contents.\n");
205 ret = pSHUnicodeToAnsi(L"test", buff, 2);
206 ok(ret == 2, "Unexpected return value %d.\n", ret);
207 ok(!strcmp(buff, "t"), "Unexpected buffer contents.\n");
210 static void test_SHAnsiToUnicode(void)
212 WCHAR buffW[16];
213 int ret;
215 ret = pSHAnsiToUnicode(NULL, NULL, 0);
216 ok(ret == 0, "Unexpected return value %d.\n", ret);
218 buffW[0] = 1;
219 buffW[1] = 2;
220 ret = pSHAnsiToUnicode(NULL, buffW, 2);
221 ok(ret == 1, "Unexpected return value %d.\n", ret);
222 ok(buffW[0] == 0 && buffW[1] == 2, "Unexpected buffer contents.\n");
224 buffW[0] = 1;
225 ret = pSHAnsiToUnicode(NULL, buffW, 0);
226 ok(ret == 0, "Unexpected return value %d.\n", ret);
227 ok(buffW[0] == 1, "Unexpected buffer contents.\n");
229 buffW[0] = 1;
230 ret = pSHAnsiToUnicode("", buffW, 1);
231 ok(ret == 1, "Unexpected return value %d.\n", ret);
232 ok(*buffW == 0, "Unexpected buffer contents.\n");
234 buffW[0] = 1;
235 ret = pSHAnsiToUnicode("test", buffW, 0);
236 ok(ret == 0, "Unexpected return value %d.\n", ret);
237 ok(buffW[0] == 1, "Unexpected buffer contents.\n");
239 buffW[0] = 1;
240 ret = pSHAnsiToUnicode("test", buffW, 1);
241 ok(ret == 1, "Unexpected return value %d.\n", ret);
242 ok(*buffW == 0, "Unexpected buffer contents.\n");
244 ret = pSHAnsiToUnicode("test", buffW, 16);
245 ok(ret == 5, "Unexpected return value %d.\n", ret);
246 ok(!lstrcmpW(buffW, L"test"), "Unexpected buffer contents.\n");
248 ret = pSHAnsiToUnicode("test", buffW, 2);
249 ok(ret == 2, "Unexpected return value %d.\n", ret);
250 ok(buffW[0] == 't' && buffW[1] == 0, "Unexpected buffer contents.\n");
253 static void test_SHAnsiToAnsi(void)
255 char buff[16];
256 int ret;
258 ret = pSHAnsiToAnsi(NULL, NULL, 0);
259 ok(ret == 0, "Unexpected return value %d.\n", ret);
261 strcpy(buff, "abcdefghijklm");
262 ret = pSHAnsiToAnsi("test", buff, 3);
263 ok(ret == 0, "Unexpected return value %d.\n", ret);
264 ok(!strcmp(buff, "te"), "Unexpected buffer contents.\n");
265 ok(buff[3] == 'd', "Unexpected buffer contents.\n");
267 strcpy(buff, "abcdefghijklm");
268 ret = pSHAnsiToAnsi("", buff, 3);
269 ok(ret == 1, "Unexpected return value %d.\n", ret);
270 ok(!*buff, "Unexpected buffer contents.\n");
271 ok(buff[3] == 'd', "Unexpected buffer contents.\n");
273 strcpy(buff, "abcdefghijklm");
274 ret = pSHAnsiToAnsi("test", buff, 4);
275 ok(ret == 0, "Unexpected return value %d.\n", ret);
276 ok(!strcmp(buff, "tes"), "Unexpected buffer contents.\n");
277 ok(buff[4] == 'e', "Unexpected buffer contents.\n");
279 strcpy(buff, "abcdefghijklm");
280 ret = pSHAnsiToAnsi("test", buff, 5);
281 ok(ret == 5, "Unexpected return value %d.\n", ret);
282 ok(!strcmp(buff, "test"), "Unexpected buffer contents.\n");
283 ok(buff[5] == 'f', "Unexpected buffer contents.\n");
285 strcpy(buff, "abcdefghijklm");
286 ret = pSHAnsiToAnsi("test", buff, 6);
287 ok(ret == 5, "Unexpected return value %d.\n", ret);
288 ok(!strcmp(buff, "test"), "Unexpected buffer contents.\n");
289 ok(buff[5] == 'f', "Unexpected buffer contents.\n");
292 static void test_SHUnicodeToUnicode(void)
294 WCHAR buff[16];
295 int ret;
297 ret = pSHUnicodeToUnicode(NULL, NULL, 0);
298 ok(ret == 0, "Unexpected return value %d.\n", ret);
300 lstrcpyW(buff, L"abcdefghiklm");
301 ret = pSHUnicodeToUnicode(L"test", buff, 3);
302 ok(ret == 0, "Unexpected return value %d.\n", ret);
303 ok(!memcmp(buff, L"test", 2 * sizeof(WCHAR)) && !buff[2], "Unexpected buffer contents.\n");
304 ok(buff[3] == 'd', "Unexpected buffer contents.\n");
306 lstrcpyW(buff, L"abcdefghiklm");
307 ret = pSHUnicodeToUnicode(L"", buff, 3);
308 ok(ret == 1, "Unexpected return value %d.\n", ret);
309 ok(!*buff, "Unexpected buffer contents.\n");
310 ok(buff[3] == 'd', "Unexpected buffer contents.\n");
312 lstrcpyW(buff, L"abcdefghiklm");
313 ret = pSHUnicodeToUnicode(L"test", buff, 4);
314 ok(ret == 0, "Unexpected return value %d.\n", ret);
315 ok(!memcmp(buff, L"test", 3 * sizeof(WCHAR)) && !buff[3], "Unexpected buffer contents.\n");
316 ok(buff[4] == 'e', "Unexpected buffer contents.\n");
318 lstrcpyW(buff, L"abcdefghiklm");
319 ret = pSHUnicodeToUnicode(L"test", buff, 5);
320 ok(ret == 5, "Unexpected return value %d.\n", ret);
321 ok(!lstrcmpW(buff, L"test"), "Unexpected buffer contents.\n");
322 ok(buff[5] == 'f', "Unexpected buffer contents.\n");
324 lstrcpyW(buff, L"abcdefghiklm");
325 ret = pSHUnicodeToUnicode(L"test", buff, 6);
326 ok(ret == 5, "Unexpected return value %d.\n", ret);
327 ok(!lstrcmpW(buff, L"test"), "Unexpected buffer contents.\n");
328 ok(buff[5] == 'f', "Unexpected buffer contents.\n");
331 static void test_SHRegDuplicateHKey(void)
333 HKEY hkey, hkey2;
334 DWORD ret;
336 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey);
337 ok(!ret, "Failed to create test key, ret %ld.\n", ret);
339 hkey2 = pSHRegDuplicateHKey(hkey);
340 ok(hkey2 != NULL && hkey2 != hkey, "Unexpected duplicate key.\n");
342 RegCloseKey(hkey2);
343 RegCloseKey(hkey);
345 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
348 static void test_SHDeleteKey(void)
350 HKEY hkey, hkey2;
351 DWORD ret;
353 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey);
354 ok(!ret, "Failed to create test key, %ld.\n", ret);
356 ret = RegCreateKeyA(hkey, "delete_key", &hkey2);
357 ok(!ret, "Failed to create test key, %ld.\n", ret);
358 RegCloseKey(hkey2);
360 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
361 ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %ld.\n", ret);
363 ret = pSHDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
364 ok(!ret, "Unexpected retval %lu.\n", ret);
366 ret = RegCloseKey(hkey);
367 ok(!ret, "Unexpected retval %lu.\n", ret);
370 static HKEY create_test_entries(void)
372 HKEY hKey;
373 DWORD ret;
374 DWORD nExpectedLen1, nExpectedLen2;
376 SetEnvironmentVariableA("LONGSYSTEMVAR", test_envvar1);
377 SetEnvironmentVariableA("FOO", test_envvar2);
379 ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY, &hKey);
380 ok(!ret, "Unexpected retval %lu.\n", ret);
382 if (hKey)
384 ok(!RegSetValueExA(hKey, "Test1", 0, REG_EXPAND_SZ, (BYTE *)test_path1, strlen(test_path1)+1), "RegSetValueExA failed\n");
385 ok(!RegSetValueExA(hKey, "Test2", 0, REG_SZ, (BYTE *)test_path1, strlen(test_path1)+1), "RegSetValueExA failed\n");
386 ok(!RegSetValueExA(hKey, "Test3", 0, REG_EXPAND_SZ, (BYTE *)test_path2, strlen(test_path2)+1), "RegSetValueExA failed\n");
389 exp_len1 = ExpandEnvironmentStringsA(test_path1, test_exp_path1, sizeof(test_exp_path1));
390 exp_len2 = ExpandEnvironmentStringsA(test_path2, test_exp_path2, sizeof(test_exp_path2));
392 nExpectedLen1 = strlen(test_path1) - strlen("%LONGSYSTEMVAR%") + strlen(test_envvar1) + 1;
393 nExpectedLen2 = strlen(test_path2) - strlen("%FOO%") + strlen(test_envvar2) + 1;
395 /* Make sure we carry on with correct values */
396 exp_len1 = nExpectedLen1;
397 exp_len2 = nExpectedLen2;
399 return hKey;
402 /* delete key and all its subkeys */
403 static DWORD delete_key( HKEY hkey, LPCSTR parent, LPCSTR keyname )
405 HKEY parentKey;
406 DWORD ret;
408 RegCloseKey(hkey);
410 /* open the parent of the key to close */
411 ret = RegOpenKeyExA( HKEY_CURRENT_USER, parent, 0, KEY_ALL_ACCESS, &parentKey);
412 if (ret != ERROR_SUCCESS)
413 return ret;
415 ret = pSHDeleteKeyA( parentKey, keyname );
416 RegCloseKey(parentKey);
418 return ret;
421 static void test_SHGetValue(void)
423 DWORD size;
424 DWORD type;
425 DWORD ret;
426 char buf[MAX_PATH];
428 HKEY hkey = create_test_entries();
430 strcpy(buf, initial_buffer);
431 size = MAX_PATH;
432 type = -1;
433 ret = pSHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", &type, buf, &size);
434 ok(!ret, "Failed to get value, ret %lu.\n", ret);
436 ok(!strcmp(test_exp_path1, buf), "Unexpected value %s.\n", buf);
437 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
439 strcpy(buf, initial_buffer);
440 size = MAX_PATH;
441 type = -1;
442 ret = pSHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", &type, buf, &size);
443 ok(!ret, "Failed to get value, ret %lu.\n", ret);
444 ok(!strcmp(test_path1, buf), "Unexpected value %s.\n", buf);
445 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
447 delete_key(hkey, "Software\\Wine", "Test");
450 static void test_SHRegGetValue(void)
452 LSTATUS ret;
453 DWORD size, type;
454 char data[MAX_PATH];
456 HKEY hkey = create_test_entries();
458 size = MAX_PATH;
459 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_EXPAND_SZ, &type, data, &size);
460 ok(ret == ERROR_INVALID_PARAMETER, "Unexpected retval %lu.\n", ret);
462 size = MAX_PATH;
463 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_SZ, &type, data, &size);
464 ok(!ret, "Unexpected retval %lu.\n", ret);
465 ok(!strcmp(data, test_exp_path1), "data = %s, expected %s\n", data, test_exp_path1);
466 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
468 size = MAX_PATH;
469 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_DWORD, &type, data, &size);
470 ok(ret == ERROR_UNSUPPORTED_TYPE, "Unexpected retval %lu.\n", ret);
472 size = MAX_PATH;
473 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_EXPAND_SZ, &type, data, &size);
474 ok(ret == ERROR_INVALID_PARAMETER, "Unexpected retval %lu.\n", ret);
476 size = MAX_PATH;
477 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_SZ, &type, data, &size);
478 ok(!ret, "Unexpected retval %lu.\n", ret);
479 ok(!strcmp(data, test_path1), "data = %s, expected %s\n", data, test_path1);
480 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
482 size = MAX_PATH;
483 ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_QWORD, &type, data, &size);
484 ok(ret == ERROR_UNSUPPORTED_TYPE, "Unexpected retval %lu.\n", ret);
486 delete_key(hkey, "Software\\Wine", "Test");
489 static void test_SHQueryValueEx(void)
491 DWORD buffer_len1,buffer_len2;
492 DWORD ret, type, size;
493 char buf[MAX_PATH];
494 HKEY hKey, testkey;
496 testkey = create_test_entries();
498 ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_KEY, 0, KEY_QUERY_VALUE, &hKey);
499 ok(!ret, "Failed to open a key, ret %lu.\n", ret);
501 /****** SHQueryValueExA ******/
503 buffer_len1 = max(strlen(test_exp_path1)+1, strlen(test_path1)+1);
504 buffer_len2 = max(strlen(test_exp_path2)+1, strlen(test_path2)+1);
507 * Case 1.1 All arguments are NULL
509 ret = pSHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, NULL);
510 ok(!ret, "Failed to query value, ret %lu.\n", ret);
513 * Case 1.2 dwType is set
515 type = -1;
516 ret = pSHQueryValueExA( hKey, "Test1", NULL, &type, NULL, NULL);
517 ok(!ret, "Failed to query value, ret %lu.\n", ret);
518 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
520 size = 6;
521 ret = pSHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, &size);
522 ok(!ret, "Failed to query value, ret %lu.\n", ret);
523 ok(size == buffer_len1, "Buffer sizes %lu and %lu are not equal\n", size, buffer_len1);
526 * Expanded > unexpanded
528 size = 6;
529 ret = pSHQueryValueExA( hKey, "Test3", NULL, NULL, NULL, &size);
530 ok(!ret, "Failed to query value, ret %lu.\n", ret);
531 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
534 * Case 1 string shrinks during expanding
536 strcpy(buf, initial_buffer);
537 size = 6;
538 type = -1;
539 ret = pSHQueryValueExA( hKey, "Test1", NULL, &type, buf, &size);
540 ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
541 ok(!strcmp(initial_buffer, buf), "Comparing (%s) with (%s) failed\n", buf, initial_buffer);
542 ok(size == buffer_len1, "Buffer sizes %lu and %lu are not equal\n", size, buffer_len1);
543 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
546 * string grows during expanding
547 * dwSize is smaller than the size of the unexpanded string
549 strcpy(buf, initial_buffer);
550 size = 6;
551 type = -1;
552 ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size);
553 ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
554 ok(!strcmp(initial_buffer, buf), "Comparing (%s) with (%s) failed\n", buf, initial_buffer);
555 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
556 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
559 * string grows during expanding
560 * dwSize is larger than the size of the unexpanded string, but
561 * smaller than the part before the backslash. If the unexpanded
562 * string fits into the buffer, it can get cut when expanded.
564 strcpy(buf, initial_buffer);
565 size = strlen(test_envvar2) - 2;
566 type = -1;
567 ret = pSHQueryValueExA(hKey, "Test3", NULL, &type, buf, &size);
568 ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
570 todo_wine
572 ok(!strcmp("", buf), "Unexpanded string %s.\n", buf);
575 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
576 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
579 * string grows during expanding
580 * dwSize is larger than the size of the part before the backslash,
581 * but smaller than the expanded string. If the unexpanded string fits
582 * into the buffer, it can get cut when expanded.
584 strcpy(buf, initial_buffer);
585 size = exp_len2 - 4;
586 type = -1;
587 ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size);
588 ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
590 todo_wine
592 ok( (0 == strcmp("", buf)) || (0 == strcmp(test_envvar2, buf)),
593 "Expected empty or first part of the string \"%s\", got \"%s\"\n", test_envvar2, buf);
596 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
597 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
600 * The buffer is NULL but the size is set
602 strcpy(buf, initial_buffer);
603 size = 6;
604 type = -1;
605 ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, NULL, &size);
606 ok(!ret, "Failed to query value, ret %lu.\n", ret);
607 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
608 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
610 RegCloseKey(hKey);
612 delete_key(testkey, "Software\\Wine", "Test");
615 static void test_SHRegGetPath(void)
617 char buf[MAX_PATH];
618 DWORD ret;
619 HKEY hkey;
621 hkey = create_test_entries();
623 strcpy(buf, initial_buffer);
624 ret = pSHRegGetPathA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", buf, 0);
625 ok(!ret, "Failed to get path, ret %lu.\n", ret);
626 ok(!strcmp(test_exp_path1, buf), "Unexpected path %s.\n", buf);
628 delete_key(hkey, "Software\\Wine", "Test");
631 static void test_SHCopyKey(void)
633 HKEY hKeySrc, hKeyDst;
634 DWORD ret;
636 HKEY hkey = create_test_entries();
638 /* Delete existing destination sub keys */
639 hKeyDst = NULL;
640 if (!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst) && hKeyDst)
642 pSHDeleteKeyA(hKeyDst, NULL);
643 RegCloseKey(hKeyDst);
646 hKeyDst = NULL;
647 ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst);
648 ok(!ret, "Failed to create a test key, ret %ld.\n", ret);
650 hKeySrc = NULL;
651 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_CURRENT_VERSION, &hKeySrc);
652 ok(!ret, "Failed to open a test key, ret %ld.\n", ret);
654 ret = pSHCopyKeyA(hKeySrc, NULL, hKeyDst, 0);
655 ok(!ret, "Copy failed, ret %lu.\n", ret);
657 RegCloseKey(hKeySrc);
658 RegCloseKey(hKeyDst);
660 /* Check we copied the sub keys, i.e. something that's on every windows system (including Wine) */
661 hKeyDst = NULL;
662 ret = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination\\Shell Folders", &hKeyDst);
663 ok(!ret, "Failed to open a test key, ret %ld.\n", ret);
665 /* And the we copied the values too */
666 ok(!pSHQueryValueExA(hKeyDst, "Common AppData", NULL, NULL, NULL, NULL), "SHQueryValueExA failed\n");
668 RegCloseKey(hKeyDst);
669 delete_key( hkey, "Software\\Wine", "Test" );
672 #define CHECK_FILE_SIZE(filename,exp_size) _check_file_size(filename, exp_size, __LINE__)
673 static void _check_file_size(const CHAR *filename, LONG exp_size, int line)
675 HANDLE handle;
676 DWORD file_size = 0xdeadbeef;
677 handle = CreateFileA(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
678 file_size = GetFileSize(handle, NULL);
679 ok_(__FILE__,line)(file_size == exp_size, "got wrong file size: %ld.\n", file_size);
680 CloseHandle(handle);
683 #define CHECK_STREAM_SIZE(obj,exp_size) _check_stream_size(obj, exp_size, __LINE__)
684 static void _check_stream_size(IStream *obj, LONG exp_size, int line)
686 ULARGE_INTEGER stream_size;
687 STATSTG stat;
688 HRESULT hr;
689 stream_size.QuadPart = 0xdeadbeef;
690 hr = pIStream_Size(obj, &stream_size);
691 ok_(__FILE__,line)(hr == S_OK, "IStream_Size failed: hr %#lx.\n", hr);
692 ok_(__FILE__,line)(stream_size.QuadPart == exp_size, "Size(): got wrong size of stream: %s.\n",
693 wine_dbgstr_longlong(stream_size.QuadPart));
694 hr = IStream_Stat(obj, &stat, STATFLAG_NONAME);
695 ok_(__FILE__,line)(hr == S_OK, "IStream_Stat failed: hr %#lx.\n", hr);
696 ok_(__FILE__,line)(stat.cbSize.QuadPart == exp_size, "Stat(): got wrong size of stream: %s.\n",
697 wine_dbgstr_longlong(stat.cbSize.QuadPart));
700 #define CHECK_STREAM_POS(obj,exp_pos) _check_stream_pos(obj, exp_pos, __LINE__)
701 static void _check_stream_pos(IStream *obj, LONG exp_pos, int line)
703 LARGE_INTEGER move;
704 ULARGE_INTEGER pos;
705 HRESULT hr;
706 move.QuadPart = 0;
707 pos.QuadPart = 0xdeadbeef;
708 hr = IStream_Seek(obj, move, STREAM_SEEK_CUR, &pos);
709 ok_(__FILE__,line)(hr == S_OK, "IStream_Seek failed: hr %#lx.\n", hr);
710 ok_(__FILE__,line)(pos.QuadPart == exp_pos, "got wrong position: %s.\n",
711 wine_dbgstr_longlong(pos.QuadPart));
714 static void test_stream_size(void)
716 static const byte test_data[] = {0x1,0x2,0x3,0x4,0x5,0x6};
717 static const CHAR filename[] = "test_file";
718 IStream *stream, *stream2;
719 HANDLE handle;
720 DWORD written = 0;
721 ULARGE_INTEGER stream_size;
722 HRESULT hr;
724 handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
725 ok(handle != INVALID_HANDLE_VALUE, "File creation failed: %lu.\n", GetLastError());
726 WriteFile(handle, test_data, sizeof(test_data), &written, NULL);
727 ok(written == sizeof(test_data), "Failed to write data into file.\n");
728 CloseHandle(handle);
730 /* in read-only mode, SetSize() will success but it has no effect on Size() and the file */
731 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_READ, &stream);
732 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
733 CHECK_STREAM_SIZE(stream, sizeof(test_data));
734 stream_size.QuadPart = 0;
735 hr = IStream_SetSize(stream, stream_size);
736 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
737 CHECK_STREAM_SIZE(stream, sizeof(test_data));
738 CHECK_STREAM_POS(stream, 0);
739 stream_size.QuadPart = 100;
740 hr = IStream_SetSize(stream, stream_size);
741 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
742 CHECK_STREAM_SIZE(stream, sizeof(test_data));
743 CHECK_STREAM_POS(stream, 100);
744 IStream_Release(stream);
745 CHECK_FILE_SIZE(filename, sizeof(test_data));
747 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_WRITE, &stream);
748 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
749 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_READ, &stream2);
750 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
751 CHECK_STREAM_SIZE(stream, sizeof(test_data));
752 CHECK_STREAM_SIZE(stream2, sizeof(test_data));
753 CHECK_STREAM_POS(stream, 0);
754 CHECK_STREAM_POS(stream2, 0);
756 stream_size.QuadPart = 0;
757 hr = IStream_SetSize(stream, stream_size);
758 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
759 CHECK_STREAM_SIZE(stream, 0);
760 CHECK_STREAM_SIZE(stream2, 0);
761 CHECK_STREAM_POS(stream, 0);
762 CHECK_STREAM_POS(stream2, 0);
764 stream_size.QuadPart = 100;
765 hr = IStream_SetSize(stream, stream_size);
766 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
767 CHECK_STREAM_SIZE(stream, 100);
768 CHECK_STREAM_SIZE(stream2, 100);
769 CHECK_STREAM_POS(stream, 0);
770 CHECK_STREAM_POS(stream2, 0);
772 stream_size.QuadPart = 90;
773 hr = IStream_SetSize(stream2, stream_size);
774 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
775 CHECK_STREAM_SIZE(stream, 100);
776 CHECK_STREAM_SIZE(stream2, 100);
777 CHECK_STREAM_POS(stream, 0);
778 CHECK_STREAM_POS(stream2, 90);
779 IStream_Release(stream);
780 IStream_Release(stream2);
781 CHECK_FILE_SIZE(filename, 100);
783 DeleteFileA(filename);
786 START_TEST(shcore)
788 HMODULE hshcore = LoadLibraryA("shcore.dll");
790 if (!hshcore)
792 win_skip("Shcore.dll is not available.\n");
793 return;
796 init(hshcore);
798 test_process_reference();
799 test_SHUnicodeToAnsi();
800 test_SHAnsiToUnicode();
801 test_SHAnsiToAnsi();
802 test_SHUnicodeToUnicode();
803 test_SHRegDuplicateHKey();
804 test_SHDeleteKey();
805 test_SHGetValue();
806 test_SHRegGetValue();
807 test_SHQueryValueEx();
808 test_SHRegGetPath();
809 test_SHCopyKey();
810 test_stream_size();