ReactOS 0.4.17-dev-343-gb35a9be
shcore.c
Go to the documentation of this file.
1/*
2 * Copyright 2018 Nikolay Sivov for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19#define COBJMACROS
20
21#include <stdarg.h>
22
23#include <windows.h>
24#include "initguid.h"
25#include "objidl.h"
26#include "shlwapi.h"
27
28#include "wine/test.h"
29
30static HRESULT (WINAPI *pGetProcessReference)(IUnknown **);
31static void (WINAPI *pSetProcessReference)(IUnknown *);
32static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown **);
33static int (WINAPI *pSHUnicodeToAnsi)(const WCHAR *, char *, int);
34static int (WINAPI *pSHAnsiToUnicode)(const char *, WCHAR *, int);
35static int (WINAPI *pSHAnsiToAnsi)(const char *, char *, int);
36static int (WINAPI *pSHUnicodeToUnicode)(const WCHAR *, WCHAR *, int);
37static HKEY (WINAPI *pSHRegDuplicateHKey)(HKEY);
38static DWORD (WINAPI *pSHDeleteKeyA)(HKEY, const char *);
39static DWORD (WINAPI *pSHGetValueA)(HKEY, const char *, const char *, DWORD *, void *, DWORD *);
40static LSTATUS (WINAPI *pSHRegGetValueA)(HKEY, const char *, const char *, SRRF, DWORD *, void *, DWORD *);
41static DWORD (WINAPI *pSHQueryValueExA)(HKEY, const char *, DWORD *, DWORD *, void *buff, DWORD *buff_len);
42static DWORD (WINAPI *pSHRegGetPathA)(HKEY, const char *, const char *, char *, DWORD);
43static DWORD (WINAPI *pSHCopyKeyA)(HKEY, const char *, HKEY, DWORD);
44static HRESULT (WINAPI *pSHCreateStreamOnFileA)(const char *path, DWORD mode, IStream **stream);
45static HRESULT (WINAPI *pIStream_Size)(IStream *stream, ULARGE_INTEGER *size);
46
47/* Keys used for testing */
48#define REG_TEST_KEY "Software\\Wine\\Test"
49#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
50
51static const char test_path1[] = "%LONGSYSTEMVAR%\\subdir1";
52static const char test_path2[] = "%FOO%\\subdir1";
53
54static const char * test_envvar1 = "bar";
55static const char * test_envvar2 = "ImARatherLongButIndeedNeededString";
60static const char * initial_buffer ="0123456789";
61
62static void init(HMODULE hshcore)
63{
64#define X(f) p##f = (void*)GetProcAddress(hshcore, #f)
80#undef X
81}
82
83static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
84{
86 {
87 *obj = iface;
88 IUnknown_AddRef(iface);
89 return S_OK;
90 }
91
92 *obj = NULL;
93 return E_NOINTERFACE;
94}
95
97{
100};
101
103{
104 return CONTAINING_RECORD(iface, struct test_unk, IUnknown_iface);
105}
106
108{
109 struct test_unk *obj = impl_from_IUnknown(iface);
110 return InterlockedIncrement(&obj->refcount);
111}
112
114{
115 struct test_unk *obj = impl_from_IUnknown(iface);
116 return InterlockedDecrement(&obj->refcount);
117}
118
119static const IUnknownVtbl testunkvtbl =
120{
121 unk_QI,
124};
125
126static void test_unk_init(struct test_unk *testunk)
127{
128 testunk->IUnknown_iface.lpVtbl = &testunkvtbl;
129 testunk->refcount = 1;
130}
131
132static void test_process_reference(void)
133{
135 IUnknown *obj;
137 HRESULT hr;
138
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");
143
146
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);
152
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);
157
158 hmod = LoadLibraryA("shell32.dll");
159
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);
165}
166
167static void test_SHUnicodeToAnsi(void)
168{
169 char buff[16];
170 int ret;
171
172 ret = pSHUnicodeToAnsi(NULL, NULL, 0);
173 ok(ret == 0, "Unexpected return value %d.\n", ret);
174
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");
179
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");
184
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");
190
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");
195
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");
200
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");
204
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");
208}
209
210static void test_SHAnsiToUnicode(void)
211{
212 WCHAR buffW[16];
213 int ret;
214
215 ret = pSHAnsiToUnicode(NULL, NULL, 0);
216 ok(ret == 0, "Unexpected return value %d.\n", ret);
217
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");
223
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");
228
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");
233
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");
238
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");
243
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");
247
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");
251}
252
253static void test_SHAnsiToAnsi(void)
254{
255 char buff[16];
256 int ret;
257
258 ret = pSHAnsiToAnsi(NULL, NULL, 0);
259 ok(ret == 0, "Unexpected return value %d.\n", ret);
260
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");
266
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");
272
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");
278
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");
284
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");
290}
291
292static void test_SHUnicodeToUnicode(void)
293{
294 WCHAR buff[16];
295 int ret;
296
297 ret = pSHUnicodeToUnicode(NULL, NULL, 0);
298 ok(ret == 0, "Unexpected return value %d.\n", ret);
299
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");
305
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");
311
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");
317
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");
323
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");
329}
330
331static void test_SHRegDuplicateHKey(void)
332{
333 HKEY hkey, hkey2;
334 DWORD ret;
335
336 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey);
337 ok(!ret, "Failed to create test key, ret %ld.\n", ret);
338
339 hkey2 = pSHRegDuplicateHKey(hkey);
340 ok(hkey2 != NULL && hkey2 != hkey, "Unexpected duplicate key.\n");
341
342 RegCloseKey(hkey2);
343 RegCloseKey(hkey);
344
345 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
346}
347
348static void test_SHDeleteKey(void)
349{
350 HKEY hkey, hkey2;
351 DWORD ret;
352
353 ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey);
354 ok(!ret, "Failed to create test key, %ld.\n", ret);
355
356 ret = RegCreateKeyA(hkey, "delete_key", &hkey2);
357 ok(!ret, "Failed to create test key, %ld.\n", ret);
358 RegCloseKey(hkey2);
359
360 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
361 ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %ld.\n", ret);
362
363 ret = pSHDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test");
364 ok(!ret, "Unexpected retval %lu.\n", ret);
365
366 ret = RegCloseKey(hkey);
367 ok(!ret, "Unexpected retval %lu.\n", ret);
368}
369
371{
372 HKEY hKey;
373 DWORD ret;
374 DWORD nExpectedLen1, nExpectedLen2;
375
376 SetEnvironmentVariableA("LONGSYSTEMVAR", test_envvar1);
378
380 ok(!ret, "Unexpected retval %lu.\n", ret);
381
382 if (hKey)
383 {
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");
387 }
388
391
392 nExpectedLen1 = strlen(test_path1) - strlen("%LONGSYSTEMVAR%") + strlen(test_envvar1) + 1;
393 nExpectedLen2 = strlen(test_path2) - strlen("%FOO%") + strlen(test_envvar2) + 1;
394
395 /* Make sure we carry on with correct values */
396 exp_len1 = nExpectedLen1;
397 exp_len2 = nExpectedLen2;
398
399 return hKey;
400}
401
402/* delete key and all its subkeys */
403static DWORD delete_key( HKEY hkey, LPCSTR parent, LPCSTR keyname )
404{
405 HKEY parentKey;
406 DWORD ret;
407
408 RegCloseKey(hkey);
409
410 /* open the parent of the key to close */
412 if (ret != ERROR_SUCCESS)
413 return ret;
414
415 ret = pSHDeleteKeyA( parentKey, keyname );
416 RegCloseKey(parentKey);
417
418 return ret;
419}
420
421static void test_SHGetValue(void)
422{
423 DWORD size;
424 DWORD type;
425 DWORD ret;
426 char buf[MAX_PATH];
427
428 HKEY hkey = create_test_entries();
429
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);
435
436 ok(!strcmp(test_exp_path1, buf), "Unexpected value %s.\n", buf);
437 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
438
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);
446
447 delete_key(hkey, "Software\\Wine", "Test");
448}
449
450static void test_SHRegGetValue(void)
451{
452 LSTATUS ret;
453 DWORD size, type;
454 char data[MAX_PATH];
455
456 HKEY hkey = create_test_entries();
457
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);
461
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);
467
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);
471
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);
475
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);
481
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);
485
486 delete_key(hkey, "Software\\Wine", "Test");
487}
488
489static void test_SHQueryValueEx(void)
490{
491 DWORD buffer_len1,buffer_len2;
492 DWORD ret, type, size;
493 char buf[MAX_PATH];
494 HKEY hKey, testkey;
495
496 testkey = create_test_entries();
497
499 ok(!ret, "Failed to open a key, ret %lu.\n", ret);
500
501 /****** SHQueryValueExA ******/
502
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);
505
506 /*
507 * Case 1.1 All arguments are NULL
508 */
509 ret = pSHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, NULL);
510 ok(!ret, "Failed to query value, ret %lu.\n", ret);
511
512 /*
513 * Case 1.2 dwType is set
514 */
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);
519
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);
524
525 /*
526 * Expanded > unexpanded
527 */
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);
532
533 /*
534 * Case 1 string shrinks during expanding
535 */
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);
544
545 /*
546 * string grows during expanding
547 * dwSize is smaller than the size of the unexpanded string
548 */
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);
557
558 /*
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.
563 */
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);
569
570 ok(!strcmp("", buf), "Unexpanded string %s.\n", buf);
571
572 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
573 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
574
575 /*
576 * string grows during expanding
577 * dwSize is larger than the size of the part before the backslash,
578 * but smaller than the expanded string. If the unexpanded string fits
579 * into the buffer, it can get cut when expanded.
580 */
582 size = exp_len2 - 4;
583 type = -1;
584 ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size);
585 ok(ret == ERROR_MORE_DATA, "Unexpected retval %ld.\n", ret);
586
587 ok( !strcmp("", buf) || !strcmp(test_envvar2, buf),
588 "Expected empty or first part of the string \"%s\", got \"%s\"\n", test_envvar2, buf);
589
590 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
591 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
592
593 /*
594 * The buffer is NULL but the size is set
595 */
597 size = 6;
598 type = -1;
599 ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, NULL, &size);
600 ok(!ret, "Failed to query value, ret %lu.\n", ret);
601 ok(size >= buffer_len2, "Buffer size %lu should be >= %lu.\n", size, buffer_len2);
602 ok(type == REG_SZ, "Unexpected type %ld.\n", type);
603
605
606 delete_key(testkey, "Software\\Wine", "Test");
607}
608
609static void test_SHRegGetPath(void)
610{
611 char buf[MAX_PATH];
612 DWORD ret;
613 HKEY hkey;
614
615 hkey = create_test_entries();
616
618 ret = pSHRegGetPathA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", buf, 0);
619 ok(!ret, "Failed to get path, ret %lu.\n", ret);
620 ok(!strcmp(test_exp_path1, buf), "Unexpected path %s.\n", buf);
621
622 delete_key(hkey, "Software\\Wine", "Test");
623}
624
625static void test_SHCopyKey(void)
626{
627 HKEY hKeySrc, hKeyDst;
628 DWORD ret;
629
630 HKEY hkey = create_test_entries();
631
632 /* Delete existing destination sub keys */
633 hKeyDst = NULL;
634 if (!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst) && hKeyDst)
635 {
636 pSHDeleteKeyA(hKeyDst, NULL);
637 RegCloseKey(hKeyDst);
638 }
639
640 hKeyDst = NULL;
641 ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst);
642 ok(!ret, "Failed to create a test key, ret %ld.\n", ret);
643
644 hKeySrc = NULL;
646 ok(!ret, "Failed to open a test key, ret %ld.\n", ret);
647
648 ret = pSHCopyKeyA(hKeySrc, NULL, hKeyDst, 0);
649 ok(!ret, "Copy failed, ret %lu.\n", ret);
650
651 RegCloseKey(hKeySrc);
652 RegCloseKey(hKeyDst);
653
654 /* Check we copied the sub keys, i.e. something that's on every windows system (including Wine) */
655 hKeyDst = NULL;
656 ret = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination\\Shell Folders", &hKeyDst);
657 ok(!ret, "Failed to open a test key, ret %ld.\n", ret);
658
659 /* And the we copied the values too */
660 ok(!pSHQueryValueExA(hKeyDst, "Common AppData", NULL, NULL, NULL, NULL), "SHQueryValueExA failed\n");
661
662 RegCloseKey(hKeyDst);
663 delete_key( hkey, "Software\\Wine", "Test" );
664}
665
666#define CHECK_FILE_SIZE(filename,exp_size) _check_file_size(filename, exp_size, __LINE__)
667static void _check_file_size(const CHAR *filename, LONG exp_size, int line)
668{
670 DWORD file_size = 0xdeadbeef;
673 ok_(__FILE__,line)(file_size == exp_size, "got wrong file size: %ld.\n", file_size);
675}
676
677#define CHECK_STREAM_SIZE(obj,exp_size) _check_stream_size(obj, exp_size, __LINE__)
678static void _check_stream_size(IStream *obj, LONG exp_size, int line)
679{
681 STATSTG stat;
682 HRESULT hr;
683 stream_size.QuadPart = 0xdeadbeef;
684 hr = pIStream_Size(obj, &stream_size);
685 ok_(__FILE__,line)(hr == S_OK, "IStream_Size failed: hr %#lx.\n", hr);
686 ok_(__FILE__,line)(stream_size.QuadPart == exp_size, "Size(): got wrong size of stream: %s.\n",
688 hr = IStream_Stat(obj, &stat, STATFLAG_NONAME);
689 ok_(__FILE__,line)(hr == S_OK, "IStream_Stat failed: hr %#lx.\n", hr);
690 ok_(__FILE__,line)(stat.cbSize.QuadPart == exp_size, "Stat(): got wrong size of stream: %s.\n",
691 wine_dbgstr_longlong(stat.cbSize.QuadPart));
692}
693
694#define CHECK_STREAM_POS(obj,exp_pos) _check_stream_pos(obj, exp_pos, __LINE__)
695static void _check_stream_pos(IStream *obj, LONG exp_pos, int line)
696{
697 LARGE_INTEGER move;
699 HRESULT hr;
700 move.QuadPart = 0;
701 pos.QuadPart = 0xdeadbeef;
702 hr = IStream_Seek(obj, move, STREAM_SEEK_CUR, &pos);
703 ok_(__FILE__,line)(hr == S_OK, "IStream_Seek failed: hr %#lx.\n", hr);
704 ok_(__FILE__,line)(pos.QuadPart == exp_pos, "got wrong position: %s.\n",
705 wine_dbgstr_longlong(pos.QuadPart));
706}
707
708static void test_stream_size(void)
709{
710 static const byte test_data[] = {0x1,0x2,0x3,0x4,0x5,0x6};
711 static const CHAR filename[] = "test_file";
712 IStream *stream, *stream2;
714 DWORD written = 0;
716 HRESULT hr;
717
719 ok(handle != INVALID_HANDLE_VALUE, "File creation failed: %lu.\n", GetLastError());
720 WriteFile(handle, test_data, sizeof(test_data), &written, NULL);
721 ok(written == sizeof(test_data), "Failed to write data into file.\n");
723
724 /* in read-only mode, SetSize() will success but it has no effect on Size() and the file */
725 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_READ, &stream);
726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
728 stream_size.QuadPart = 0;
729 hr = IStream_SetSize(stream, stream_size);
730 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
733 stream_size.QuadPart = 100;
734 hr = IStream_SetSize(stream, stream_size);
735 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
738 IStream_Release(stream);
740
741 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_WRITE, &stream);
742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
743 hr = pSHCreateStreamOnFileA(filename, STGM_FAILIFTHERE|STGM_READ, &stream2);
744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
746 CHECK_STREAM_SIZE(stream2, sizeof(test_data));
748 CHECK_STREAM_POS(stream2, 0);
749
750 stream_size.QuadPart = 0;
751 hr = IStream_SetSize(stream, stream_size);
752 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
754 CHECK_STREAM_SIZE(stream2, 0);
756 CHECK_STREAM_POS(stream2, 0);
757
758 stream_size.QuadPart = 100;
759 hr = IStream_SetSize(stream, stream_size);
760 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
762 CHECK_STREAM_SIZE(stream2, 100);
764 CHECK_STREAM_POS(stream2, 0);
765
766 stream_size.QuadPart = 90;
767 hr = IStream_SetSize(stream2, stream_size);
768 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
770 CHECK_STREAM_SIZE(stream2, 100);
772 CHECK_STREAM_POS(stream2, 90);
773 IStream_Release(stream);
774 IStream_Release(stream2);
776
778}
779
781{
782 HMODULE hshcore = LoadLibraryA("shcore.dll");
783
784 if (!hshcore)
785 {
786 win_skip("Shcore.dll is not available.\n");
787 return;
788 }
789
790 init(hshcore);
791
805}
#define stat
Definition: acwin.h:100
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
const GUID IID_IUnknown
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define E_FAIL
Definition: ddrawi.h:102
HRESULT hr
Definition: delayimp.cpp:582
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3298
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define OPEN_EXISTING
Definition: compat.h:775
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define lstrcpyW
Definition: compat.h:749
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
DWORD WINAPI ExpandEnvironmentStringsA(IN LPCSTR lpSrc, IN LPSTR lpDst, IN DWORD nSize)
Definition: environ.c:372
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:191
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI WriteFile(_In_ HANDLE hFile, _In_reads_bytes_opt_(nNumberOfBytesToWrite) LPCVOID lpBuffer, _In_ DWORD nNumberOfBytesToWrite, _Out_opt_ LPDWORD lpNumberOfBytesWritten, _Inout_opt_ LPOVERLAPPED lpOverlapped)
Definition: rw.c:25
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
void WINAPI SetProcessReference(IUnknown *obj)
Definition: main.c:1564
DWORD WINAPI SHCopyKeyA(HKEY hkey_src, const char *subkey, HKEY hkey_dst, DWORD reserved)
Definition: main.c:1950
DWORD WINAPI SHUnicodeToUnicode(const WCHAR *src, WCHAR *dest, int dest_len)
Definition: main.c:1783
HRESULT WINAPI IStream_Size(IStream *stream, ULARGE_INTEGER *size)
Definition: main.c:120
DWORD WINAPI SHDeleteKeyA(HKEY hkey, const char *subkey)
Definition: main.c:1896
DWORD WINAPI SHRegGetPathA(HKEY hkey, const char *subkey, const char *value, char *path, DWORD flags)
Definition: main.c:2268
DWORD WINAPI SHQueryValueExA(HKEY hkey, const char *name, DWORD *reserved, DWORD *type, void *buff, DWORD *buff_len)
Definition: main.c:2149
HRESULT WINAPI SHCreateStreamOnFileA(const char *path, DWORD mode, IStream **stream)
Definition: main.c:1196
DWORD WINAPI SHAnsiToUnicode(const char *src, WCHAR *dest, int dest_len)
Definition: main.c:1801
DWORD WINAPI SHUnicodeToAnsi(const WCHAR *src, char *dest, int dest_len)
Definition: main.c:1756
HRESULT WINAPI GetProcessReference(IUnknown **obj)
Definition: main.c:1546
HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
Definition: main.c:1828
DWORD WINAPI SHAnsiToAnsi(const char *src, char *dest, int dest_len)
Definition: main.c:1738
DWORD WINAPI SHGetValueA(HKEY hkey, const char *subkey, const char *value, DWORD *type, void *data, DWORD *data_len)
Definition: main.c:2197
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
const char * filename
Definition: ioapi.h:137
#define REG_SZ
Definition: layer.c:22
#define win_skip
Definition: minitest.h:67
#define CREATE_ALWAYS
Definition: disk.h:72
static NTSTATUS *static PWSTR CURDIR *static HMODULE hmod
Definition: security.c:104
static IUnknown test_unk2
Definition: dictionary.c:329
#define KEY_ALL_ACCESS
Definition: nt_native.h:1044
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1497
#define STGM_FAILIFTHERE
Definition: objbase.h:947
#define STGM_WRITE
Definition: objbase.h:937
#define STGM_READ
Definition: objbase.h:936
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
char CHAR
Definition: pedump.c:57
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define SRRF_RT_REG_EXPAND_SZ
Definition: shlwapi.h:699
#define SRRF_RT_REG_DWORD
Definition: shlwapi.h:701
#define SRRF_RT_REG_QWORD
Definition: shlwapi.h:703
#define SRRF_RT_REG_SZ
Definition: shlwapi.h:698
#define delete_key(r, p, s)
Definition: reg_test.h:64
static unsigned int file_size
Definition: regtests2xml.c:47
strcpy
Definition: string.h:131
int const char int stream_size
Definition: zlib.h:814
static void test_SHRegGetPath(void)
Definition: shcore.c:609
static const char HKEY
Definition: shcore.c:43
static DWORD exp_len2
Definition: shcore.c:59
static void test_SHQueryValueEx(void)
Definition: shcore.c:489
static const char *static const char const char DWORD void DWORD *static const char const char SRRF
Definition: shcore.c:40
static void test_SHRegDuplicateHKey(void)
Definition: shcore.c:331
static void test_unk_init(struct test_unk *testunk)
Definition: shcore.c:126
#define CHECK_STREAM_SIZE(obj, exp_size)
Definition: shcore.c:677
static struct test_unk * impl_from_IUnknown(IUnknown *iface)
Definition: shcore.c:102
static void test_SHUnicodeToUnicode(void)
Definition: shcore.c:292
static void test_SHDeleteKey(void)
Definition: shcore.c:348
#define CHECK_STREAM_POS(obj, exp_pos)
Definition: shcore.c:694
static const char *static const char const char DWORD void DWORD *static LSTATUS(WINAPI *pSHRegGetValueA)(HKEY
static char test_exp_path2[MAX_PATH]
Definition: shcore.c:57
static void test_SHUnicodeToAnsi(void)
Definition: shcore.c:167
static void test_stream_size(void)
Definition: shcore.c:708
static void test_SHGetValue(void)
Definition: shcore.c:421
static void _check_stream_pos(IStream *obj, LONG exp_pos, int line)
Definition: shcore.c:695
static void test_SHCopyKey(void)
Definition: shcore.c:625
static void _check_file_size(const CHAR *filename, LONG exp_size, int line)
Definition: shcore.c:667
static void test_process_reference(void)
Definition: shcore.c:132
#define X(f)
static DWORD IStream ** stream
Definition: shcore.c:44
static HKEY create_test_entries(void)
Definition: shcore.c:370
static const char * test_envvar1
Definition: shcore.c:54
static void test_SHAnsiToUnicode(void)
Definition: shcore.c:210
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void DWORD * buff_len
Definition: shcore.c:41
static char test_exp_path1[MAX_PATH]
Definition: shcore.c:56
static ULONG WINAPI unk_Release(IUnknown *iface)
Definition: shcore.c:113
static void test_SHAnsiToAnsi(void)
Definition: shcore.c:253
static void _check_stream_size(IStream *obj, LONG exp_size, int line)
Definition: shcore.c:678
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void * buff
Definition: shcore.c:41
#define REG_CURRENT_VERSION
Definition: shcore.c:49
static const char const char char DWORD
Definition: shcore.c:42
static const char * initial_buffer
Definition: shcore.c:60
static ULONG WINAPI unk_AddRef(IUnknown *iface)
Definition: shcore.c:107
static const char test_path1[]
Definition: shcore.c:51
static char int
Definition: shcore.c:33
static const char * test_envvar2
Definition: shcore.c:55
#define REG_TEST_KEY
Definition: shcore.c:48
static DWORD exp_len1
Definition: shcore.c:58
static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
Definition: shcore.c:83
static ULARGE_INTEGER * size
Definition: shcore.c:45
static const char test_path2[]
Definition: shcore.c:52
#define CHECK_FILE_SIZE(filename, exp_size)
Definition: shcore.c:666
static const IUnknownVtbl testunkvtbl
Definition: shcore.c:119
static void test_SHRegGetValue(void)
Definition: shcore.c:450
static DWORD mode
Definition: shcore.c:44
Definition: parser.c:49
Definition: stat.h:66
Definition: parse.h:23
IUnknown IUnknown_iface
Definition: shcore.c:98
LONG refcount
Definition: shcore.c:99
#define max(a, b)
Definition: svc.c:63
const char * LPCSTR
Definition: typedefs.h:52
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
WINSHLWAPI LSTATUS WINAPI SHRegGetValueA(HKEY, LPCSTR, LPCSTR, SRRF, LPDWORD, LPVOID, LPDWORD)
#define E_NOINTERFACE
Definition: winerror.h:3479
#define ERROR_UNSUPPORTED_TYPE
Definition: winerror.h:1336
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static int init
Definition: wintirpc.c:33
unsigned char BYTE
Definition: xxhash.c:193