ReactOS 0.4.16-dev-2206-gc56950d
profile.c
Go to the documentation of this file.
1/*
2 * Unit tests for profile functions
3 *
4 * Copyright (c) 2003 Stefan Leichter
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22#include <stdio.h>
23
24#include "wine/test.h"
25#include "windef.h"
26#include "winbase.h"
27#include "windows.h"
28#include "sddl.h"
29
30#define KEY "ProfileInt"
31#define SECTION "Test"
32#define TESTFILE ".\\testwine.ini"
33#define TESTFILE2 ".\\testwine2.ini"
34
35static void check_profile_string_(int line, const char *section, const char *name, const char *file, const char *expect)
36{
37 char value[200] = {0};
38 DWORD ret = GetPrivateProfileStringA(section, name, "default", value, sizeof(value), file);
39 ok_(__FILE__, line)(ret == strlen(expect), "expected len %Iu, got %lu\n", strlen(expect), ret);
40 ok_(__FILE__, line)(!strcmp(value, expect), "expected %s, got %s\n", debugstr_a(expect), debugstr_a(value));
41}
42#define check_profile_string(a, b, c, d) check_profile_string_(__LINE__, a, b, c, d);
43
44struct _profileInt {
51};
52
53static void test_profile_int(void)
54{
55 struct _profileInt profileInt[]={
56 { NULL, NULL, NULL, NULL, 70, 0}, /* 0 */
57 { NULL, NULL, NULL, TESTFILE, -1, 4294967295U},
58 { NULL, NULL, NULL, TESTFILE, 1, 1},
59 { SECTION, NULL, NULL, TESTFILE, -1, 4294967295U},
60 { SECTION, NULL, NULL, TESTFILE, 1, 1},
61 { NULL, KEY, NULL, TESTFILE, -1, 4294967295U}, /* 5 */
62 { NULL, KEY, NULL, TESTFILE, 1, 1},
63 { SECTION, KEY, NULL, TESTFILE, -1, 4294967295U},
64 { SECTION, KEY, NULL, TESTFILE, 1, 1},
65 { SECTION, KEY, "-1", TESTFILE, -1, 4294967295U},
66 { SECTION, KEY, "-1", TESTFILE, 1, 4294967295U}, /* 10 */
67 { SECTION, KEY, "1", TESTFILE, -1, 1},
68 { SECTION, KEY, "1", TESTFILE, 1, 1},
69 { SECTION, KEY, "+1", TESTFILE, -1, 1},
70 { SECTION, KEY, "+1", TESTFILE, 1, 1},
71 { SECTION, KEY, "4294967296", TESTFILE, -1, 0}, /* 15 */
72 { SECTION, KEY, "4294967296", TESTFILE, 1, 0},
73 { SECTION, KEY, "4294967297", TESTFILE, -1, 1},
74 { SECTION, KEY, "4294967297", TESTFILE, 1, 1},
75 { SECTION, KEY, "-4294967297", TESTFILE, -1, 4294967295U},
76 { SECTION, KEY, "-4294967297", TESTFILE, 1, 4294967295U}, /* 20 */
77 { SECTION, KEY, "42A94967297", TESTFILE, -1, 42},
78 { SECTION, KEY, "42A94967297", TESTFILE, 1, 42},
79 { SECTION, KEY, "B4294967297", TESTFILE, -1, 0},
80 { SECTION, KEY, "B4294967297", TESTFILE, 1, 0},
81 };
82 int i, num_test = ARRAY_SIZE(profileInt);
83 char section[64];
84 UINT res;
85
87
88 for (i=0; i < num_test; i++) {
89 if (profileInt[i].value)
91 profileInt[i].iniFile);
92
93 res = GetPrivateProfileIntA(profileInt[i].section, profileInt[i].key,
94 profileInt[i].defaultVal, profileInt[i].iniFile);
95 ok((res == profileInt[i].result), "test<%02d>: ret<%010u> exp<%010u>\n",
96 i, res, profileInt[i].result);
97
98 sprintf(section, " %s ", profileInt[i].section);
99 res = GetPrivateProfileIntA(profileInt[i].section, profileInt[i].key,
100 profileInt[i].defaultVal, profileInt[i].iniFile);
101 ok((res == profileInt[i].result), "test<%02d>: ret<%010u> exp<%010u>\n",
102 i, res, profileInt[i].result);
103 }
104
106}
107
108static void test_profile_string(void)
109{
110 static WCHAR emptyW[] = { 0 }; /* if "const", GetPrivateProfileStringW(emptyW, ...) crashes on win2k */
111 static const WCHAR keyW[] = { 'k','e','y',0 };
112 static const WCHAR sW[] = { 's',0 };
113 static const WCHAR TESTFILE2W[] = {'.','\\','t','e','s','t','w','i','n','e','2','.','i','n','i',0};
114 static const WCHAR valsectionW[] = {'v','a','l','_','e','_','s','e','c','t','i','o','n',0 };
115 static const WCHAR valnokeyW[] = {'v','a','l','_','n','o','_','k','e','y',0};
116 HANDLE h;
117 int ret;
118 DWORD count;
119 char buf[100];
120 WCHAR bufW[100];
121 char *p;
122 /* test that lines without an '=' will not be enumerated */
123 /* in the case below, name2 is a key while name3 is not. */
124 char content[]="[s]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n";
125 char content2[]="\r\nkey=val_no_section\r\n[]\r\nkey=val_e_section\r\n"
126 "[s]\r\n=val_no_key\r\n[t]\r\n";
130 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
131 if( h == INVALID_HANDLE_VALUE) return;
132 WriteFile( h, content, sizeof(content), &count, NULL);
133 CloseHandle( h);
134
135 /* enumerate the keys */
136 ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
137 TESTFILE2);
138 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
139 p[-1] = ',';
140 /* and test */
141 ok( ret == 18 && !strcmp( buf, "name1,name2,name4"), "wrong keys returned(%d): %s\n", ret,
142 buf);
143
144 /* add a new key to test that the file is quite usable */
145 WritePrivateProfileStringA( "s", "name5", "val5", TESTFILE2);
146 ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
147 TESTFILE2);
148 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
149 p[-1] = ',';
150 ok( ret == 24 && !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned(%d): %s\n",
151 ret, buf);
152
155 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
156 if( h == INVALID_HANDLE_VALUE) return;
157 WriteFile( h, content2, sizeof(content2), &count, NULL);
158 CloseHandle( h);
159
160 /* works only in unicode, ansi crashes */
161 ret=GetPrivateProfileStringW(emptyW, keyW, emptyW, bufW, ARRAY_SIZE(bufW), TESTFILE2W);
163 ok(ret == 13, "expected 13, got %u\n", ret);
165 ok(!lstrcmpW(valsectionW,bufW), "expected %s, got %s\n",
166 wine_dbgstr_w(valsectionW), wine_dbgstr_w(bufW) );
167
168 /* works only in unicode, ansi crashes */
169 ret=GetPrivateProfileStringW(sW, emptyW, emptyW, bufW, ARRAY_SIZE(bufW), TESTFILE2W);
170 ok(ret == 10, "expected 10, got %u\n", ret);
171 ok(!lstrcmpW(valnokeyW,bufW), "expected %s, got %s\n",
172 wine_dbgstr_w(valnokeyW), wine_dbgstr_w(bufW) );
173
175}
176
177static void test_profile_sections(void)
178{
179 HANDLE h;
180 int ret;
181 DWORD count;
182 char buf[100];
183 char *p;
184 static const char content[]="[section1]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n[section2]\r\n[section3]\r\n=val5\r\n";
185 static const char testfile4[]=".\\testwine4.ini";
186 BOOL on_win98 = FALSE;
187
188 DeleteFileA( testfile4 );
190 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", testfile4);
191 if( h == INVALID_HANDLE_VALUE) return;
192 WriteFile( h, content, sizeof(content), &count, NULL);
193 CloseHandle( h);
194
195 /* Some parameter checking */
196 SetLastError(0xdeadbeef);
198 ok( ret == 0, "expected return size 0, got %d\n", ret );
200 GetLastError() == 0xdeadbeef /* Win98 */,
201 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
202 if (GetLastError() == 0xdeadbeef) on_win98 = TRUE;
203
204 SetLastError(0xdeadbeef);
205 ret = GetPrivateProfileSectionA( NULL, NULL, 0, testfile4 );
206 ok( ret == 0, "expected return size 0, got %d\n", ret );
208 GetLastError() == 0xdeadbeef /* Win98 */,
209 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
210
211 if (!on_win98)
212 {
213 SetLastError(0xdeadbeef);
214 ret = GetPrivateProfileSectionA( "section1", NULL, 0, testfile4 );
215 ok( ret == 0, "expected return size 0, got %d\n", ret );
216 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
217 }
218
219 SetLastError(0xdeadbeef);
220 ret = GetPrivateProfileSectionA( NULL, buf, sizeof(buf), testfile4 );
221 ok( ret == 0, "expected return size 0, got %d\n", ret );
223 "expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError());
224
225 SetLastError(0xdeadbeef);
226 ret = GetPrivateProfileSectionA( "section1", buf, sizeof(buf), NULL );
227 ok( ret == 0, "expected return size 0, got %d\n", ret );
230 "expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
231
232 /* Existing empty section with no keys */
233 SetLastError(0xdeadbeef);
234 ret=GetPrivateProfileSectionA("section2", buf, sizeof(buf), testfile4);
235 ok( ret == 0, "expected return size 0, got %d\n", ret );
237 "expected ERROR_SUCCESS, got %ld\n", GetLastError());
238
239 /* Existing section with keys and values*/
240 SetLastError(0xdeadbeef);
241 ret=GetPrivateProfileSectionA("section1", buf, sizeof(buf), testfile4);
242 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
243 p[-1] = ',';
244 ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
245 ret, buf);
246 ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
248 "expected ERROR_SUCCESS, got %ld\n", GetLastError());
249
250 /* Existing section with no keys but has values */
251 SetLastError(0xdeadbeef);
252 ret=GetPrivateProfileSectionA("section3", buf, sizeof(buf), testfile4);
253 trace("section3 return: %s\n", buf);
254 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
255 p[-1] = ',';
256 ok( ret == 6 && !strcmp( buf, "=val5"), "wrong section returned(%d): %s\n",
257 ret, buf);
258 ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
260 "expected ERROR_SUCCESS, got %ld\n", GetLastError());
261
262 /* Overflow*/
263 ret=GetPrivateProfileSectionA("section1", buf, 24, testfile4);
264 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
265 p[-1] = ',';
266 ok( ret == 22 && !strcmp( buf, "name1=val1,name2=,name"), "wrong section returned(%d): %s\n",
267 ret, buf);
268 ok( buf[ret] == 0 && buf[ret+1] == 0, "returned buffer not terminated with double-null\n" );
269
270 DeleteFileA( testfile4 );
271}
272
274{
275 HANDLE h;
276 int ret;
277 DWORD count;
278 char buf[100];
279 WCHAR bufW[100];
280 static const char content[]="[ section1 ]\r\n[section2]\r\n[section3]\r\n";
281 static const char testfile3[]=".\\testwine3.ini";
282 static const WCHAR testfile3W[]={ '.','\\','t','e','s','t','w','i','n','e','3','.','i','n','i',0 };
283 static const WCHAR not_here[] = {'.','\\','n','o','t','_','h','e','r','e','.','i','n','i',0};
284 DeleteFileA( testfile3 );
285 h = CreateFileA( testfile3, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
287 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", testfile3);
288 if( h == INVALID_HANDLE_VALUE) return;
289 WriteFile( h, content, sizeof(content), &count, NULL);
290 CloseHandle( h);
291
292 /* Test with sufficiently large buffer */
293 memset(buf, 0xc, sizeof(buf));
294 ret = GetPrivateProfileSectionNamesA( buf, 29, testfile3 );
295 ok( ret == 27, "expected return size 27, got %d\n", ret );
296 ok( (buf[ret-1] == 0 && buf[ret] == 0),
297 "returned buffer not terminated with double-null\n" );
298 ok( !strcmp(buf, "section1"), "Unexpected content %s.\n", debugstr_a(buf));
299
300 /* Test with exactly fitting buffer */
301 memset(buf, 0xc, sizeof(buf));
302 ret = GetPrivateProfileSectionNamesA( buf, 28, testfile3 );
303 ok( ret == 26, "expected return size 26, got %d\n", ret );
305 ok( (buf[ret+1] == 0 && buf[ret] == 0) || /* W2K3 and higher */
306 broken(buf[ret+1] == 0xc && buf[ret] == 0), /* NT4, W2K, WinXP */
307 "returned buffer not terminated with double-null\n" );
308
309 /* Test with a buffer too small */
310 memset(buf, 0xc, sizeof(buf));
311 ret = GetPrivateProfileSectionNamesA( buf, 27, testfile3 );
312 ok( ret == 25, "expected return size 25, got %d\n", ret );
313 count = strlen("section1") + sizeof(CHAR) + strlen("section2");
315 ok( buf[ret+1] == 0 && buf[ret] == 0,
316 "returned buffer not terminated with double-null\n" );
317
318 /* Tests on nonexistent file */
319 memset(buf, 0xc, sizeof(buf));
320 ret = GetPrivateProfileSectionNamesA( buf, 10, ".\\not_here.ini" );
321 ok( ret == 0, "expected return size 0, got %d\n", ret );
322 ok( buf[0] == 0, "returned buffer not terminated with null\n" );
323 ok( buf[1] != 0, "returned buffer terminated with double-null\n" );
324
325 /* Test with sufficiently large buffer */
326 SetLastError(0xdeadbeef);
327 memset(bufW, 0xcc, sizeof(bufW));
328 ret = GetPrivateProfileSectionNamesW( bufW, 29, testfile3W );
330 {
331 win_skip("GetPrivateProfileSectionNamesW is not implemented\n");
332 DeleteFileA( testfile3 );
333 return;
334 }
335 ok( ret == 27, "expected return size 27, got %d\n", ret );
336 ok( bufW[ret-1] == 0 && bufW[ret] == 0, "returned buffer not terminated with double-null\n" );
337
338 /* Test with exactly fitting buffer */
339 memset(bufW, 0xcc, sizeof(bufW));
340 ret = GetPrivateProfileSectionNamesW( bufW, 28, testfile3W );
341 ok( ret == 26, "expected return size 26, got %d\n", ret );
342 ok( (bufW[ret+1] == 0 && bufW[ret] == 0) || /* W2K3 and higher */
343 broken(bufW[ret+1] == 0xcccc && bufW[ret] == 0), /* NT4, W2K, WinXP */
344 "returned buffer not terminated with double-null\n" );
345
346 /* Test with a buffer too small */
347 memset(bufW, 0xcc, sizeof(bufW));
348 ret = GetPrivateProfileSectionNamesW( bufW, 27, testfile3W );
349 ok( ret == 25, "expected return size 25, got %d\n", ret );
350 ok( bufW[ret+1] == 0 && bufW[ret] == 0, "returned buffer not terminated with double-null\n" );
351
352 DeleteFileA( testfile3 );
353
354 /* Tests on nonexistent file */
355 memset(bufW, 0xcc, sizeof(bufW));
356 ret = GetPrivateProfileSectionNamesW( bufW, 10, not_here );
357 ok( ret == 0, "expected return size 0, got %d\n", ret );
358 ok( bufW[0] == 0, "returned buffer not terminated with null\n" );
359 ok( bufW[1] != 0, "returned buffer terminated with double-null\n" );
360}
361
362/* If the ini-file has already been opened with CreateFile, WritePrivateProfileString failed in wine with an error ERROR_SHARING_VIOLATION, some testing here */
363static void test_profile_existing(void)
364{
365 static const char *testfile1 = ".\\winesharing1.ini";
366 static const char *testfile2 = ".\\winesharing2.ini";
367
368 static const struct {
369 DWORD dwDesiredAccess;
370 DWORD dwShareMode;
371 DWORD write_error;
372 BOOL read_error;
373 DWORD broken_error;
374 } pe[] = {
383 /*Thief demo (bug 5024) opens .ini file like this*/
385 };
386
387 int i;
388 BOOL ret;
389 DWORD size;
390 HANDLE h = 0;
391 char buffer[MAX_PATH];
392
393 for (i=0; i < ARRAY_SIZE(pe); i++)
394 {
395 h = CreateFileA(testfile1, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
397 ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
398 SetLastError(0xdeadbeef);
399
400 ret = WritePrivateProfileStringA(SECTION, KEY, "12345", testfile1);
401 if (!pe[i].write_error)
402 {
403 if (!ret)
404 ok( broken(GetLastError() == pe[i].broken_error),
405 "%d: WritePrivateProfileString failed with error %lu\n", i, GetLastError() );
406 CloseHandle(h);
408 if (ret)
409 ok( size == 5, "%d: test failed, number of characters copied: %ld instead of 5\n", i, size );
410 else
411 ok( !size, "%d: test failed, number of characters copied: %ld instead of 0\n", i, size );
412 }
413 else
414 {
416 ok( !ret, "%d: WritePrivateProfileString succeeded\n", i );
417 if (!ret)
418 ok( err == pe[i].write_error, "%d: WritePrivateProfileString failed with error %lu/%lu\n",
419 i, err, pe[i].write_error );
420 CloseHandle(h);
422 ok( !size, "%d: test failed, number of characters copied: %ld instead of 0\n", i, size );
423 }
424
425 ok( DeleteFileA(testfile1), "delete failed\n" );
426 }
427
429 sprintf( buffer, "[%s]\r\n%s=123\r\n", SECTION, KEY );
430 ok( WriteFile( h, buffer, strlen(buffer), &size, NULL ), "failed to write\n" );
431 CloseHandle( h );
432
433 for (i=0; i < ARRAY_SIZE(pe); i++)
434 {
435 h = CreateFileA(testfile2, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
437 ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
438 SetLastError(0xdeadbeef);
440 if (!pe[i].read_error)
441 ok( ret, "%d: GetPrivateProfileString failed with error %lu\n", i, GetLastError() );
442 else
443 ok( !ret, "%d: GetPrivateProfileString succeeded\n", i );
444 CloseHandle(h);
445 }
446 ok( DeleteFileA(testfile2), "delete failed\n" );
447}
448
450{
451 HANDLE h;
452 DWORD size, res;
453 static const CHAR testfile[] = ".\\testwine5.ini";
454 static const char contents[] = "[" SECTION "]\n" KEY "=123\n";
455
458 res = WriteFile( h, contents, sizeof contents - 1, &size, NULL );
459 ok( res, "Cannot write test file: %lx\n", GetLastError() );
460 ok( size == sizeof contents - 1, "Test file: partial write\n");
461
462 SetLastError(0xdeadbeef);
463 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
464 ok( res == 123, "Got %ld instead of 123\n", res);
465
466 /* This also deletes the file */
467 CloseHandle(h);
468}
469
470static void test_profile_refresh(void)
471{
472 static const CHAR testfile[] = ".\\winetest4.ini";
473 HANDLE h;
474 DWORD size, res;
475 static const char contents1[] = "[" SECTION "]\n" KEY "=123\n";
476 static const char contents2[] = "[" SECTION "]\n" KEY "=124\n";
477
480 res = WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL );
481 ok( res, "Cannot write test file: %lx\n", GetLastError() );
482 ok( size == sizeof contents1 - 1, "Test file: partial write\n");
483
484 SetLastError(0xdeadbeef);
485 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
486 ok( res == 123, "Got %ld instead of 123\n", res);
487
488 CloseHandle(h);
489
490 /* Test proper invalidation of wine's profile file cache */
491
494 res = WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL );
495 ok( res, "Cannot write test file: %lx\n", GetLastError() );
496 ok( size == sizeof contents2 - 1, "Test file: partial write\n");
497
498 SetLastError(0xdeadbeef);
499 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
500 ok( res == 124, "Got %ld instead of 124\n", res);
501
502 /* This also deletes the file */
503 CloseHandle(h);
504
505 /* Cache must be invalidated if file no longer exists and default must be returned */
506 SetLastError(0xdeadbeef);
507 res = GetPrivateProfileIntA(SECTION, KEY, 421, testfile);
508 ok( res == 421, "Got %ld instead of 421\n", res);
509}
510
512{
513 HANDLE hfile;
514 DWORD count;
515
517 ok(hfile != INVALID_HANDLE_VALUE, "cannot create %s\n", name);
518 WriteFile(hfile, data, size, &count, NULL);
519 CloseHandle(hfile);
520}
521
522static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
523{
524 int i;
525
526 for(i = 0;i < MAX_PATH;++i)
527 if(emptystr[i] != 0)
528 {
529 trace("emptystr[%d] = %d\n",i,emptystr[i]);
530 return FALSE;
531 }
532
533 return TRUE;
534}
535
537{
538 BOOL ret;
539 CHAR path_folder[MAX_PATH];
540 CHAR path_file[MAX_PATH];
541 const char *sddl_string_everyone_readonly = "D:PAI(A;;0x1200a9;;;WD)";
542 SECURITY_ATTRIBUTES attributes = {0};
543 char lpStruct[] = { 's', 't', 'r', 'i', 'n', 'g' };
544
545 attributes.nLength = sizeof(attributes);
547 ok(ret == TRUE, "ConvertStringSecurityDescriptorToSecurityDescriptor failed: %ld\n", GetLastError());
548
549 GetTempPathA(MAX_PATH, path_folder);
550 lstrcatA(path_folder, "wine-test");
551
552 strcpy(path_file, path_folder);
553 lstrcatA(path_file, "\\tmp.ini");
554
555 ret = CreateDirectoryA(path_folder, &attributes);
556 ok(ret == TRUE, "CreateDirectoryA failed: %ld\n", GetLastError());
557
558 ret = WritePrivateProfileStringA("App", "key", "string", path_file);
559 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
560
561 ret = WritePrivateProfileSectionA("App", "key=string", path_file);
562 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
563
564 ret = WritePrivateProfileStructA("App", "key", lpStruct, sizeof(lpStruct), path_file);
565 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
566
567 ret = RemoveDirectoryA(path_folder);
568 ok(ret == TRUE, "RemoveDirectoryA failed: %ld\n", GetLastError());
569
571}
572
573static void test_GetPrivateProfileString(const char *content, const char *descript)
574{
575 DWORD ret, len;
577 CHAR def_val[MAX_PATH];
579 CHAR windir[MAX_PATH];
580 /* NT series crashes on r/o empty strings, so pass an r/w
581 empty string and check for modification */
582 CHAR emptystr[MAX_PATH] = "";
583 LPSTR tempfile;
584
585 static const char filename[] = ".\\winetest.ini";
586
587 trace("test_GetPrivateProfileStringA: %s\n", descript);
588
590
591 /* Run this test series with caching. Wine won't cache profile
592 files younger than 2.1 seconds. */
593 Sleep(2500);
594
595 /* lpAppName is NULL */
596 memset(buf, 0xc, sizeof(buf));
597 lstrcpyA(buf, "kumquat");
598 ret = GetPrivateProfileStringA(NULL, "name1", "default",
600 ok(ret == 18, "Expected 18, got %ld\n", ret);
601 len = lstrlenA("section1") + sizeof(CHAR) + lstrlenA("section2") + 2 * sizeof(CHAR);
602
603 ok(!memcmp(buf, "section1\0section2\0", len),
604 "Expected \"section1\\x00section2\\x00\\x00\", got %s\n",
605 debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
606
607 /* lpAppName is empty */
608 memset(buf, 0xc, sizeof(buf));
609 lstrcpyA(buf, "kumquat");
610 ret = GetPrivateProfileStringA(emptystr, "name1", "default",
612 ok(ret == 7, "Expected 7, got %ld\n", ret);
613 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
614 ok(emptystr_ok(emptystr), "AppName modified\n");
615
616 /* lpAppName is missing */
617 memset(buf, 0xc,sizeof(buf));
618 lstrcpyA(buf, "kumquat");
619 ret = GetPrivateProfileStringA("notasection", "name1", "default",
621 ok(ret == 7, "Expected 7, got %ld\n", ret);
622 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
623
624 /* lpAppName is empty, lpDefault is NULL */
625 memset(buf, 0xc,sizeof(buf));
626 lstrcpyA(buf, "kumquat");
627 ret = GetPrivateProfileStringA(emptystr, "name1", NULL,
629 ok(ret == 0, "Expected 0, got %ld\n", ret);
630 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
631 ok(emptystr_ok(emptystr), "AppName modified\n");
632
633 /* lpAppName is empty, lpDefault is empty */
634 memset(buf, 0xc,sizeof(buf));
635 lstrcpyA(buf, "kumquat");
636 ret = GetPrivateProfileStringA(emptystr, "name1", "",
638 ok(ret == 0, "Expected 0, got %ld\n", ret);
639 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
640 ok(emptystr_ok(emptystr), "AppName modified\n");
641
642 /* lpAppName is empty, lpDefault has trailing blank characters */
643 memset(buf, 0xc,sizeof(buf));
644 lstrcpyA(buf, "kumquat");
645 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
646 lstrcpyA(def_val, "default ");
647 ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
649 ok(ret == 7, "Expected 7, got %ld\n", ret);
650 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
651 ok(emptystr_ok(emptystr), "AppName modified\n");
652
653 /* lpAppName is empty, many blank characters in lpDefault */
654 memset(buf, 0xc,sizeof(buf));
655 lstrcpyA(buf, "kumquat");
656 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
657 lstrcpyA(def_val, "one two ");
658 ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
660 ok(ret == 7, "Expected 7, got %ld\n", ret);
661 ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
662 ok(emptystr_ok(emptystr), "AppName modified\n");
663
664 /* lpAppName is empty, blank character but not trailing in lpDefault */
665 memset(buf, 0xc,sizeof(buf));
666 lstrcpyA(buf, "kumquat");
667 ret = GetPrivateProfileStringA(emptystr, "name1", "one two",
669 ok(ret == 7, "Expected 7, got %ld\n", ret);
670 ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
671 ok(emptystr_ok(emptystr), "AppName modified\n");
672
673 /* lpKeyName is NULL */
674 memset(buf, 0xc,sizeof(buf));
675 lstrcpyA(buf, "kumquat");
676 ret = GetPrivateProfileStringA("section1", NULL, "default",
678 ok(ret == 18, "Expected 18, got %ld\n", ret);
679 ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
680 "Expected \"name1\\x00name2\\x00name4\\x00\\x00\", got %s\n",
681 debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
682
683 /* lpKeyName is empty */
684 memset(buf, 0xc,sizeof(buf));
685 lstrcpyA(buf, "kumquat");
686 ret = GetPrivateProfileStringA("section1", emptystr, "default",
688 ok(ret == 7, "Expected 7, got %ld\n", ret);
689 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
690 ok(emptystr_ok(emptystr), "KeyName modified\n");
691
692 /* lpKeyName is missing */
693 memset(buf, 0xc,sizeof(buf));
694 lstrcpyA(buf, "kumquat");
695 ret = GetPrivateProfileStringA("section1", "notakey", "default",
697 ok(ret == 7, "Expected 7, got %ld\n", ret);
698 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
699
700 /* lpKeyName is empty, lpDefault is NULL */
701 memset(buf, 0xc,sizeof(buf));
702 lstrcpyA(buf, "kumquat");
703 ret = GetPrivateProfileStringA("section1", emptystr, NULL,
705 ok(ret == 0, "Expected 0, got %ld\n", ret);
706 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
707 ok(emptystr_ok(emptystr), "KeyName modified\n");
708
709 /* lpKeyName is empty, lpDefault is empty */
710 memset(buf, 0xc,sizeof(buf));
711 lstrcpyA(buf, "kumquat");
712 ret = GetPrivateProfileStringA("section1", emptystr, "",
714 ok(ret == 0, "Expected 0, got %ld\n", ret);
715 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
716 ok(emptystr_ok(emptystr), "KeyName modified\n");
717
718 /* lpKeyName is empty, lpDefault has trailing blank characters */
719 memset(buf, 0xc,sizeof(buf));
720 lstrcpyA(buf, "kumquat");
721 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
722 lstrcpyA(def_val, "default ");
723 ret = GetPrivateProfileStringA("section1", emptystr, def_val,
725 ok(ret == 7, "Expected 7, got %ld\n", ret);
726 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
727 ok(emptystr_ok(emptystr), "KeyName modified\n");
728
729 if (0) /* crashes */
730 {
731 /* lpReturnedString is NULL */
732 ret = GetPrivateProfileStringA("section1", "name1", "default",
734 }
735
736 /* lpFileName is NULL */
737 memset(buf, 0xc,sizeof(buf));
738 lstrcpyA(buf, "kumquat");
739 ret = GetPrivateProfileStringA("section1", "name1", "default",
740 buf, MAX_PATH, NULL);
741 ok(ret == 7, "Expected 7, got %ld\n", ret);
742 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
743
744 /* lpFileName is empty */
745 memset(buf, 0xc,sizeof(buf));
746 lstrcpyA(buf, "kumquat");
747 ret = GetPrivateProfileStringA("section1", "name1", "default",
748 buf, MAX_PATH, "");
749 ok(ret == 7, "Expected 7, got %ld\n", ret);
750 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
751
752 /* lpFileName is nonexistent */
753 memset(buf, 0xc,sizeof(buf));
754 lstrcpyA(buf, "kumquat");
755 ret = GetPrivateProfileStringA("section1", "name1", "default",
756 buf, MAX_PATH, "nonexistent");
757 ok(ret == 7, "Expected 7, got %ld\n", ret);
758 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
759
760 /* nSize is 0 */
761 memset(buf, 0xc,sizeof(buf));
762 lstrcpyA(buf, "kumquat");
763 ret = GetPrivateProfileStringA("section1", "name1", "default",
764 buf, 0, filename);
765 ok(ret == 0, "Expected 0, got %ld\n", ret);
766 ok(!lstrcmpA(buf, "kumquat"), "Expected buf to be unchanged, got \"%s\"\n", buf);
767
768 /* nSize is exact size of output */
769 memset(buf, 0xc,sizeof(buf));
770 lstrcpyA(buf, "kumquat");
771 ret = GetPrivateProfileStringA("section1", "name1", "default",
772 buf, 4, filename);
773 ok(ret == 3, "Expected 3, got %ld\n", ret);
774 ok(!lstrcmpA(buf, "val"), "Expected \"val\", got \"%s\"\n", buf);
775
776 /* nSize has room for NULL terminator */
777 memset(buf, 0xc,sizeof(buf));
778 lstrcpyA(buf, "kumquat");
779 ret = GetPrivateProfileStringA("section1", "name1", "default",
780 buf, 5, filename);
781 ok(ret == 4, "Expected 4, got %ld\n", ret);
782 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
783
784 /* output is 1 character */
785 memset(buf, 0xc,sizeof(buf));
786 lstrcpyA(buf, "kumquat");
787 ret = GetPrivateProfileStringA("section1", "name4", "default",
789 ok(ret == 1, "Expected 1, got %ld\n", ret);
790 ok(!lstrcmpA(buf, "a"), "Expected \"a\", got \"%s\"\n", buf);
791
792 /* output is 1 character, no room for NULL terminator */
793 memset(buf, 0xc,sizeof(buf));
794 lstrcpyA(buf, "kumquat");
795 ret = GetPrivateProfileStringA("section1", "name4", "default",
796 buf, 1, filename);
797 ok(ret == 0, "Expected 0, got %ld\n", ret);
798 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
799
800 /* lpAppName is NULL, not enough room for final section name */
801 memset(buf, 0xc,sizeof(buf));
802 lstrcpyA(buf, "kumquat");
803 ret = GetPrivateProfileStringA(NULL, "name1", "default",
804 buf, 16, filename);
805 ok(ret == 14, "Expected 14, got %ld\n", ret);
806 len = lstrlenA("section1") + 2 * sizeof(CHAR);
808 ok(!memcmp(buf, "section1\0secti\0", ret + 2),
809 "Expected \"section1\\x00secti\\x00\\x00\", got %s\n",
810 debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
811
812 /* lpKeyName is NULL, not enough room for final key name */
813 memset(buf, 0xc,sizeof(buf));
814 lstrcpyA(buf, "kumquat");
815 ret = GetPrivateProfileStringA("section1", NULL, "default",
816 buf, 16, filename);
817 ok(ret == 14, "Expected 14, got %ld\n", ret);
819 ok(!memcmp(buf, "name1\0name2\0na\0", ret + 2),
820 "Expected \"name1\\x00name2\\x00na\\x00\\x00\", got %s\n",
821 debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
822
823 /* key value has quotation marks which are stripped */
824 memset(buf, 0xc,sizeof(buf));
825 lstrcpyA(buf, "kumquat");
826 ret = GetPrivateProfileStringA("section1", "name2", "default",
828 ok(ret == 4, "Expected 4, got %ld\n", ret);
829 ok(!lstrcmpA(buf, "val2"), "Expected \"val2\", got \"%s\"\n", buf);
830
831 /* case does not match */
832 memset(buf, 0xc,sizeof(buf));
833 lstrcpyA(buf, "kumquat");
834 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
836 ok(ret == 4, "Expected 4, got %ld\n", ret);
837 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
838
839 /* only filename is used */
840 memset(buf, 0xc,sizeof(buf));
841 lstrcpyA(buf, "kumquat");
842 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
843 buf, MAX_PATH, "winetest.ini");
844 ok(ret == 7, "Expected 7, got %ld\n", ret);
845 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
846
848 SetLastError(0xdeadbeef);
849 ret = GetTempFileNameA(windir, "pre", 0, path);
851 {
852 skip("Not allowed to create a file in the Windows directory\n");
854 return;
855 }
856 tempfile = strrchr(path, '\\') + 1;
858
859 /* only filename is used, file exists in windows directory */
860 memset(buf, 0xc,sizeof(buf));
861 lstrcpyA(buf, "kumquat");
862 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
863 buf, MAX_PATH, tempfile);
864 ok(ret == 4, "Expected 4, got %ld\n", ret);
865 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
866
867 /* successful case */
868 memset(buf, 0xc,sizeof(buf));
869 lstrcpyA(buf, "kumquat");
870 ret = GetPrivateProfileStringA("section1", "name1", "default",
872 ok(ret == 4, "Expected 4, got %ld\n", ret);
873 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
874
875 /* Existing section with no keys in an existing file */
876 memset(buf, 0xc,sizeof(buf));
877 SetLastError(0xdeadbeef);
878 ret=GetPrivateProfileStringA("section2", "DoesntExist", "",
880 ok( ret == 0, "expected return size 0, got %ld\n", ret );
881 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
883 ok( GetLastError() == 0xdeadbeef ||
884 GetLastError() == ERROR_FILE_NOT_FOUND /* Win 7 */,
885 "expected 0xdeadbeef or ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
886
887
890}
891
893{
894 HANDLE file;
896 BOOL ret;
897
900 return FALSE;
901
902 if(size != GetFileSize(file, NULL) )
903 {
905 return FALSE;
906 }
907
908 ret = ReadFile(file, buf, size, &size, NULL);
910 if (!ret)
911 return FALSE;
912
913 return !memcmp(buf, data, size);
914}
915
917{
919}
920
922{
923 BOOL ret;
924 LPCSTR data;
927 HANDLE file;
928
930 GetTempFileNameA(temp, "wine", 0, path);
932
933 /* path is not created yet */
934
935 /* NULL lpAppName */
936 SetLastError(0xdeadbeef);
937 ret = WritePrivateProfileStringA(NULL, "key", "string", path);
938 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
940 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
942 "Expected path to not exist\n");
943
944 GetTempFileNameA(temp, "wine", 0, path);
945
946 /* NULL lpAppName, path exists */
947 data = "";
948 SetLastError(0xdeadbeef);
949 ret = WritePrivateProfileStringA(NULL, "key", "string", path);
950 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
952 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
953 ok(check_file_data(path, data), "File doesn't match\n");
955
956 if (0)
957 {
958 /* empty lpAppName, crashes on NT4 and higher */
959 data = "[]\r\n"
960 "key=string\r\n";
961 ret = WritePrivateProfileStringA("", "key", "string", path);
962 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
963 ok(check_file_data(path, data), "File doesn't match\n");
965 }
966
967 /* NULL lpKeyName */
968 data = "";
969 ret = WritePrivateProfileStringA("App", NULL, "string", path);
970 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
972 {
973 ok(check_file_data(path, data), "File doesn't match\n");
974 }
976
977 if (0)
978 {
979 /* empty lpKeyName, crashes on NT4 and higher */
980 data = "[App]\r\n"
981 "=string\r\n";
982 ret = WritePrivateProfileStringA("App", "", "string", path);
983 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
985 {
986 ok(check_file_data(path, data), "File doesn't match\n");
987 }
989 }
990
991 /* NULL lpString */
992 data = "";
993 ret = WritePrivateProfileStringA("App", "key", NULL, path);
994 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
996 {
997 ok(check_file_data(path, data), "File doesn't match\n");
998 }
1000
1001 /* empty lpString */
1002 data = "[App]\r\n"
1003 "key=\r\n";
1004 ret = WritePrivateProfileStringA("App", "key", "", path);
1005 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1006 ok(check_file_data(path, data), "File doesn't match\n");
1008
1009 /* empty lpFileName */
1010 SetLastError(0xdeadbeef);
1011 ret = WritePrivateProfileStringA("App", "key", "string", "");
1012 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1014 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError());
1015
1016 /* Relative paths are relative to X:\\%WINDIR% */
1018 strcat(path, "\\win1.tmp");
1021 skip("Not allowed to create a file in the Windows directory\n");
1022 else
1023 {
1026
1027 data = "[App]\r\n"
1028 "key=string\r\n";
1029 ret = WritePrivateProfileStringA("App", "key", "string", "win1.tmp");
1030 ok(ret == TRUE, "Expected TRUE, got %d, le=%lu\n", ret, GetLastError());
1031 ok(check_file_data(path, data), "File doesn't match\n");
1033 }
1034
1036 GetTempFileNameA(temp, "wine", 0, path);
1037
1038 /* build up an INI file */
1039 WritePrivateProfileStringA("App1", "key1", "string1", path);
1040 WritePrivateProfileStringA("App1", "key2", "string2", path);
1041 WritePrivateProfileStringA("App1", "key3", "string3", path);
1042 WritePrivateProfileStringA("App2", "key4", "string4", path);
1043
1044 /* make an addition and verify the INI */
1045 data = "[App1]\r\n"
1046 "key1=string1\r\n"
1047 "key2=string2\r\n"
1048 "key3=string3\r\n"
1049 "[App2]\r\n"
1050 "key4=string4\r\n"
1051 "[App3]\r\n"
1052 "key5=string5\r\n";
1053 ret = WritePrivateProfileStringA("App3", "key5", "string5", path);
1054 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1055 ok(check_file_data(path, data), "File doesn't match\n");
1056
1057 /* lpString is NULL, key2 key is deleted */
1058 data = "[App1]\r\n"
1059 "key1=string1\r\n"
1060 "key3=string3\r\n"
1061 "[App2]\r\n"
1062 "key4=string4\r\n"
1063 "[App3]\r\n"
1064 "key5=string5\r\n";
1065 ret = WritePrivateProfileStringA("App1", "key2", NULL, path);
1066 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1067 ok(check_file_data(path, data), "File doesn't match\n");
1068
1069 /* try to delete key2 again */
1070 data = "[App1]\r\n"
1071 "key1=string1\r\n"
1072 "key3=string3\r\n"
1073 "[App2]\r\n"
1074 "key4=string4\r\n"
1075 "[App3]\r\n"
1076 "key5=string5\r\n";
1077 ret = WritePrivateProfileStringA("App1", "key2", NULL, path);
1078 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1079 ok(check_file_data(path, data), "File doesn't match\n");
1080
1081 /* lpKeyName is NULL, App1 section is deleted */
1082 data = "[App2]\r\n"
1083 "key4=string4\r\n"
1084 "[App3]\r\n"
1085 "key5=string5\r\n";
1086 ret = WritePrivateProfileStringA("App1", NULL, "string1", path);
1087 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1088 ok(check_file_data(path, data), "File doesn't match\n");
1089
1090 /* lpString is not needed to delete a section */
1091 data = "[App3]\r\n"
1092 "key5=string5\r\n";
1094 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1095 ok(check_file_data(path, data), "File doesn't match\n");
1096
1097 /* leave just the section */
1098 data = "[App3]\r\n";
1099 ret = WritePrivateProfileStringA("App3", "key5", NULL, path);
1100 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1101 ok(check_file_data(path, data), "File doesn't match\n");
1103
1104 /* NULLs in file before first section. Should be preserved in output */
1105 data = "Data \0 before \0 first \0 section" /* 31 bytes */
1106 "\r\n[section1]\r\n" /* 14 bytes */
1107 "key1=string1\r\n"; /* 14 bytes */
1108 GetTempFileNameA(temp, "wine", 0, path);
1110 ret = WritePrivateProfileStringA("section1", "key1", "string1", path);
1111 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1112 todo_wine
1113 ok( check_binary_file_data(path, data, 59), "File doesn't match\n");
1115}
1116
1117static void test_profile_struct(void)
1118{
1119 static const char expect_data[] = "[s]\r\nkey=616261637573006F\r\n";
1120 static const char expect_data_empty[] = "[s]\r\n";
1121 char buffer[20];
1122 BOOL ret;
1123
1124 SetLastError(0xdeadbeef);
1125 ret = GetPrivateProfileStructA("s", "key", buffer, sizeof(buffer), "./winetest.ini");
1126 ok(!ret, "expected failure\n");
1127 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %lu\n", GetLastError());
1128
1129 ret = WritePrivateProfileStructA("s", "key", (void *)"abacus", sizeof("abacus"), "./winetest.ini");
1130 ok(ret, "got error %lu\n", GetLastError());
1131 ok(check_file_data("./winetest.ini", expect_data), "file doesn't match\n");
1132
1133 SetLastError(0xdeadbeef);
1134 ret = GetPrivateProfileStructA("s", "key", buffer, 6, "./winetest.ini");
1135 ok(!ret, "expected failure\n");
1136 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %lu\n", GetLastError());
1137
1138 SetLastError(0xdeadbeef);
1139 ret = GetPrivateProfileStructA("s", "key", buffer, 8, "./winetest.ini");
1140 ok(!ret, "expected failure\n");
1141 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %lu\n", GetLastError());
1142
1143 memset(buffer, 0xcc, sizeof(buffer));
1144 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1145 ok(ret, "got error %lu\n", GetLastError());
1146 ok(!strcmp(buffer, "abacus"), "data didn't match\n");
1147
1148 memset(buffer, 0xcc, sizeof(buffer));
1149 ret = GetPrivateProfileStringA("s", "key", "default", buffer, sizeof(buffer), "./winetest.ini");
1150 ok(ret == 16, "got size %u\n", ret);
1151 ok(!strcmp(buffer, "616261637573006F"), "got %s\n", debugstr_a(buffer));
1152
1153 ret = WritePrivateProfileStringA("s", "key", "636163747573006F", "./winetest.ini");
1154 ok(ret, "got error %lu\n", GetLastError());
1155
1156 SetLastError(0xdeadbeef);
1157 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1158 ok(!ret, "expected failure\n");
1159 todo_wine ok(GetLastError() == ERROR_INVALID_DATA, "got error %lu\n", GetLastError());
1160
1161 ret = WritePrivateProfileStringA("s", "key", "6361637475730083", "./winetest.ini");
1162 ok(ret, "got error %lu\n", GetLastError());
1163
1164 memset(buffer, 0xcc, sizeof(buffer));
1165 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1166 ok(ret, "got error %lu\n", GetLastError());
1167 ok(!strcmp(buffer, "cactus"), "data didn't match\n");
1168
1169 ret = WritePrivateProfileStringA("s", "key", "636163747573008Q", "./winetest.ini");
1170 ok(ret, "got error %lu\n", GetLastError());
1171
1172 SetLastError(0xdeadbeef);
1173 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1174 ok(!ret, "expected failure\n");
1175 todo_wine ok(GetLastError() == ERROR_INVALID_DATA, "got error %lu\n", GetLastError());
1176
1177 ret = WritePrivateProfileStringA("s", "key", "16361637475730083", "./winetest.ini");
1178 ok(ret, "got error %lu\n", GetLastError());
1179
1180 SetLastError(0xdeadbeef);
1181 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1182 ok(!ret, "expected failure\n");
1183 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %lu\n", GetLastError());
1184
1185 /* Test deleting struct */
1186#ifdef __REACTOS__
1187 if (is_reactos()) {
1188 ok(FALSE, "FIXME: Deleting private profile struct crashes on ReactOS!\n");
1189 } else {
1190#endif
1191 ret = WritePrivateProfileStructA("s", "key", NULL, sizeof("abacus"), "./winetest.ini");
1192 ok(ret, "got error %lu\n", GetLastError());
1193 ok(check_file_data("./winetest.ini", expect_data_empty), "file doesn't match\n");
1194#ifdef __REACTOS__
1195 }
1196#endif
1197
1198 ret = DeleteFileA("./winetest.ini");
1199 ok(ret, "got error %lu\n", GetLastError());
1200}
1201
1202static void check_registry_value_(int line, HKEY key, const char *value, const char *expect)
1203{
1204 char buffer[30];
1205 DWORD type, size = sizeof(buffer);
1206 LSTATUS ret;
1207
1208 memset(buffer, 0xcc, sizeof(buffer));
1210 ok_(__FILE__, line)(!ret, "got error %lu\n", ret);
1211 ok_(__FILE__, line)(!strcmp(buffer, expect), "expected %s, got %s\n", debugstr_a(expect), debugstr_a(buffer));
1212 ok_(__FILE__, line)(type == REG_SZ, "got type %lu\n", type);
1213}
1214#define check_registry_value(a, b, c) check_registry_value_(__LINE__, a, b, c)
1215
1216static void test_registry_mapping(void)
1217{
1218 static const DWORD ivalue = 0xabacab;
1219 HKEY mapping_key, mapped_key, mapping_subkey;
1220 char buffer[30];
1221 LSTATUS ret;
1222#ifdef __REACTOS__
1223 char path[MAX_PATH];
1224
1225 /* Get the real system root, use forward slashes, and lowercase everything other than "C:\" */
1226 GetWindowsDirectoryA(path, sizeof(path));
1227 for (char *p = path; *p; p++)
1228 if (*p == '\\') *p = '/';
1229 else if (p != path) *p = (char)tolower((unsigned char)*p);
1230 strcat(path, "/winetest_map.ini");
1231#endif
1232
1233 /* impersonate ourselves to prevent registry virtualization */
1235 ok(ret, "got error %lu\n", GetLastError());
1236
1238 "Software\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\winetest_map.ini",
1239 0, NULL, 0, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, NULL, &mapping_key, NULL);
1240 if (ret == ERROR_ACCESS_DENIED)
1241 {
1242 skip("Not enough permissions to write to the IniFileMapping key.\n");
1243 return;
1244 }
1245 ok(!ret, "got error %lu\n", ret);
1246
1247 ret = RegSetValueExA(mapping_key, "section1", 0, REG_SZ, (BYTE *)"USR:winetest_map", sizeof("USR:winetest_map"));
1248 ok(!ret, "got error %lu\n", ret);
1249 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1250 todo_wine ok(ret, "got error %lu\n", GetLastError());
1251
1252 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1253
1254 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1255 ok(ret, "got error %lu\n", GetLastError());
1256
1257 check_profile_string("section1", "name1", "winetest_map.ini", "value1");
1258 check_profile_string("section1", "name1", "C:/fake/path/winetest_map.ini", "value1");
1259
1260 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1261 ok(!ret, "got error %lu\n", ret);
1262 check_registry_value(mapped_key, "name1", "value1");
1263
1264 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1265 ok(!ret, "got error %lu\n", ret);
1266
1267 check_profile_string("section1", "name2", "winetest_map.ini", "value2");
1268
1269#ifdef __REACTOS__
1271#else
1272 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1273#endif
1274 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1275
1276 ret = WritePrivateProfileStringA("section1", "name2", NULL, "winetest_map.ini");
1277 ok(ret, "got error %lu\n", GetLastError());
1278 ret = RegQueryValueExA(mapped_key, "name2", 0, NULL, NULL, NULL);
1279 ok(ret == ERROR_FILE_NOT_FOUND, "got error %lu\n", ret);
1280
1281 /* Test non-string types. */
1282
1283 ret = RegSetValueExA(mapped_key, "name3", 0, REG_DWORD, (BYTE *)&ivalue, sizeof(ivalue));
1284 ok(!ret, "got error %lu\n", ret);
1285 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1286
1287 ret = GetPrivateProfileIntA("section1", "name3", 0, "winetest_map.ini");
1288 ok(ret == 0, "got %#lx\n", ret);
1289
1290 ret = RegSetValueExA(mapped_key, "name3", 0, REG_BINARY, (BYTE *)"value3", sizeof("value3"));
1291 ok(!ret, "got error %lu\n", ret);
1292 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1293
1294 ret = RegSetValueExA(mapped_key, "name3", 0, REG_MULTI_SZ, (BYTE *)"one\0two\0", sizeof("one\0two\0"));
1295 ok(!ret, "got error %lu\n", ret);
1296 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1297
1298 ret = RegSetValueExA(mapped_key, "name3", 0, REG_EXPAND_SZ, (BYTE *)"x%SystemRoot%", sizeof("x%SystemRoot%"));
1299 ok(!ret, "got error %lu\n", ret);
1300 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1301
1302 /* Test WritePrivateProfileSection(). Unlike with .ini files, it doesn't
1303 * remove existing entries. */
1304
1305 ret = WritePrivateProfileStringA("section1", "name4", "value4", "winetest_map.ini");
1306 ok(ret, "got error %lu\n", GetLastError());
1307 ret = WritePrivateProfileStringA("section1", "name5", "value5", "winetest_map.ini");
1308 ok(ret, "got error %lu\n", GetLastError());
1309 ret = WritePrivateProfileSectionA("section1", "name4=four\0name6=six\0", "winetest_map.ini");
1310 ok(ret, "got error %lu\n", GetLastError());
1311 check_profile_string("section1", "name4", "winetest_map.ini", "four");
1312 check_profile_string("section1", "name5", "winetest_map.ini", "value5");
1313 check_profile_string("section1", "name6", "winetest_map.ini", "six");
1314
1315 /* Test deleting the section. */
1316
1317 RegCloseKey(mapped_key);
1318
1319 ret = RegCreateKeyExA(HKEY_CURRENT_USER, "winetest_map\\subkey", 0, NULL, 0, 0, NULL, &mapped_key, NULL);
1320 ok(!ret, "got error %lu\n", ret);
1321 RegCloseKey(mapped_key);
1322
1323 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1324 ok(ret, "got error %lu\n", GetLastError());
1325 ret = WritePrivateProfileStringA("section1", NULL, NULL, "winetest_map.ini");
1326 ok(ret, "got error %lu\n", GetLastError());
1327 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1328
1329 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1330 ok(ret, "got error %lu\n", GetLastError());
1331 ret = WritePrivateProfileSectionA("section1", NULL, "winetest_map.ini");
1332 ok(ret, "got error %lu\n", GetLastError());
1333 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1334
1335 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_map\\subkey");
1336 ok(!ret, "got error %lu\n", ret);
1337 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_map");
1338 ok(!ret, "got error %lu\n", ret);
1339
1340 /* Test GetPrivateProfileSectionNames(). */
1341
1342 memset(buffer, 0xcc, sizeof(buffer));
1343 ret = GetPrivateProfileSectionNamesA(buffer, 5, "winetest_map.ini");
1344 ok(ret == 3, "got %lu\n", ret);
1345 ok(!memcmp(buffer, "sec\0", 5), "got %s\n", debugstr_an(buffer, ret));
1346
1347 memset(buffer, 0xcc, sizeof(buffer));
1348 ret = GetPrivateProfileSectionNamesA(buffer, sizeof(buffer), "winetest_map.ini");
1349 ok(ret == 9, "got %lu\n", ret);
1350 ok(!memcmp(buffer, "section1\0", 10), "got %s\n", debugstr_an(buffer, ret));
1351
1352 ret = WritePrivateProfileStringA("file_section", "name1", "value1", "winetest_map.ini");
1353 ok(ret, "got error %lu\n", GetLastError());
1354
1355 memset(buffer, 0xcc, sizeof(buffer));
1356 ret = GetPrivateProfileSectionNamesA(buffer, 5, "winetest_map.ini");
1357 ok(ret == 3, "got %lu\n", ret);
1358 ok(!memcmp(buffer, "sec\0", 5), "got %s\n", debugstr_an(buffer, ret));
1359
1360 memset(buffer, 0xcc, sizeof(buffer));
1361 ret = GetPrivateProfileSectionNamesA(buffer, sizeof(buffer), "winetest_map.ini");
1362 ok(ret == 22, "got %lu\n", ret);
1363 ok(!memcmp(buffer, "section1\0file_section\0", 23), "got %s\n", debugstr_an(buffer, ret));
1364
1365#ifdef __REACTOS__
1366 ret = DeleteFileA(path);
1367#else
1368 ret = DeleteFileA("C:/windows/winetest_map.ini");
1369#endif
1370 ok(ret, "got error %lu\n", GetLastError());
1371
1372 /* Test the SYS: prefix. */
1373
1374 ret = RegSetValueExA(mapping_key, "section2", 0, REG_SZ, (BYTE *)"SYS:winetest_map", sizeof("SYS:winetest_map"));
1375 ok(!ret, "got error %lu\n", ret);
1376 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1377 todo_wine ok(ret, "got error %lu\n", GetLastError());
1378
1379 check_profile_string("section2", "name1", "winetest_map.ini", "default");
1380
1381 ret = WritePrivateProfileStringA("section2", "name1", "value1", "winetest_map.ini");
1382 ok(ret, "got error %lu\n", GetLastError());
1383
1384 check_profile_string("section2", "name1", "winetest_map.ini", "value1");
1385
1386 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1387 ok(!ret, "got error %lu\n", ret);
1388 check_registry_value(mapped_key, "name1", "value1");
1389
1390 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1391 ok(!ret, "got error %lu\n", ret);
1392
1393 check_profile_string("section2", "name2", "winetest_map.ini", "value2");
1394
1395#ifdef __REACTOS__
1397#else
1398 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1399#endif
1400 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1401
1402 ret = RegDeleteKeyA(mapped_key, "");
1403 ok(!ret, "got error %lu\n", ret);
1404 RegCloseKey(mapped_key);
1405
1406 /* Try writing directly to the .ini file on disk instead. */
1407
1408 ret = WritePrivateProfileStringA("section3", "name1", "value1", "winetest_map.ini");
1409 ok(ret, "got error %lu\n", GetLastError());
1410 check_profile_string("section3", "name1", "winetest_map.ini", "value1");
1411
1412 ret = RegSetValueExA(mapping_key, "section3", 0, REG_SZ, (BYTE *)"USR:winetest_map", sizeof("USR:winetest_map"));
1413 ok(!ret, "got error %lu\n", ret);
1414 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1415 todo_wine ok(ret, "got error %lu\n", GetLastError());
1416
1417 check_profile_string("section3", "name1", "winetest_map.ini", "default");
1418
1419 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_section3", 0, KEY_READ | KEY_WRITE, &mapped_key);
1420 ok(ret == ERROR_FILE_NOT_FOUND, "got error %lu\n", ret);
1421
1422 ret = WritePrivateProfileStringA("section3", "name1", "value2", "winetest_map.ini");
1423 ok(ret, "got error %lu\n", GetLastError());
1424
1425 check_profile_string("section3", "name1", "winetest_map.ini", "value2");
1426
1427 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1428 ok(!ret, "got error %lu\n", ret);
1429
1430 ret = RegDeleteKeyA(mapped_key, "");
1431 ok(!ret, "got error %lu\n", ret);
1432 RegCloseKey(mapped_key);
1433
1434 ret = RegDeleteValueA(mapping_key, "section3");
1435 ok(!ret, "got error %lu\n", ret);
1436 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1437 todo_wine ok(ret, "got error %lu\n", GetLastError());
1438
1439 check_profile_string("section3", "name1", "winetest_map.ini", "value1");
1440
1441#ifdef __REACTOS__
1442 ret = DeleteFileA(path);
1443#else
1444 ret = DeleteFileA("C:/windows/winetest_map.ini");
1445#endif
1446 ok(ret, "got error %lu\n", GetLastError());
1447
1448 /* Test default keys. */
1449
1450 ret = WritePrivateProfileStringA("section4", "name1", "value1", "winetest_map.ini");
1451 ok(ret, "got error %lu\n", GetLastError());
1452
1453 check_profile_string("section4", "name1", "winetest_map.ini", "value1");
1454
1455#ifdef __REACTOS__
1456 ret = DeleteFileA(path);
1457#else
1458 ret = DeleteFileA("C:/windows/winetest_map.ini");
1459#endif
1460 ok(ret, "got error %lu\n", GetLastError());
1461
1462 ret = RegSetValueExA(mapping_key, NULL, 0, REG_SZ, (BYTE *)"SYS:winetest_default", sizeof("SYS:winetest_default"));
1463 ok(!ret, "got error %lu\n", ret);
1464 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1465 todo_wine ok(ret, "got error %lu\n", GetLastError());
1466
1467 ret = WritePrivateProfileStringA("section4", "name1", "value1", "winetest_map.ini");
1468 ok(ret, "got error %lu\n", GetLastError());
1469
1470 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\section4", 0, KEY_READ, &mapped_key);
1471 ok(!ret, "got error %lu\n", ret);
1472 check_registry_value(mapped_key, "name1", "value1");
1473 RegCloseKey(mapped_key);
1474
1475 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\section5",
1476 0, NULL, 0, KEY_WRITE, NULL, &mapped_key, NULL);
1477 ok(!ret, "got error %lu\n", ret);
1478 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1479 ok(!ret, "got error %lu\n", ret);
1480 RegCloseKey(mapped_key);
1481
1482 check_profile_string("section5", "name2", "winetest_map.ini", "value2");
1483
1484#ifdef __REACTOS__
1486#else
1487 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1488#endif
1489 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1490
1491 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\Section4");
1492 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\Section5");
1493 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default");
1494 ok(!ret, "got error %lu\n", ret);
1495 ret = RegDeleteValueA(mapping_key, NULL);
1496 ok(!ret, "got error %lu\n", ret);
1497
1498 /* Test name-specific mapping. */
1499
1500 ret = RegCreateKeyExA(mapping_key, "section6", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &mapping_subkey, NULL);
1501 ok(!ret, "got error %lu\n", ret);
1502 ret = RegSetValueExA(mapping_subkey, "name1", 0, REG_SZ, (BYTE *)"USR:winetest_name1", sizeof("USR:winetest_name1"));
1503 ok(!ret, "got error %lu\n", ret);
1504 ret = RegSetValueExA(mapping_subkey, "name2", 0, REG_SZ, (BYTE *)"SYS:winetest_name2", sizeof("SYS:winetest_name2"));
1505 ok(!ret, "got error %lu\n", ret);
1506 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1507 todo_wine ok(ret, "got error %lu\n", GetLastError());
1508
1509 ret = WritePrivateProfileStringA("section6", "name1", "value1", "winetest_map.ini");
1510 ok(ret, "got error %lu\n", GetLastError());
1511 check_profile_string("section6", "name1", "winetest_map.ini", "value1");
1512
1513 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_name1", 0, KEY_READ | KEY_WRITE, &mapped_key);
1514 ok(!ret, "got error %lu\n", ret);
1515 check_registry_value(mapped_key, "name1", "value1");
1516
1517 ret = RegSetValueExA(mapped_key, "name1", 0, REG_SZ, (BYTE *)"one", sizeof("one"));
1518 ok(!ret, "got error %lu\n", ret);
1519 check_profile_string("section6", "name1", "winetest_map.ini", "one");
1520
1521 ret = RegDeleteKeyA(mapped_key, "");
1522 ok(!ret, "got error %lu\n", ret);
1523 RegCloseKey(mapped_key);
1524
1525 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1526 ok(ret, "got error %lu\n", GetLastError());
1527
1528 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2", 0, KEY_READ | KEY_WRITE, &mapped_key);
1529 ok(!ret, "got error %lu\n", ret);
1530 check_registry_value(mapped_key, "name2", "value2");
1531
1532 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"two", sizeof("two"));
1533 ok(!ret, "got error %lu\n", ret);
1534 check_profile_string("section6", "name2", "winetest_map.ini", "two");
1535
1536 ret = RegDeleteKeyA(mapped_key, "");
1537 ok(!ret, "got error %lu\n", ret);
1538 RegCloseKey(mapped_key);
1539
1540 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1541 ok(ret, "got error %lu\n", GetLastError());
1542 check_profile_string("section6", "name3", "winetest_map.ini", "value3");
1543#ifdef __REACTOS__
1544 ret = DeleteFileA(path);
1545#else
1546 ret = DeleteFileA("C:/windows/winetest_map.ini");
1547#endif
1548 ok(ret, "got error %lu\n", GetLastError());
1549
1550 /* Test name-specific mapping with Get/WritePrivateProfileSection(). */
1551
1552 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1553 ok(ret, "got error %lu\n", GetLastError());
1554
1555 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1556 ok(ret, "got error %lu\n", GetLastError());
1557
1558 ret = WritePrivateProfileSectionA("section6", "name1=one\0name3=three\0", "winetest_map.ini");
1559 ok(ret, "got error %lu\n", GetLastError());
1560 check_profile_string("section6", "name1", "winetest_map.ini", "one");
1561 check_profile_string("section6", "name2", "winetest_map.ini", "value2");
1562 check_profile_string("section6", "name3", "winetest_map.ini", "value3");
1563
1564 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_name1", 0, KEY_READ | KEY_WRITE, &mapped_key);
1565 ok(!ret, "got error %lu\n", ret);
1566 ret = RegDeleteValueA(mapped_key, "name1");
1567 ok(!ret, "got error %lu\n", ret);
1568 RegCloseKey(mapped_key);
1569
1570 memset(buffer, 0xcc, sizeof(buffer));
1571 ret = GetPrivateProfileSectionA("section6", buffer, 5, "winetest_map.ini");
1572 ok(ret == 3, "got %lu\n", ret);
1573 ok(!memcmp(buffer, "nam\0", 5), "got %s\n", debugstr_an(buffer, ret));
1574
1575 memset(buffer, 0xcc, sizeof(buffer));
1576 ret = GetPrivateProfileSectionA("section6", buffer, sizeof(buffer), "winetest_map.ini");
1577 ok(ret == 26, "got %lu\n", ret);
1578 ok(!memcmp(buffer, "name2=value2\0name3=value3\0", 27), "got %s\n", debugstr_an(buffer, ret));
1579
1580 ret = WritePrivateProfileStringA("section6", NULL, NULL, "winetest_map.ini");
1581 ok(ret, "got error %lu\n", GetLastError());
1582 check_profile_string("section6", "name1", "winetest_map.ini", "default");
1583 check_profile_string("section6", "name2", "winetest_map.ini", "default");
1584 check_profile_string("section6", "name3", "winetest_map.ini", "default");
1585
1586 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_name1");
1587 ok(!ret, "got error %lu\n", ret);
1588 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2");
1589 ok(!ret, "got error %lu\n", ret);
1590#ifdef __REACTOS__
1591 ret = DeleteFileA(path);
1592#else
1593 ret = DeleteFileA("C:/windows/winetest_map.ini");
1594#endif
1595 ok(ret, "got error %lu\n", GetLastError());
1596
1597 /* Test name-specific mapping with a default value. */
1598
1599 ret = RegSetValueExA(mapping_subkey, NULL, 0, REG_SZ, (BYTE *)"USR:winetest_default", sizeof("USR:winetest_default"));
1600 ok(!ret, "got error %lu\n", ret);
1601 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1602 todo_wine ok(ret, "got error %lu\n", GetLastError());
1603
1604 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1605 ok(ret, "got error %lu\n", GetLastError());
1606 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1607 ok(ret, "got error %lu\n", GetLastError());
1608
1609 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_default", 0, KEY_READ | KEY_WRITE, &mapped_key);
1610 ok(!ret, "got error %lu\n", ret);
1611 check_registry_value(mapped_key, "name3", "value3");
1612
1613 ret = RegSetValueExA(mapped_key, "name3", 0, REG_SZ, (BYTE *)"three", sizeof("three"));
1614 ok(!ret, "got error %lu\n", ret);
1615 check_profile_string("section6", "name3", "winetest_map.ini", "three");
1616
1617 memset(buffer, 0xcc, sizeof(buffer));
1618 ret = GetPrivateProfileSectionA("section6", buffer, sizeof(buffer), "winetest_map.ini");
1619 ok(ret == 25, "got %lu\n", ret);
1620 todo_wine ok(!memcmp(buffer, "name2=value2\0name3=three\0", 26), "got %s\n", debugstr_an(buffer, ret));
1621
1622 ret = WritePrivateProfileSectionA("section6", "name2=duo\0name3=treis\0", "winetest_map.ini");
1623 ok(ret, "got error %lu\n", GetLastError());
1624 check_profile_string("section6", "name2", "winetest_map.ini", "duo");
1625 check_profile_string("section6", "name3", "winetest_map.ini", "treis");
1626
1627 ret = WritePrivateProfileStringA("section6", NULL, NULL, "winetest_map.ini");
1628 ok(ret, "got error %lu\n", GetLastError());
1629 check_profile_string("section6", "name2", "winetest_map.ini", "default");
1630 check_profile_string("section6", "name3", "winetest_map.ini", "default");
1631
1632 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2");
1633 ok(!ret, "got error %lu\n", ret);
1634 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_name1");
1635 ok(!ret, "got error %lu\n", ret);
1636 ret = RegDeleteKeyA(mapped_key, "");
1637 ok(!ret, "got error %lu\n", ret);
1638 RegCloseKey(mapped_key);
1639
1640 ret = RegDeleteKeyA(mapping_subkey, "");
1641 ok(!ret, "got error %lu\n", ret);
1642 RegCloseKey(mapping_subkey);
1643
1644 ret = RegDeleteKeyA(mapping_key, "");
1645 ok(!ret, "got error %lu\n", ret);
1646 RegCloseKey(mapping_key);
1647
1648#ifdef __REACTOS__
1649 ret = DeleteFileA(path);
1650#else
1651 ret = DeleteFileA("C:/windows/winetest_map.ini");
1652#endif
1653 ok(!ret, "expected failure\n");
1654 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError());
1655 ret = RevertToSelf();
1656 ok(ret, "got error %lu\n", GetLastError());
1657}
1658
1660{
1670 "[section1]\r\n"
1671 "name1=val1\r\n"
1672 "name2=\"val2\"\r\n"
1673 "name3\r\n"
1674 "name4=a\r\n"
1675 "[section2]\r\n",
1676 "CR+LF");
1678 "[section1]\r"
1679 "name1=val1\r"
1680 "name2=\"val2\"\r"
1681 "name3\r"
1682 "name4=a\r"
1683 "[section2]\r",
1684 "CR only");
1688}
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define ARRAY_SIZE(A)
Definition: main.h:20
#define CHAR(Char)
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
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 RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
LONG WINAPI RegCreateKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD Reserved, _In_ LPSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_ LPDWORD lpdwDisposition)
Definition: reg.c:1034
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor, DWORD StringSDRevision, PSECURITY_DESCRIPTOR *SecurityDescriptor, PULONG SecurityDescriptorSize)
Definition: security.c:3032
BOOL WINAPI ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
Definition: security.c:1631
content
Definition: atl_ax.c:994
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#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 * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define FILE_SHARE_READ
Definition: compat.h:136
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
UINT WINAPI GetWindowsDirectoryA(OUT LPSTR lpBuffer, IN UINT uSize)
Definition: path.c:2337
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
DWORD WINAPI GetPrivateProfileSectionNamesW(LPWSTR buffer, DWORD size, LPCWSTR filename)
Definition: profile.c:1641
INT WINAPI GetPrivateProfileSectionA(LPCSTR section, LPSTR buffer, DWORD len, LPCSTR filename)
Definition: profile.c:1381
BOOL WINAPI WritePrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buf, UINT bufsize, LPCSTR filename)
Definition: profile.c:1838
BOOL WINAPI WritePrivateProfileSectionA(LPCSTR section, LPCSTR string, LPCSTR filename)
Definition: profile.c:1553
INT WINAPI GetPrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR def_val, LPSTR buffer, UINT len, LPCSTR filename)
Definition: profile.c:1204
DWORD WINAPI GetPrivateProfileSectionNamesA(LPSTR buffer, DWORD size, LPCSTR filename)
Definition: profile.c:1660
UINT WINAPI GetPrivateProfileIntA(LPCSTR section, LPCSTR entry, INT def_val, LPCSTR filename)
Definition: profile.c:1326
INT WINAPI GetPrivateProfileStringW(LPCWSTR section, LPCWSTR entry, LPCWSTR def_val, LPWSTR buffer, UINT len, LPCWSTR filename)
Definition: profile.c:1142
BOOL WINAPI GetPrivateProfileStructA(LPCSTR section, LPCSTR key, LPVOID buffer, UINT len, LPCSTR filename)
Definition: profile.c:1769
BOOL WINAPI DECLSPEC_HOTPATCH WritePrivateProfileStringA(LPCSTR section, LPCSTR entry, LPCSTR string, LPCSTR filename)
Definition: profile.c:1484
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4246
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4198
BOOL WINAPI RevertToSelf(void)
Definition: security.c:855
int CDECL tolower(int c)
Definition: ctype.c:572
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
_ACRTIMP char *__cdecl strrchr(const char *, int)
Definition: string.c:3298
unsigned char
Definition: typeof.h:29
return ret
Definition: mutex.c:146
UINT WINAPI GetTempFileNameA(IN LPCSTR lpPathName, IN LPCSTR lpPrefixString, IN UINT uUnique, OUT LPSTR lpTempFileName)
Definition: filename.c:26
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
static const WCHAR emptyW[]
Definition: navigate.c:40
const char * filename
Definition: ioapi.h:137
#define debugstr_a
Definition: kernel32.h:31
#define profile
Definition: kernel32.h:12
#define wine_dbgstr_w
Definition: kernel32.h:34
#define REG_SZ
Definition: layer.c:22
@ SecurityImpersonation
Definition: lsa.idl:57
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define win_skip
Definition: minitest.h:67
#define todo_wine
Definition: minitest.h:80
#define CREATE_ALWAYS
Definition: disk.h:72
#define FILE_FLAG_DELETE_ON_CLOSE
Definition: disk.h:42
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define sprintf
Definition: sprintf.c:45
static BOOL check_file_data(LPCSTR path, LPCSTR data)
Definition: profile.c:916
static void check_profile_string_(int line, const char *section, const char *name, const char *file, const char *expect)
Definition: profile.c:35
#define check_profile_string(a, b, c, d)
Definition: profile.c:42
static void check_registry_value_(int line, HKEY key, const char *value, const char *expect)
Definition: profile.c:1202
static void test_profile_string(void)
Definition: profile.c:108
static void test_profile_existing(void)
Definition: profile.c:363
#define check_registry_value(a, b, c)
Definition: profile.c:1214
#define TESTFILE
Definition: profile.c:32
static void test_GetPrivateProfileString(const char *content, const char *descript)
Definition: profile.c:573
static void test_WritePrivateProfileString(void)
Definition: profile.c:921
static void create_test_file(LPCSTR name, LPCSTR data, DWORD size)
Definition: profile.c:511
#define KEY
Definition: profile.c:30
static void test_profile_int(void)
Definition: profile.c:53
static void test_profile_struct(void)
Definition: profile.c:1117
#define SECTION
Definition: profile.c:31
static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
Definition: profile.c:522
static void test_profile_refresh(void)
Definition: profile.c:470
static void test_profile_delete_on_close(void)
Definition: profile.c:449
static void test_registry_mapping(void)
Definition: profile.c:1216
static void test_profile_sections_names(void)
Definition: profile.c:273
static void test_profile_directory_readonly(void)
Definition: profile.c:536
static BOOL check_binary_file_data(LPCSTR path, const VOID *data, DWORD size)
Definition: profile.c:892
#define TESTFILE2
Definition: profile.c:33
static void test_profile_sections(void)
Definition: profile.c:177
static const char * contents
Definition: parser.c:511
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define REG_BINARY
Definition: nt_native.h:1499
#define KEY_READ
Definition: nt_native.h:1026
#define REG_MULTI_SZ
Definition: nt_native.h:1504
#define KEY_WRITE
Definition: nt_native.h:1034
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1497
#define err(...)
static calc_node_t temp
Definition: rpn_ieee.c:38
#define REG_DWORD
Definition: sdbapi.c:615
#define SDDL_REVISION_1
Definition: sddl.h:30
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
#define is_reactos()
Definition: test.h:1041
#define memset(x, y, z)
Definition: compat.h:39
Definition: btrfs.h:143
LPVOID lpSecurityDescriptor
Definition: compat.h:193
UINT result
Definition: profile.c:50
LPCSTR iniFile
Definition: profile.c:48
LPCSTR key
Definition: profile.c:46
INT defaultVal
Definition: profile.c:49
LPCSTR value
Definition: profile.c:47
LPCSTR section
Definition: profile.c:45
Definition: fci.c:127
Definition: copy.c:22
Definition: parser.c:49
Definition: name.c:39
Definition: parser.c:56
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
char iniFile[_MAX_PATH]
Definition: tftpd.cpp:37
int32_t INT
Definition: typedefs.h:58
Definition: pdh_main.c:96
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:257
#define ERROR_BAD_LENGTH
Definition: winerror.h:249
#define ERROR_INVALID_DATA
Definition: winerror.h:238
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193