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
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
);
70 X(SHUnicodeToUnicode
);
71 X(SHRegDuplicateHKey
);
78 X(SHCreateStreamOnFileA
);
83 static HRESULT WINAPI
unk_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
85 if (IsEqualIID(riid
, &IID_IUnknown
))
88 IUnknown_AddRef(iface
);
98 IUnknown IUnknown_iface
;
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
=
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
;
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)
172 ret
= pSHUnicodeToAnsi(NULL
, NULL
, 0);
173 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
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");
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");
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");
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");
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)
215 ret
= pSHAnsiToUnicode(NULL
, NULL
, 0);
216 ok(ret
== 0, "Unexpected return value %d.\n", ret
);
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");
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");
230 ret
= pSHAnsiToUnicode("", buffW
, 1);
231 ok(ret
== 1, "Unexpected return value %d.\n", ret
);
232 ok(*buffW
== 0, "Unexpected buffer contents.\n");
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");
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)
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)
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)
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");
345 RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\Test");
348 static void test_SHDeleteKey(void)
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
);
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)
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
);
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
;
402 /* delete key and all its subkeys */
403 static DWORD
delete_key( HKEY hkey
, LPCSTR parent
, LPCSTR keyname
)
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
)
415 ret
= pSHDeleteKeyA( parentKey
, keyname
);
416 RegCloseKey(parentKey
);
421 static void test_SHGetValue(void)
428 HKEY hkey
= create_test_entries();
430 strcpy(buf
, initial_buffer
);
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
);
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)
456 HKEY hkey
= create_test_entries();
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
);
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
);
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
);
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
);
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
);
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
;
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
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
);
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
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
);
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
);
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;
567 ret
= pSHQueryValueExA(hKey
, "Test3", NULL
, &type
, buf
, &size
);
568 ok(ret
== ERROR_MORE_DATA
, "Unexpected retval %ld.\n", ret
);
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
);
587 ret
= pSHQueryValueExA( hKey
, "Test3", NULL
, &type
, buf
, &size
);
588 ok(ret
== ERROR_MORE_DATA
, "Unexpected retval %ld.\n", ret
);
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
);
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
);
612 delete_key(testkey
, "Software\\Wine", "Test");
615 static void test_SHRegGetPath(void)
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
;
636 HKEY hkey
= create_test_entries();
638 /* Delete existing destination sub keys */
640 if (!RegOpenKeyA(HKEY_CURRENT_USER
, REG_TEST_KEY
"\\CopyDestination", &hKeyDst
) && hKeyDst
)
642 pSHDeleteKeyA(hKeyDst
, NULL
);
643 RegCloseKey(hKeyDst
);
647 ret
= RegCreateKeyA(HKEY_CURRENT_USER
, REG_TEST_KEY
"\\CopyDestination", &hKeyDst
);
648 ok(!ret
, "Failed to create a test key, ret %ld.\n", ret
);
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) */
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
)
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
);
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
;
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
)
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
;
721 ULARGE_INTEGER stream_size
;
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");
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
);
788 HMODULE hshcore
= LoadLibraryA("shcore.dll");
792 win_skip("Shcore.dll is not available.\n");
798 test_process_reference();
799 test_SHUnicodeToAnsi();
800 test_SHAnsiToUnicode();
802 test_SHUnicodeToUnicode();
803 test_SHRegDuplicateHKey();
806 test_SHRegGetValue();
807 test_SHQueryValueEx();