mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / kernel32 / tests / profile.c
blobf981558548045c5540d2b91c94a0aa388e14650a
1 /*
2 * Unit tests for profile functions
4 * Copyright (c) 2003 Stefan Leichter
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "windows.h"
28 #include "sddl.h"
30 #define KEY "ProfileInt"
31 #define SECTION "Test"
32 #define TESTFILE ".\\testwine.ini"
33 #define TESTFILE2 ".\\testwine2.ini"
35 static void check_profile_string_(int line, const char *section, const char *name, const char *file, const char *expect)
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 %u, got %u\n", strlen(expect), ret);
40 ok_(__FILE__, line)(!strcmp(value, expect), "expected %s, got %s\n", debugstr_a(expect), debugstr_a(value));
42 #define check_profile_string(a, b, c, d) check_profile_string_(__LINE__, a, b, c, d);
44 struct _profileInt {
45 LPCSTR section;
46 LPCSTR key;
47 LPCSTR value;
48 LPCSTR iniFile;
49 INT defaultVal;
50 UINT result;
53 static void test_profile_int(void)
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},
82 int i, num_test = ARRAY_SIZE(profileInt);
83 UINT res;
85 DeleteFileA( TESTFILE);
87 for (i=0; i < num_test; i++) {
88 if (profileInt[i].value)
89 WritePrivateProfileStringA(SECTION, KEY, profileInt[i].value,
90 profileInt[i].iniFile);
92 res = GetPrivateProfileIntA(profileInt[i].section, profileInt[i].key,
93 profileInt[i].defaultVal, profileInt[i].iniFile);
94 ok((res == profileInt[i].result), "test<%02d>: ret<%010u> exp<%010u>\n",
95 i, res, profileInt[i].result);
98 DeleteFileA( TESTFILE);
101 static void test_profile_string(void)
103 static WCHAR emptyW[] = { 0 }; /* if "const", GetPrivateProfileStringW(emptyW, ...) crashes on win2k */
104 static const WCHAR keyW[] = { 'k','e','y',0 };
105 static const WCHAR sW[] = { 's',0 };
106 static const WCHAR TESTFILE2W[] = {'.','\\','t','e','s','t','w','i','n','e','2','.','i','n','i',0};
107 static const WCHAR valsectionW[] = {'v','a','l','_','e','_','s','e','c','t','i','o','n',0 };
108 static const WCHAR valnokeyW[] = {'v','a','l','_','n','o','_','k','e','y',0};
109 HANDLE h;
110 int ret;
111 DWORD count;
112 char buf[100];
113 WCHAR bufW[100];
114 char *p;
115 /* test that lines without an '=' will not be enumerated */
116 /* in the case below, name2 is a key while name3 is not. */
117 char content[]="[s]\r\nname1=val1\r\nname2=\r\nname3\r\nname4=val4\r\n";
118 char content2[]="\r\nkey=val_no_section\r\n[]\r\nkey=val_e_section\r\n"
119 "[s]\r\n=val_no_key\r\n[t]\r\n";
120 DeleteFileA( TESTFILE2);
121 h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
122 FILE_ATTRIBUTE_NORMAL, NULL);
123 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
124 if( h == INVALID_HANDLE_VALUE) return;
125 WriteFile( h, content, sizeof(content), &count, NULL);
126 CloseHandle( h);
128 /* enumerate the keys */
129 ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
130 TESTFILE2);
131 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
132 p[-1] = ',';
133 /* and test */
134 ok( ret == 18 && !strcmp( buf, "name1,name2,name4"), "wrong keys returned(%d): %s\n", ret,
135 buf);
137 /* add a new key to test that the file is quite usable */
138 WritePrivateProfileStringA( "s", "name5", "val5", TESTFILE2);
139 ret=GetPrivateProfileStringA( "s", NULL, "", buf, sizeof(buf),
140 TESTFILE2);
141 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
142 p[-1] = ',';
143 ok( ret == 24 && !strcmp( buf, "name1,name2,name4,name5"), "wrong keys returned(%d): %s\n",
144 ret, buf);
146 h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
147 FILE_ATTRIBUTE_NORMAL, NULL);
148 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", TESTFILE2);
149 if( h == INVALID_HANDLE_VALUE) return;
150 WriteFile( h, content2, sizeof(content2), &count, NULL);
151 CloseHandle( h);
153 /* works only in unicode, ascii crashes */
154 ret=GetPrivateProfileStringW(emptyW, keyW, emptyW, bufW, ARRAY_SIZE(bufW), TESTFILE2W);
155 todo_wine
156 ok(ret == 13, "expected 13, got %u\n", ret);
157 todo_wine
158 ok(!lstrcmpW(valsectionW,bufW), "expected %s, got %s\n",
159 wine_dbgstr_w(valsectionW), wine_dbgstr_w(bufW) );
161 /* works only in unicode, ascii crashes */
162 ret=GetPrivateProfileStringW(sW, emptyW, emptyW, bufW, ARRAY_SIZE(bufW), TESTFILE2W);
163 ok(ret == 10, "expected 10, got %u\n", ret);
164 ok(!lstrcmpW(valnokeyW,bufW), "expected %s, got %s\n",
165 wine_dbgstr_w(valnokeyW), wine_dbgstr_w(bufW) );
167 DeleteFileA( TESTFILE2);
170 static void test_profile_sections(void)
172 HANDLE h;
173 int ret;
174 DWORD count;
175 char buf[100];
176 char *p;
177 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";
178 static const char testfile4[]=".\\testwine4.ini";
179 BOOL on_win98 = FALSE;
181 DeleteFileA( testfile4 );
182 h = CreateFileA( testfile4, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
183 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", testfile4);
184 if( h == INVALID_HANDLE_VALUE) return;
185 WriteFile( h, content, sizeof(content), &count, NULL);
186 CloseHandle( h);
188 /* Some parameter checking */
189 SetLastError(0xdeadbeef);
190 ret = GetPrivateProfileSectionA( NULL, NULL, 0, NULL );
191 ok( ret == 0, "expected return size 0, got %d\n", ret );
192 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
193 GetLastError() == 0xdeadbeef /* Win98 */,
194 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
195 if (GetLastError() == 0xdeadbeef) on_win98 = TRUE;
197 SetLastError(0xdeadbeef);
198 ret = GetPrivateProfileSectionA( NULL, NULL, 0, testfile4 );
199 ok( ret == 0, "expected return size 0, got %d\n", ret );
200 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
201 GetLastError() == 0xdeadbeef /* Win98 */,
202 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
204 if (!on_win98)
206 SetLastError(0xdeadbeef);
207 ret = GetPrivateProfileSectionA( "section1", NULL, 0, testfile4 );
208 ok( ret == 0, "expected return size 0, got %d\n", ret );
209 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
212 SetLastError(0xdeadbeef);
213 ret = GetPrivateProfileSectionA( NULL, buf, sizeof(buf), testfile4 );
214 ok( ret == 0, "expected return size 0, got %d\n", ret );
215 ok( GetLastError() == ERROR_INVALID_PARAMETER,
216 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
218 SetLastError(0xdeadbeef);
219 ret = GetPrivateProfileSectionA( "section1", buf, sizeof(buf), NULL );
220 ok( ret == 0, "expected return size 0, got %d\n", ret );
221 todo_wine
222 ok( GetLastError() == ERROR_FILE_NOT_FOUND,
223 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* Existing empty section with no keys */
226 SetLastError(0xdeadbeef);
227 ret=GetPrivateProfileSectionA("section2", buf, sizeof(buf), testfile4);
228 ok( ret == 0, "expected return size 0, got %d\n", ret );
229 ok( GetLastError() == ERROR_SUCCESS,
230 "expected ERROR_SUCCESS, got %d\n", GetLastError());
232 /* Existing section with keys and values*/
233 SetLastError(0xdeadbeef);
234 ret=GetPrivateProfileSectionA("section1", buf, sizeof(buf), testfile4);
235 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
236 p[-1] = ',';
237 ok( ret == 35 && !strcmp( buf, "name1=val1,name2=,name3,name4=val4"), "wrong section returned(%d): %s\n",
238 ret, buf);
239 ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
240 ok( GetLastError() == ERROR_SUCCESS,
241 "expected ERROR_SUCCESS, got %d\n", GetLastError());
243 /* Existing section with no keys but has values */
244 SetLastError(0xdeadbeef);
245 ret=GetPrivateProfileSectionA("section3", buf, sizeof(buf), testfile4);
246 trace("section3 return: %s\n", buf);
247 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
248 p[-1] = ',';
249 ok( ret == 6 && !strcmp( buf, "=val5"), "wrong section returned(%d): %s\n",
250 ret, buf);
251 ok( buf[ret-1] == 0 && buf[ret] == 0, "returned buffer not terminated with double-null\n" );
252 ok( GetLastError() == ERROR_SUCCESS,
253 "expected ERROR_SUCCESS, got %d\n", GetLastError());
255 /* Overflow*/
256 ret=GetPrivateProfileSectionA("section1", buf, 24, testfile4);
257 for( p = buf + strlen(buf) + 1; *p;p += strlen(p)+1)
258 p[-1] = ',';
259 ok( ret == 22 && !strcmp( buf, "name1=val1,name2=,name"), "wrong section returned(%d): %s\n",
260 ret, buf);
261 ok( buf[ret] == 0 && buf[ret+1] == 0, "returned buffer not terminated with double-null\n" );
263 DeleteFileA( testfile4 );
266 static void test_profile_sections_names(void)
268 HANDLE h;
269 int ret;
270 DWORD count;
271 char buf[100];
272 WCHAR bufW[100];
273 static const char content[]="[section1]\r\n[section2]\r\n[section3]\r\n";
274 static const char testfile3[]=".\\testwine3.ini";
275 static const WCHAR testfile3W[]={ '.','\\','t','e','s','t','w','i','n','e','3','.','i','n','i',0 };
276 static const WCHAR not_here[] = {'.','\\','n','o','t','_','h','e','r','e','.','i','n','i',0};
277 DeleteFileA( testfile3 );
278 h = CreateFileA( testfile3, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
279 FILE_ATTRIBUTE_NORMAL, NULL);
280 ok( h != INVALID_HANDLE_VALUE, " cannot create %s\n", testfile3);
281 if( h == INVALID_HANDLE_VALUE) return;
282 WriteFile( h, content, sizeof(content), &count, NULL);
283 CloseHandle( h);
285 /* Test with sufficiently large buffer */
286 memset(buf, 0xc, sizeof(buf));
287 ret = GetPrivateProfileSectionNamesA( buf, 29, testfile3 );
288 ok( ret == 27, "expected return size 27, got %d\n", ret );
289 ok( (buf[ret-1] == 0 && buf[ret] == 0),
290 "returned buffer not terminated with double-null\n" );
292 /* Test with exactly fitting buffer */
293 memset(buf, 0xc, sizeof(buf));
294 ret = GetPrivateProfileSectionNamesA( buf, 28, testfile3 );
295 ok( ret == 26, "expected return size 26, got %d\n", ret );
296 todo_wine
297 ok( (buf[ret+1] == 0 && buf[ret] == 0) || /* W2K3 and higher */
298 broken(buf[ret+1] == 0xc && buf[ret] == 0), /* NT4, W2K, WinXP */
299 "returned buffer not terminated with double-null\n" );
301 /* Test with a buffer too small */
302 memset(buf, 0xc, sizeof(buf));
303 ret = GetPrivateProfileSectionNamesA( buf, 27, testfile3 );
304 ok( ret == 25, "expected return size 25, got %d\n", ret );
305 count = strlen("section1") + sizeof(CHAR) + strlen("section2");
306 todo_wine
307 ok( buf[ret+1] == 0 && buf[ret] == 0,
308 "returned buffer not terminated with double-null\n" );
310 /* Tests on nonexistent file */
311 memset(buf, 0xc, sizeof(buf));
312 ret = GetPrivateProfileSectionNamesA( buf, 10, ".\\not_here.ini" );
313 ok( ret == 0, "expected return size 0, got %d\n", ret );
314 ok( buf[0] == 0, "returned buffer not terminated with null\n" );
315 ok( buf[1] != 0, "returned buffer terminated with double-null\n" );
317 /* Test with sufficiently large buffer */
318 SetLastError(0xdeadbeef);
319 memset(bufW, 0xcc, sizeof(bufW));
320 ret = GetPrivateProfileSectionNamesW( bufW, 29, testfile3W );
321 if (ret == 0 && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
323 win_skip("GetPrivateProfileSectionNamesW is not implemented\n");
324 DeleteFileA( testfile3 );
325 return;
327 ok( ret == 27, "expected return size 27, got %d\n", ret );
328 ok( bufW[ret-1] == 0 && bufW[ret] == 0, "returned buffer not terminated with double-null\n" );
330 /* Test with exactly fitting buffer */
331 memset(bufW, 0xcc, sizeof(bufW));
332 ret = GetPrivateProfileSectionNamesW( bufW, 28, testfile3W );
333 ok( ret == 26, "expected return size 26, got %d\n", ret );
334 ok( (bufW[ret+1] == 0 && bufW[ret] == 0) || /* W2K3 and higher */
335 broken(bufW[ret+1] == 0xcccc && bufW[ret] == 0), /* NT4, W2K, WinXP */
336 "returned buffer not terminated with double-null\n" );
338 /* Test with a buffer too small */
339 memset(bufW, 0xcc, sizeof(bufW));
340 ret = GetPrivateProfileSectionNamesW( bufW, 27, testfile3W );
341 ok( ret == 25, "expected return size 25, got %d\n", ret );
342 ok( bufW[ret+1] == 0 && bufW[ret] == 0, "returned buffer not terminated with double-null\n" );
344 DeleteFileA( testfile3 );
346 /* Tests on nonexistent file */
347 memset(bufW, 0xcc, sizeof(bufW));
348 ret = GetPrivateProfileSectionNamesW( bufW, 10, not_here );
349 ok( ret == 0, "expected return size 0, got %d\n", ret );
350 ok( bufW[0] == 0, "returned buffer not terminated with null\n" );
351 ok( bufW[1] != 0, "returned buffer terminated with double-null\n" );
354 /* If the ini-file has already been opened with CreateFile, WritePrivateProfileString failed in wine with an error ERROR_SHARING_VIOLATION, some testing here */
355 static void test_profile_existing(void)
357 static const char *testfile1 = ".\\winesharing1.ini";
358 static const char *testfile2 = ".\\winesharing2.ini";
360 static const struct {
361 DWORD dwDesiredAccess;
362 DWORD dwShareMode;
363 DWORD write_error;
364 BOOL read_error;
365 DWORD broken_error;
366 } pe[] = {
367 {GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
368 {GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
369 {GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
370 {GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
371 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE },
372 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE },
373 {GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
374 {GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */},
375 /*Thief demo (bug 5024) opens .ini file like this*/
376 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */}
379 int i;
380 BOOL ret;
381 DWORD size;
382 HANDLE h = 0;
383 char buffer[MAX_PATH];
385 for (i=0; i < ARRAY_SIZE(pe); i++)
387 h = CreateFileA(testfile1, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
388 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
389 ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
390 SetLastError(0xdeadbeef);
392 ret = WritePrivateProfileStringA(SECTION, KEY, "12345", testfile1);
393 if (!pe[i].write_error)
395 if (!ret)
396 ok( broken(GetLastError() == pe[i].broken_error),
397 "%d: WritePrivateProfileString failed with error %u\n", i, GetLastError() );
398 CloseHandle(h);
399 size = GetPrivateProfileStringA(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
400 if (ret)
401 ok( size == 5, "%d: test failed, number of characters copied: %d instead of 5\n", i, size );
402 else
403 ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
405 else
407 DWORD err = GetLastError();
408 ok( !ret, "%d: WritePrivateProfileString succeeded\n", i );
409 if (!ret)
410 ok( err == pe[i].write_error, "%d: WritePrivateProfileString failed with error %u/%u\n",
411 i, err, pe[i].write_error );
412 CloseHandle(h);
413 size = GetPrivateProfileStringA(SECTION, KEY, 0, buffer, MAX_PATH, testfile1);
414 ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size );
417 ok( DeleteFileA(testfile1), "delete failed\n" );
420 h = CreateFileA(testfile2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
421 sprintf( buffer, "[%s]\r\n%s=123\r\n", SECTION, KEY );
422 ok( WriteFile( h, buffer, strlen(buffer), &size, NULL ), "failed to write\n" );
423 CloseHandle( h );
425 for (i=0; i < ARRAY_SIZE(pe); i++)
427 h = CreateFileA(testfile2, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL,
428 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
429 ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i);
430 SetLastError(0xdeadbeef);
431 ret = GetPrivateProfileStringA(SECTION, KEY, NULL, buffer, MAX_PATH, testfile2);
432 if (!pe[i].read_error)
433 ok( ret, "%d: GetPrivateProfileString failed with error %u\n", i, GetLastError() );
434 else
435 ok( !ret, "%d: GetPrivateProfileString succeeded\n", i );
436 CloseHandle(h);
438 ok( DeleteFileA(testfile2), "delete failed\n" );
441 static void test_profile_delete_on_close(void)
443 HANDLE h;
444 DWORD size, res;
445 static const CHAR testfile[] = ".\\testwine5.ini";
446 static const char contents[] = "[" SECTION "]\n" KEY "=123\n";
448 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
449 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
450 res = WriteFile( h, contents, sizeof contents - 1, &size, NULL );
451 ok( res, "Cannot write test file: %x\n", GetLastError() );
452 ok( size == sizeof contents - 1, "Test file: partial write\n");
454 SetLastError(0xdeadbeef);
455 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
456 ok( res == 123, "Got %d instead of 123\n", res);
458 /* This also deletes the file */
459 CloseHandle(h);
462 static void test_profile_refresh(void)
464 static const CHAR testfile[] = ".\\winetest4.ini";
465 HANDLE h;
466 DWORD size, res;
467 static const char contents1[] = "[" SECTION "]\n" KEY "=123\n";
468 static const char contents2[] = "[" SECTION "]\n" KEY "=124\n";
470 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
471 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
472 res = WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL );
473 ok( res, "Cannot write test file: %x\n", GetLastError() );
474 ok( size == sizeof contents1 - 1, "Test file: partial write\n");
476 SetLastError(0xdeadbeef);
477 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
478 ok( res == 123, "Got %d instead of 123\n", res);
480 CloseHandle(h);
482 /* Test proper invalidation of wine's profile file cache */
484 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
485 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
486 res = WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL );
487 ok( res, "Cannot write test file: %x\n", GetLastError() );
488 ok( size == sizeof contents2 - 1, "Test file: partial write\n");
490 SetLastError(0xdeadbeef);
491 res = GetPrivateProfileIntA(SECTION, KEY, 0, testfile);
492 ok( res == 124, "Got %d instead of 124\n", res);
494 /* This also deletes the file */
495 CloseHandle(h);
497 /* Cache must be invalidated if file no longer exists and default must be returned */
498 SetLastError(0xdeadbeef);
499 res = GetPrivateProfileIntA(SECTION, KEY, 421, testfile);
500 ok( res == 421, "Got %d instead of 421\n", res);
503 static void create_test_file(LPCSTR name, LPCSTR data, DWORD size)
505 HANDLE hfile;
506 DWORD count;
508 hfile = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
509 ok(hfile != INVALID_HANDLE_VALUE, "cannot create %s\n", name);
510 WriteFile(hfile, data, size, &count, NULL);
511 CloseHandle(hfile);
514 static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
516 int i;
518 for(i = 0;i < MAX_PATH;++i)
519 if(emptystr[i] != 0)
521 trace("emptystr[%d] = %d\n",i,emptystr[i]);
522 return FALSE;
525 return TRUE;
528 static void test_profile_directory_readonly(void)
530 BOOL ret;
531 CHAR path_folder[MAX_PATH];
532 CHAR path_file[MAX_PATH];
533 const char *sddl_string_everyone_readonly = "D:PAI(A;;0x1200a9;;;WD)";
534 SECURITY_ATTRIBUTES attributes = {0};
535 char lpStruct[] = { 's', 't', 'r', 'i', 'n', 'g' };
537 attributes.nLength = sizeof(attributes);
538 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(sddl_string_everyone_readonly, SDDL_REVISION_1, &attributes.lpSecurityDescriptor, NULL);
539 ok(ret == TRUE, "ConvertStringSecurityDescriptorToSecurityDescriptor failed: %d\n", GetLastError());
541 GetTempPathA(MAX_PATH, path_folder);
542 lstrcatA(path_folder, "wine-test");
544 strcpy(path_file, path_folder);
545 lstrcatA(path_file, "\\tmp.ini");
547 ret = CreateDirectoryA(path_folder, &attributes);
548 ok(ret == TRUE, "CreateDirectoryA failed: %d\n", GetLastError());
550 ret = WritePrivateProfileStringA("App", "key", "string", path_file);
551 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
553 ret = WritePrivateProfileSectionA("App", "key=string", path_file);
554 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
556 ret = WritePrivateProfileStructA("App", "key", lpStruct, sizeof(lpStruct), path_file);
557 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
559 ret = RemoveDirectoryA(path_folder);
560 ok(ret == TRUE, "RemoveDirectoryA failed: %d\n", GetLastError());
562 LocalFree(attributes.lpSecurityDescriptor);
565 static void test_GetPrivateProfileString(const char *content, const char *descript)
567 DWORD ret, len;
568 CHAR buf[MAX_PATH];
569 CHAR def_val[MAX_PATH];
570 CHAR path[MAX_PATH];
571 CHAR windir[MAX_PATH];
572 /* NT series crashes on r/o empty strings, so pass an r/w
573 empty string and check for modification */
574 CHAR emptystr[MAX_PATH] = "";
575 LPSTR tempfile;
577 static const char filename[] = ".\\winetest.ini";
579 trace("test_GetPrivateProfileStringA: %s\n", descript);
581 create_test_file(filename, content, lstrlenA(content));
583 /* Run this test series with caching. Wine won't cache profile
584 files younger than 2.1 seconds. */
585 Sleep(2500);
587 /* lpAppName is NULL */
588 memset(buf, 0xc, sizeof(buf));
589 lstrcpyA(buf, "kumquat");
590 ret = GetPrivateProfileStringA(NULL, "name1", "default",
591 buf, MAX_PATH, filename);
592 ok(ret == 18, "Expected 18, got %d\n", ret);
593 len = lstrlenA("section1") + sizeof(CHAR) + lstrlenA("section2") + 2 * sizeof(CHAR);
595 ok(!memcmp(buf, "section1\0section2\0", len),
596 "Expected \"section1\\x00section2\\x00\\x00\", got %s\n",
597 debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
599 /* lpAppName is empty */
600 memset(buf, 0xc, sizeof(buf));
601 lstrcpyA(buf, "kumquat");
602 ret = GetPrivateProfileStringA(emptystr, "name1", "default",
603 buf, MAX_PATH, filename);
604 ok(ret == 7, "Expected 7, got %d\n", ret);
605 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
606 ok(emptystr_ok(emptystr), "AppName modified\n");
608 /* lpAppName is missing */
609 memset(buf, 0xc,sizeof(buf));
610 lstrcpyA(buf, "kumquat");
611 ret = GetPrivateProfileStringA("notasection", "name1", "default",
612 buf, MAX_PATH, filename);
613 ok(ret == 7, "Expected 7, got %d\n", ret);
614 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
616 /* lpAppName is empty, lpDefault is NULL */
617 memset(buf, 0xc,sizeof(buf));
618 lstrcpyA(buf, "kumquat");
619 ret = GetPrivateProfileStringA(emptystr, "name1", NULL,
620 buf, MAX_PATH, filename);
621 ok(ret == 0, "Expected 0, got %d\n", ret);
622 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
623 ok(emptystr_ok(emptystr), "AppName modified\n");
625 /* lpAppName is empty, lpDefault is empty */
626 memset(buf, 0xc,sizeof(buf));
627 lstrcpyA(buf, "kumquat");
628 ret = GetPrivateProfileStringA(emptystr, "name1", "",
629 buf, MAX_PATH, filename);
630 ok(ret == 0, "Expected 0, got %d\n", ret);
631 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
632 ok(emptystr_ok(emptystr), "AppName modified\n");
634 /* lpAppName is empty, lpDefault has trailing blank characters */
635 memset(buf, 0xc,sizeof(buf));
636 lstrcpyA(buf, "kumquat");
637 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
638 lstrcpyA(def_val, "default ");
639 ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
640 buf, MAX_PATH, filename);
641 ok(ret == 7, "Expected 7, got %d\n", ret);
642 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
643 ok(emptystr_ok(emptystr), "AppName modified\n");
645 /* lpAppName is empty, many blank characters in lpDefault */
646 memset(buf, 0xc,sizeof(buf));
647 lstrcpyA(buf, "kumquat");
648 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
649 lstrcpyA(def_val, "one two ");
650 ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
651 buf, MAX_PATH, filename);
652 ok(ret == 7, "Expected 7, got %d\n", ret);
653 ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
654 ok(emptystr_ok(emptystr), "AppName modified\n");
656 /* lpAppName is empty, blank character but not trailing in lpDefault */
657 memset(buf, 0xc,sizeof(buf));
658 lstrcpyA(buf, "kumquat");
659 ret = GetPrivateProfileStringA(emptystr, "name1", "one two",
660 buf, MAX_PATH, filename);
661 ok(ret == 7, "Expected 7, got %d\n", ret);
662 ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
663 ok(emptystr_ok(emptystr), "AppName modified\n");
665 /* lpKeyName is NULL */
666 memset(buf, 0xc,sizeof(buf));
667 lstrcpyA(buf, "kumquat");
668 ret = GetPrivateProfileStringA("section1", NULL, "default",
669 buf, MAX_PATH, filename);
670 ok(ret == 18, "Expected 18, got %d\n", ret);
671 ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
672 "Expected \"name1\\x00name2\\x00name4\\x00\\x00\", got %s\n",
673 debugstr_an(buf, (ret + 2 >= MAX_PATH ? MAX_PATH : ret + 1)));
675 /* lpKeyName is empty */
676 memset(buf, 0xc,sizeof(buf));
677 lstrcpyA(buf, "kumquat");
678 ret = GetPrivateProfileStringA("section1", emptystr, "default",
679 buf, MAX_PATH, filename);
680 ok(ret == 7, "Expected 7, got %d\n", ret);
681 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
682 ok(emptystr_ok(emptystr), "KeyName modified\n");
684 /* lpKeyName is missing */
685 memset(buf, 0xc,sizeof(buf));
686 lstrcpyA(buf, "kumquat");
687 ret = GetPrivateProfileStringA("section1", "notakey", "default",
688 buf, MAX_PATH, filename);
689 ok(ret == 7, "Expected 7, got %d\n", ret);
690 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
692 /* lpKeyName is empty, lpDefault is NULL */
693 memset(buf, 0xc,sizeof(buf));
694 lstrcpyA(buf, "kumquat");
695 ret = GetPrivateProfileStringA("section1", emptystr, NULL,
696 buf, MAX_PATH, filename);
697 ok(ret == 0, "Expected 0, got %d\n", ret);
698 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
699 ok(emptystr_ok(emptystr), "KeyName modified\n");
701 /* lpKeyName is empty, lpDefault is empty */
702 memset(buf, 0xc,sizeof(buf));
703 lstrcpyA(buf, "kumquat");
704 ret = GetPrivateProfileStringA("section1", emptystr, "",
705 buf, MAX_PATH, filename);
706 ok(ret == 0, "Expected 0, got %d\n", ret);
707 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
708 ok(emptystr_ok(emptystr), "KeyName modified\n");
710 /* lpKeyName is empty, lpDefault has trailing blank characters */
711 memset(buf, 0xc,sizeof(buf));
712 lstrcpyA(buf, "kumquat");
713 /* lpDefault must be writable (trailing blanks are removed inplace in win9x) */
714 lstrcpyA(def_val, "default ");
715 ret = GetPrivateProfileStringA("section1", emptystr, def_val,
716 buf, MAX_PATH, filename);
717 ok(ret == 7, "Expected 7, got %d\n", ret);
718 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
719 ok(emptystr_ok(emptystr), "KeyName modified\n");
721 if (0) /* crashes */
723 /* lpReturnedString is NULL */
724 ret = GetPrivateProfileStringA("section1", "name1", "default",
725 NULL, MAX_PATH, filename);
728 /* lpFileName is NULL */
729 memset(buf, 0xc,sizeof(buf));
730 lstrcpyA(buf, "kumquat");
731 ret = GetPrivateProfileStringA("section1", "name1", "default",
732 buf, MAX_PATH, NULL);
733 ok(ret == 7, "Expected 7, got %d\n", ret);
734 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
736 /* lpFileName is empty */
737 memset(buf, 0xc,sizeof(buf));
738 lstrcpyA(buf, "kumquat");
739 ret = GetPrivateProfileStringA("section1", "name1", "default",
740 buf, MAX_PATH, "");
741 ok(ret == 7, "Expected 7, got %d\n", ret);
742 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
744 /* lpFileName is nonexistent */
745 memset(buf, 0xc,sizeof(buf));
746 lstrcpyA(buf, "kumquat");
747 ret = GetPrivateProfileStringA("section1", "name1", "default",
748 buf, MAX_PATH, "nonexistent");
749 ok(ret == 7, "Expected 7, got %d\n", ret);
750 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
752 /* nSize is 0 */
753 memset(buf, 0xc,sizeof(buf));
754 lstrcpyA(buf, "kumquat");
755 ret = GetPrivateProfileStringA("section1", "name1", "default",
756 buf, 0, filename);
757 ok(ret == 0, "Expected 0, got %d\n", ret);
758 ok(!lstrcmpA(buf, "kumquat"), "Expected buf to be unchanged, got \"%s\"\n", buf);
760 /* nSize is exact size of output */
761 memset(buf, 0xc,sizeof(buf));
762 lstrcpyA(buf, "kumquat");
763 ret = GetPrivateProfileStringA("section1", "name1", "default",
764 buf, 4, filename);
765 ok(ret == 3, "Expected 3, got %d\n", ret);
766 ok(!lstrcmpA(buf, "val"), "Expected \"val\", got \"%s\"\n", buf);
768 /* nSize has room for NULL terminator */
769 memset(buf, 0xc,sizeof(buf));
770 lstrcpyA(buf, "kumquat");
771 ret = GetPrivateProfileStringA("section1", "name1", "default",
772 buf, 5, filename);
773 ok(ret == 4, "Expected 4, got %d\n", ret);
774 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
776 /* output is 1 character */
777 memset(buf, 0xc,sizeof(buf));
778 lstrcpyA(buf, "kumquat");
779 ret = GetPrivateProfileStringA("section1", "name4", "default",
780 buf, MAX_PATH, filename);
781 ok(ret == 1, "Expected 1, got %d\n", ret);
782 ok(!lstrcmpA(buf, "a"), "Expected \"a\", got \"%s\"\n", buf);
784 /* output is 1 character, no room for NULL terminator */
785 memset(buf, 0xc,sizeof(buf));
786 lstrcpyA(buf, "kumquat");
787 ret = GetPrivateProfileStringA("section1", "name4", "default",
788 buf, 1, filename);
789 ok(ret == 0, "Expected 0, got %d\n", ret);
790 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
792 /* lpAppName is NULL, not enough room for final section name */
793 memset(buf, 0xc,sizeof(buf));
794 lstrcpyA(buf, "kumquat");
795 ret = GetPrivateProfileStringA(NULL, "name1", "default",
796 buf, 16, filename);
797 ok(ret == 14, "Expected 14, got %d\n", ret);
798 len = lstrlenA("section1") + 2 * sizeof(CHAR);
799 todo_wine
800 ok(!memcmp(buf, "section1\0secti\0", ret + 2),
801 "Expected \"section1\\x00secti\\x00\\x00\", got %s\n",
802 debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
804 /* lpKeyName is NULL, not enough room for final key name */
805 memset(buf, 0xc,sizeof(buf));
806 lstrcpyA(buf, "kumquat");
807 ret = GetPrivateProfileStringA("section1", NULL, "default",
808 buf, 16, filename);
809 ok(ret == 14, "Expected 14, got %d\n", ret);
810 todo_wine
811 ok(!memcmp(buf, "name1\0name2\0na\0", ret + 2),
812 "Expected \"name1\\x00name2\\x00na\\x00\\x00\", got %s\n",
813 debugstr_an(buf, (ret + 2 >= 16 ? 16 : ret + 1)));
815 /* key value has quotation marks which are stripped */
816 memset(buf, 0xc,sizeof(buf));
817 lstrcpyA(buf, "kumquat");
818 ret = GetPrivateProfileStringA("section1", "name2", "default",
819 buf, MAX_PATH, filename);
820 ok(ret == 4, "Expected 4, got %d\n", ret);
821 ok(!lstrcmpA(buf, "val2"), "Expected \"val2\", got \"%s\"\n", buf);
823 /* case does not match */
824 memset(buf, 0xc,sizeof(buf));
825 lstrcpyA(buf, "kumquat");
826 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
827 buf, MAX_PATH, filename);
828 ok(ret == 4, "Expected 4, got %d\n", ret);
829 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
831 /* only filename is used */
832 memset(buf, 0xc,sizeof(buf));
833 lstrcpyA(buf, "kumquat");
834 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
835 buf, MAX_PATH, "winetest.ini");
836 ok(ret == 7, "Expected 7, got %d\n", ret);
837 ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
839 GetWindowsDirectoryA(windir, MAX_PATH);
840 SetLastError(0xdeadbeef);
841 ret = GetTempFileNameA(windir, "pre", 0, path);
842 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
844 skip("Not allowed to create a file in the Windows directory\n");
845 DeleteFileA(filename);
846 return;
848 tempfile = strrchr(path, '\\') + 1;
849 create_test_file(path, content, lstrlenA(content));
851 /* only filename is used, file exists in windows directory */
852 memset(buf, 0xc,sizeof(buf));
853 lstrcpyA(buf, "kumquat");
854 ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
855 buf, MAX_PATH, tempfile);
856 ok(ret == 4, "Expected 4, got %d\n", ret);
857 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
859 /* successful case */
860 memset(buf, 0xc,sizeof(buf));
861 lstrcpyA(buf, "kumquat");
862 ret = GetPrivateProfileStringA("section1", "name1", "default",
863 buf, MAX_PATH, filename);
864 ok(ret == 4, "Expected 4, got %d\n", ret);
865 ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
867 /* Existing section with no keys in an existing file */
868 memset(buf, 0xc,sizeof(buf));
869 SetLastError(0xdeadbeef);
870 ret=GetPrivateProfileStringA("section2", "DoesntExist", "",
871 buf, MAX_PATH, filename);
872 ok( ret == 0, "expected return size 0, got %d\n", ret );
873 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
874 todo_wine
875 ok( GetLastError() == 0xdeadbeef ||
876 GetLastError() == ERROR_FILE_NOT_FOUND /* Win 7 */,
877 "expected 0xdeadbeef or ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
880 DeleteFileA(path);
881 DeleteFileA(filename);
884 static BOOL check_binary_file_data(LPCSTR path, const VOID *data, DWORD size)
886 HANDLE file;
887 CHAR buf[MAX_PATH];
888 BOOL ret;
890 file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
891 if (file == INVALID_HANDLE_VALUE)
892 return FALSE;
894 if(size != GetFileSize(file, NULL) )
896 CloseHandle(file);
897 return FALSE;
900 ret = ReadFile(file, buf, size, &size, NULL);
901 CloseHandle(file);
902 if (!ret)
903 return FALSE;
905 return !memcmp(buf, data, size);
908 static BOOL check_file_data(LPCSTR path, LPCSTR data)
910 return check_binary_file_data(path, data, lstrlenA(data));
913 static void test_WritePrivateProfileString(void)
915 BOOL ret;
916 LPCSTR data;
917 CHAR path[MAX_PATH];
918 CHAR temp[MAX_PATH];
919 HANDLE file;
921 GetTempPathA(MAX_PATH, temp);
922 GetTempFileNameA(temp, "wine", 0, path);
923 DeleteFileA(path);
925 /* path is not created yet */
927 /* NULL lpAppName */
928 SetLastError(0xdeadbeef);
929 ret = WritePrivateProfileStringA(NULL, "key", "string", path);
930 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
931 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
932 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
933 ok(GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES,
934 "Expected path to not exist\n");
936 GetTempFileNameA(temp, "wine", 0, path);
938 /* NULL lpAppName, path exists */
939 data = "";
940 SetLastError(0xdeadbeef);
941 ret = WritePrivateProfileStringA(NULL, "key", "string", path);
942 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
943 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
944 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
945 ok(check_file_data(path, data), "File doesn't match\n");
946 DeleteFileA(path);
948 if (0)
950 /* empty lpAppName, crashes on NT4 and higher */
951 data = "[]\r\n"
952 "key=string\r\n";
953 ret = WritePrivateProfileStringA("", "key", "string", path);
954 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
955 ok(check_file_data(path, data), "File doesn't match\n");
956 DeleteFileA(path);
959 /* NULL lpKeyName */
960 data = "";
961 ret = WritePrivateProfileStringA("App", NULL, "string", path);
962 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
963 todo_wine
965 ok(check_file_data(path, data), "File doesn't match\n");
967 DeleteFileA(path);
969 if (0)
971 /* empty lpKeyName, crashes on NT4 and higher */
972 data = "[App]\r\n"
973 "=string\r\n";
974 ret = WritePrivateProfileStringA("App", "", "string", path);
975 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
976 todo_wine
978 ok(check_file_data(path, data), "File doesn't match\n");
980 DeleteFileA(path);
983 /* NULL lpString */
984 data = "";
985 ret = WritePrivateProfileStringA("App", "key", NULL, path);
986 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
987 todo_wine
989 ok(check_file_data(path, data), "File doesn't match\n");
991 DeleteFileA(path);
993 /* empty lpString */
994 data = "[App]\r\n"
995 "key=\r\n";
996 ret = WritePrivateProfileStringA("App", "key", "", path);
997 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
998 ok(check_file_data(path, data), "File doesn't match\n");
999 DeleteFileA(path);
1001 /* empty lpFileName */
1002 SetLastError(0xdeadbeef);
1003 ret = WritePrivateProfileStringA("App", "key", "string", "");
1004 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1005 ok(GetLastError() == ERROR_ACCESS_DENIED,
1006 "Expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
1008 /* Relative paths are relative to X:\\%WINDIR% */
1009 GetWindowsDirectoryA(path, MAX_PATH);
1010 strcat(path, "\\win1.tmp");
1011 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1012 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1013 skip("Not allowed to create a file in the Windows directory\n");
1014 else
1016 CloseHandle(file);
1017 DeleteFileA(path);
1019 data = "[App]\r\n"
1020 "key=string\r\n";
1021 ret = WritePrivateProfileStringA("App", "key", "string", "win1.tmp");
1022 ok(ret == TRUE, "Expected TRUE, got %d, le=%u\n", ret, GetLastError());
1023 ok(check_file_data(path, data), "File doesn't match\n");
1024 DeleteFileA(path);
1027 GetTempPathA(MAX_PATH, temp);
1028 GetTempFileNameA(temp, "wine", 0, path);
1030 /* build up an INI file */
1031 WritePrivateProfileStringA("App1", "key1", "string1", path);
1032 WritePrivateProfileStringA("App1", "key2", "string2", path);
1033 WritePrivateProfileStringA("App1", "key3", "string3", path);
1034 WritePrivateProfileStringA("App2", "key4", "string4", path);
1036 /* make an addition and verify the INI */
1037 data = "[App1]\r\n"
1038 "key1=string1\r\n"
1039 "key2=string2\r\n"
1040 "key3=string3\r\n"
1041 "[App2]\r\n"
1042 "key4=string4\r\n"
1043 "[App3]\r\n"
1044 "key5=string5\r\n";
1045 ret = WritePrivateProfileStringA("App3", "key5", "string5", path);
1046 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1047 ok(check_file_data(path, data), "File doesn't match\n");
1049 /* lpString is NULL, key2 key is deleted */
1050 data = "[App1]\r\n"
1051 "key1=string1\r\n"
1052 "key3=string3\r\n"
1053 "[App2]\r\n"
1054 "key4=string4\r\n"
1055 "[App3]\r\n"
1056 "key5=string5\r\n";
1057 ret = WritePrivateProfileStringA("App1", "key2", NULL, path);
1058 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1059 ok(check_file_data(path, data), "File doesn't match\n");
1061 /* try to delete key2 again */
1062 data = "[App1]\r\n"
1063 "key1=string1\r\n"
1064 "key3=string3\r\n"
1065 "[App2]\r\n"
1066 "key4=string4\r\n"
1067 "[App3]\r\n"
1068 "key5=string5\r\n";
1069 ret = WritePrivateProfileStringA("App1", "key2", NULL, path);
1070 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1071 ok(check_file_data(path, data), "File doesn't match\n");
1073 /* lpKeyName is NULL, App1 section is deleted */
1074 data = "[App2]\r\n"
1075 "key4=string4\r\n"
1076 "[App3]\r\n"
1077 "key5=string5\r\n";
1078 ret = WritePrivateProfileStringA("App1", NULL, "string1", path);
1079 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1080 ok(check_file_data(path, data), "File doesn't match\n");
1082 /* lpString is not needed to delete a section */
1083 data = "[App3]\r\n"
1084 "key5=string5\r\n";
1085 ret = WritePrivateProfileStringA("App2", NULL, NULL, path);
1086 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1087 ok(check_file_data(path, data), "File doesn't match\n");
1089 /* leave just the section */
1090 data = "[App3]\r\n";
1091 ret = WritePrivateProfileStringA("App3", "key5", NULL, path);
1092 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1093 ok(check_file_data(path, data), "File doesn't match\n");
1094 DeleteFileA(path);
1096 /* NULLs in file before first section. Should be preserved in output */
1097 data = "Data \0 before \0 first \0 section" /* 31 bytes */
1098 "\r\n[section1]\r\n" /* 14 bytes */
1099 "key1=string1\r\n"; /* 14 bytes */
1100 GetTempFileNameA(temp, "wine", 0, path);
1101 create_test_file(path, data, 31);
1102 ret = WritePrivateProfileStringA("section1", "key1", "string1", path);
1103 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1104 todo_wine
1105 ok( check_binary_file_data(path, data, 59), "File doesn't match\n");
1106 DeleteFileA(path);
1109 static void test_profile_struct(void)
1111 static const char expect_data[] = "[s]\r\nkey=616261637573006F\r\n";
1112 char buffer[20];
1113 BOOL ret;
1115 SetLastError(0xdeadbeef);
1116 ret = GetPrivateProfileStructA("s", "key", buffer, sizeof(buffer), "./winetest.ini");
1117 ok(!ret, "expected failure\n");
1118 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %u\n", GetLastError());
1120 ret = WritePrivateProfileStructA("s", "key", (void *)"abacus", sizeof("abacus"), "./winetest.ini");
1121 ok(ret, "got error %u\n", GetLastError());
1122 ok(check_file_data("./winetest.ini", expect_data), "file doesn't match\n");
1124 SetLastError(0xdeadbeef);
1125 ret = GetPrivateProfileStructA("s", "key", buffer, 6, "./winetest.ini");
1126 ok(!ret, "expected failure\n");
1127 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %u\n", GetLastError());
1129 SetLastError(0xdeadbeef);
1130 ret = GetPrivateProfileStructA("s", "key", buffer, 8, "./winetest.ini");
1131 ok(!ret, "expected failure\n");
1132 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %u\n", GetLastError());
1134 memset(buffer, 0xcc, sizeof(buffer));
1135 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1136 ok(ret, "got error %u\n", GetLastError());
1137 ok(!strcmp(buffer, "abacus"), "data didn't match\n");
1139 memset(buffer, 0xcc, sizeof(buffer));
1140 ret = GetPrivateProfileStringA("s", "key", "default", buffer, sizeof(buffer), "./winetest.ini");
1141 ok(ret == 16, "got size %u\n", ret);
1142 ok(!strcmp(buffer, "616261637573006F"), "got %s\n", debugstr_a(buffer));
1144 ret = WritePrivateProfileStringA("s", "key", "636163747573006F", "./winetest.ini");
1145 ok(ret, "got error %u\n", GetLastError());
1147 SetLastError(0xdeadbeef);
1148 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1149 ok(!ret, "expected failure\n");
1150 todo_wine ok(GetLastError() == ERROR_INVALID_DATA, "got error %u\n", GetLastError());
1152 ret = WritePrivateProfileStringA("s", "key", "6361637475730083", "./winetest.ini");
1153 ok(ret, "got error %u\n", GetLastError());
1155 memset(buffer, 0xcc, sizeof(buffer));
1156 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1157 ok(ret, "got error %u\n", GetLastError());
1158 ok(!strcmp(buffer, "cactus"), "data didn't match\n");
1160 ret = WritePrivateProfileStringA("s", "key", "636163747573008Q", "./winetest.ini");
1161 ok(ret, "got error %u\n", GetLastError());
1163 SetLastError(0xdeadbeef);
1164 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1165 ok(!ret, "expected failure\n");
1166 todo_wine ok(GetLastError() == ERROR_INVALID_DATA, "got error %u\n", GetLastError());
1168 ret = WritePrivateProfileStringA("s", "key", "16361637475730083", "./winetest.ini");
1169 ok(ret, "got error %u\n", GetLastError());
1171 SetLastError(0xdeadbeef);
1172 ret = GetPrivateProfileStructA("s", "key", buffer, 7, "./winetest.ini");
1173 ok(!ret, "expected failure\n");
1174 todo_wine ok(GetLastError() == ERROR_BAD_LENGTH, "got error %u\n", GetLastError());
1176 ret = DeleteFileA("./winetest.ini");
1177 ok(ret, "got error %u\n", GetLastError());
1180 static void check_registry_value_(int line, HKEY key, const char *value, const char *expect)
1182 char buffer[30];
1183 DWORD type, size = sizeof(buffer);
1184 LSTATUS ret;
1186 memset(buffer, 0xcc, sizeof(buffer));
1187 ret = RegQueryValueExA(key, value, 0, &type, (BYTE *)buffer, &size);
1188 ok_(__FILE__, line)(!ret, "got error %u\n", ret);
1189 ok_(__FILE__, line)(!strcmp(buffer, expect), "expected %s, got %s\n", debugstr_a(expect), debugstr_a(buffer));
1190 ok_(__FILE__, line)(type == REG_SZ, "got type %u\n", type);
1192 #define check_registry_value(a, b, c) check_registry_value_(__LINE__, a, b, c)
1194 static void test_registry_mapping(void)
1196 static const DWORD ivalue = 0xabacab;
1197 HKEY mapping_key, mapped_key, mapping_subkey;
1198 char buffer[30];
1199 LSTATUS ret;
1201 /* impersonate ourselves to prevent registry virtualization */
1202 ret = ImpersonateSelf(SecurityImpersonation);
1203 ok(ret, "got error %u\n", GetLastError());
1205 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
1206 "Software\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\winetest_map.ini",
1207 0, NULL, 0, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, NULL, &mapping_key, NULL);
1208 if (ret == ERROR_ACCESS_DENIED)
1210 skip("Not enough permissions to write to the IniFileMapping key.\n");
1211 return;
1213 ok(!ret, "got error %u\n", ret);
1215 ret = RegSetValueExA(mapping_key, "section1", 0, REG_SZ, (BYTE *)"USR:winetest_map", sizeof("USR:winetest_map"));
1216 ok(!ret, "got error %u\n", ret);
1217 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1218 todo_wine ok(ret, "got error %u\n", GetLastError());
1220 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1222 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1223 ok(ret, "got error %u\n", GetLastError());
1225 check_profile_string("section1", "name1", "winetest_map.ini", "value1");
1226 check_profile_string("section1", "name1", "C:/fake/path/winetest_map.ini", "value1");
1228 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1229 ok(!ret, "got error %u\n", ret);
1230 check_registry_value(mapped_key, "name1", "value1");
1232 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1233 ok(!ret, "got error %u\n", ret);
1235 check_profile_string("section1", "name2", "winetest_map.ini", "value2");
1237 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1238 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1240 ret = WritePrivateProfileStringA("section1", "name2", NULL, "winetest_map.ini");
1241 ok(ret, "got error %u\n", GetLastError());
1242 ret = RegQueryValueExA(mapped_key, "name2", 0, NULL, NULL, NULL);
1243 ok(ret == ERROR_FILE_NOT_FOUND, "got error %u\n", ret);
1245 /* Test non-string types. */
1247 ret = RegSetValueExA(mapped_key, "name3", 0, REG_DWORD, (BYTE *)&ivalue, sizeof(ivalue));
1248 ok(!ret, "got error %u\n", ret);
1249 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1251 ret = GetPrivateProfileIntA("section1", "name3", 0, "winetest_map.ini");
1252 ok(ret == 0, "got %#x\n", ret);
1254 ret = RegSetValueExA(mapped_key, "name3", 0, REG_BINARY, (BYTE *)"value3", sizeof("value3"));
1255 ok(!ret, "got error %u\n", ret);
1256 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1258 ret = RegSetValueExA(mapped_key, "name3", 0, REG_MULTI_SZ, (BYTE *)"one\0two\0", sizeof("one\0two\0"));
1259 ok(!ret, "got error %u\n", ret);
1260 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1262 ret = RegSetValueExA(mapped_key, "name3", 0, REG_EXPAND_SZ, (BYTE *)"x%SystemRoot%", sizeof("x%SystemRoot%"));
1263 ok(!ret, "got error %u\n", ret);
1264 check_profile_string("section1", "name3", "winetest_map.ini", "default");
1266 /* Test WritePrivateProfileSection(). Unlike with .ini files, it doesn't
1267 * remove existing entries. */
1269 ret = WritePrivateProfileStringA("section1", "name4", "value4", "winetest_map.ini");
1270 ok(ret, "got error %u\n", GetLastError());
1271 ret = WritePrivateProfileStringA("section1", "name5", "value5", "winetest_map.ini");
1272 ok(ret, "got error %u\n", GetLastError());
1273 ret = WritePrivateProfileSectionA("section1", "name4=four\0name6=six\0", "winetest_map.ini");
1274 ok(ret, "got error %u\n", GetLastError());
1275 check_profile_string("section1", "name4", "winetest_map.ini", "four");
1276 check_profile_string("section1", "name5", "winetest_map.ini", "value5");
1277 check_profile_string("section1", "name6", "winetest_map.ini", "six");
1279 /* Test deleting the section. */
1281 RegCloseKey(mapped_key);
1283 ret = RegCreateKeyExA(HKEY_CURRENT_USER, "winetest_map\\subkey", 0, NULL, 0, 0, NULL, &mapped_key, NULL);
1284 ok(!ret, "got error %u\n", ret);
1285 RegCloseKey(mapped_key);
1287 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1288 ok(ret, "got error %u\n", GetLastError());
1289 ret = WritePrivateProfileStringA("section1", NULL, NULL, "winetest_map.ini");
1290 ok(ret, "got error %u\n", GetLastError());
1291 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1293 ret = WritePrivateProfileStringA("section1", "name1", "value1", "winetest_map.ini");
1294 ok(ret, "got error %u\n", GetLastError());
1295 ret = WritePrivateProfileSectionA("section1", NULL, "winetest_map.ini");
1296 ok(ret, "got error %u\n", GetLastError());
1297 check_profile_string("section1", "name1", "winetest_map.ini", "default");
1299 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_map\\subkey");
1300 ok(!ret, "got error %u\n", ret);
1301 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_map");
1302 ok(!ret, "got error %u\n", ret);
1304 /* Test GetPrivateProfileSectionNames(). */
1306 memset(buffer, 0xcc, sizeof(buffer));
1307 ret = GetPrivateProfileSectionNamesA(buffer, 5, "winetest_map.ini");
1308 ok(ret == 3, "got %u\n", ret);
1309 ok(!memcmp(buffer, "sec\0", 5), "got %s\n", debugstr_an(buffer, ret));
1311 memset(buffer, 0xcc, sizeof(buffer));
1312 ret = GetPrivateProfileSectionNamesA(buffer, sizeof(buffer), "winetest_map.ini");
1313 ok(ret == 9, "got %u\n", ret);
1314 ok(!memcmp(buffer, "section1\0", 10), "got %s\n", debugstr_an(buffer, ret));
1316 ret = WritePrivateProfileStringA("file_section", "name1", "value1", "winetest_map.ini");
1317 ok(ret, "got error %u\n", GetLastError());
1319 memset(buffer, 0xcc, sizeof(buffer));
1320 ret = GetPrivateProfileSectionNamesA(buffer, 5, "winetest_map.ini");
1321 ok(ret == 3, "got %u\n", ret);
1322 ok(!memcmp(buffer, "sec\0", 5), "got %s\n", debugstr_an(buffer, ret));
1324 memset(buffer, 0xcc, sizeof(buffer));
1325 ret = GetPrivateProfileSectionNamesA(buffer, sizeof(buffer), "winetest_map.ini");
1326 ok(ret == 22, "got %u\n", ret);
1327 ok(!memcmp(buffer, "section1\0file_section\0", 23), "got %s\n", debugstr_an(buffer, ret));
1329 ret = DeleteFileA("C:/windows/winetest_map.ini");
1330 ok(ret, "got error %u\n", GetLastError());
1332 /* Test the SYS: prefix. */
1334 ret = RegSetValueExA(mapping_key, "section2", 0, REG_SZ, (BYTE *)"SYS:winetest_map", sizeof("SYS:winetest_map"));
1335 ok(!ret, "got error %u\n", ret);
1336 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1337 todo_wine ok(ret, "got error %u\n", GetLastError());
1339 check_profile_string("section2", "name1", "winetest_map.ini", "default");
1341 ret = WritePrivateProfileStringA("section2", "name1", "value1", "winetest_map.ini");
1342 ok(ret, "got error %u\n", GetLastError());
1344 check_profile_string("section2", "name1", "winetest_map.ini", "value1");
1346 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1347 ok(!ret, "got error %u\n", ret);
1348 check_registry_value(mapped_key, "name1", "value1");
1350 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1351 ok(!ret, "got error %u\n", ret);
1353 check_profile_string("section2", "name2", "winetest_map.ini", "value2");
1355 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1356 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1358 ret = RegDeleteKeyA(mapped_key, "");
1359 ok(!ret, "got error %u\n", ret);
1360 RegCloseKey(mapped_key);
1362 /* Try writing directly to the .ini file on disk instead. */
1364 ret = WritePrivateProfileStringA("section3", "name1", "value1", "winetest_map.ini");
1365 ok(ret, "got error %u\n", GetLastError());
1366 check_profile_string("section3", "name1", "winetest_map.ini", "value1");
1368 ret = RegSetValueExA(mapping_key, "section3", 0, REG_SZ, (BYTE *)"USR:winetest_map", sizeof("USR:winetest_map"));
1369 ok(!ret, "got error %u\n", ret);
1370 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1371 todo_wine ok(ret, "got error %u\n", GetLastError());
1373 check_profile_string("section3", "name1", "winetest_map.ini", "default");
1375 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_section3", 0, KEY_READ | KEY_WRITE, &mapped_key);
1376 ok(ret == ERROR_FILE_NOT_FOUND, "got error %u\n", ret);
1378 ret = WritePrivateProfileStringA("section3", "name1", "value2", "winetest_map.ini");
1379 ok(ret, "got error %u\n", GetLastError());
1381 check_profile_string("section3", "name1", "winetest_map.ini", "value2");
1383 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
1384 ok(!ret, "got error %u\n", ret);
1386 ret = RegDeleteKeyA(mapped_key, "");
1387 ok(!ret, "got error %u\n", ret);
1388 RegCloseKey(mapped_key);
1390 ret = RegDeleteValueA(mapping_key, "section3");
1391 ok(!ret, "got error %u\n", ret);
1392 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1393 todo_wine ok(ret, "got error %u\n", GetLastError());
1395 check_profile_string("section3", "name1", "winetest_map.ini", "value1");
1397 ret = DeleteFileA("C:/windows/winetest_map.ini");
1398 ok(ret, "got error %u\n", GetLastError());
1400 /* Test default keys. */
1402 ret = WritePrivateProfileStringA("section4", "name1", "value1", "winetest_map.ini");
1403 ok(ret, "got error %u\n", GetLastError());
1405 check_profile_string("section4", "name1", "winetest_map.ini", "value1");
1407 ret = DeleteFileA("C:/windows/winetest_map.ini");
1408 ok(ret, "got error %u\n", GetLastError());
1410 ret = RegSetValueExA(mapping_key, NULL, 0, REG_SZ, (BYTE *)"SYS:winetest_default", sizeof("SYS:winetest_default"));
1411 ok(!ret, "got error %u\n", ret);
1412 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1413 todo_wine ok(ret, "got error %u\n", GetLastError());
1415 ret = WritePrivateProfileStringA("section4", "name1", "value1", "winetest_map.ini");
1416 ok(ret, "got error %u\n", GetLastError());
1418 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\section4", 0, KEY_READ, &mapped_key);
1419 ok(!ret, "got error %u\n", ret);
1420 check_registry_value(mapped_key, "name1", "value1");
1421 RegCloseKey(mapped_key);
1423 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\section5",
1424 0, NULL, 0, KEY_WRITE, NULL, &mapped_key, NULL);
1425 ok(!ret, "got error %u\n", ret);
1426 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"value2", sizeof("value2"));
1427 ok(!ret, "got error %u\n", ret);
1428 RegCloseKey(mapped_key);
1430 check_profile_string("section5", "name2", "winetest_map.ini", "value2");
1432 ret = GetFileAttributesA("C:/windows/winetest_map.ini");
1433 ok(ret == INVALID_FILE_ATTRIBUTES, "winetest_map.ini should not exist.\n");
1435 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\Section4");
1436 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default\\Section5");
1437 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_default");
1438 ok(!ret, "got error %u\n", ret);
1439 ret = RegDeleteValueA(mapping_key, NULL);
1440 ok(!ret, "got error %u\n", ret);
1442 /* Test name-specific mapping. */
1444 ret = RegCreateKeyExA(mapping_key, "section6", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &mapping_subkey, NULL);
1445 ok(!ret, "got error %u\n", ret);
1446 ret = RegSetValueExA(mapping_subkey, "name1", 0, REG_SZ, (BYTE *)"USR:winetest_name1", sizeof("USR:winetest_name1"));
1447 ok(!ret, "got error %u\n", ret);
1448 ret = RegSetValueExA(mapping_subkey, "name2", 0, REG_SZ, (BYTE *)"SYS:winetest_name2", sizeof("SYS:winetest_name2"));
1449 ok(!ret, "got error %u\n", ret);
1450 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1451 todo_wine ok(ret, "got error %u\n", GetLastError());
1453 ret = WritePrivateProfileStringA("section6", "name1", "value1", "winetest_map.ini");
1454 ok(ret, "got error %u\n", GetLastError());
1455 check_profile_string("section6", "name1", "winetest_map.ini", "value1");
1457 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_name1", 0, KEY_READ | KEY_WRITE, &mapped_key);
1458 ok(!ret, "got error %u\n", ret);
1459 check_registry_value(mapped_key, "name1", "value1");
1461 ret = RegSetValueExA(mapped_key, "name1", 0, REG_SZ, (BYTE *)"one", sizeof("one"));
1462 ok(!ret, "got error %u\n", ret);
1463 check_profile_string("section6", "name1", "winetest_map.ini", "one");
1465 ret = RegDeleteKeyA(mapped_key, "");
1466 ok(!ret, "got error %u\n", ret);
1467 RegCloseKey(mapped_key);
1469 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1470 ok(ret, "got error %u\n", GetLastError());
1472 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2", 0, KEY_READ | KEY_WRITE, &mapped_key);
1473 ok(!ret, "got error %u\n", ret);
1474 check_registry_value(mapped_key, "name2", "value2");
1476 ret = RegSetValueExA(mapped_key, "name2", 0, REG_SZ, (BYTE *)"two", sizeof("two"));
1477 ok(!ret, "got error %u\n", ret);
1478 check_profile_string("section6", "name2", "winetest_map.ini", "two");
1480 ret = RegDeleteKeyA(mapped_key, "");
1481 ok(!ret, "got error %u\n", ret);
1482 RegCloseKey(mapped_key);
1484 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1485 ok(ret, "got error %u\n", GetLastError());
1486 check_profile_string("section6", "name3", "winetest_map.ini", "value3");
1487 ret = DeleteFileA("C:/windows/winetest_map.ini");
1488 ok(ret, "got error %u\n", GetLastError());
1490 /* Test name-specific mapping with Get/WritePrivateProfileSection(). */
1492 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1493 ok(ret, "got error %u\n", GetLastError());
1495 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1496 ok(ret, "got error %u\n", GetLastError());
1498 ret = WritePrivateProfileSectionA("section6", "name1=one\0name3=three\0", "winetest_map.ini");
1499 ok(ret, "got error %u\n", GetLastError());
1500 check_profile_string("section6", "name1", "winetest_map.ini", "one");
1501 check_profile_string("section6", "name2", "winetest_map.ini", "value2");
1502 check_profile_string("section6", "name3", "winetest_map.ini", "value3");
1504 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_name1", 0, KEY_READ | KEY_WRITE, &mapped_key);
1505 ok(!ret, "got error %u\n", ret);
1506 ret = RegDeleteValueA(mapped_key, "name1");
1507 ok(!ret, "got error %u\n", ret);
1508 RegCloseKey(mapped_key);
1510 memset(buffer, 0xcc, sizeof(buffer));
1511 ret = GetPrivateProfileSectionA("section6", buffer, 5, "winetest_map.ini");
1512 ok(ret == 3, "got %u\n", ret);
1513 ok(!memcmp(buffer, "nam\0", 5), "got %s\n", debugstr_an(buffer, ret));
1515 memset(buffer, 0xcc, sizeof(buffer));
1516 ret = GetPrivateProfileSectionA("section6", buffer, sizeof(buffer), "winetest_map.ini");
1517 ok(ret == 26, "got %u\n", ret);
1518 ok(!memcmp(buffer, "name2=value2\0name3=value3\0", 27), "got %s\n", debugstr_an(buffer, ret));
1520 ret = WritePrivateProfileStringA("section6", NULL, NULL, "winetest_map.ini");
1521 ok(ret, "got error %u\n", GetLastError());
1522 check_profile_string("section6", "name1", "winetest_map.ini", "default");
1523 check_profile_string("section6", "name2", "winetest_map.ini", "default");
1524 check_profile_string("section6", "name3", "winetest_map.ini", "default");
1526 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_name1");
1527 ok(!ret, "got error %u\n", ret);
1528 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2");
1529 ok(!ret, "got error %u\n", ret);
1530 ret = DeleteFileA("C:/windows/winetest_map.ini");
1531 ok(ret, "got error %u\n", GetLastError());
1533 /* Test name-specific mapping with a default value. */
1535 ret = RegSetValueExA(mapping_subkey, NULL, 0, REG_SZ, (BYTE *)"USR:winetest_default", sizeof("USR:winetest_default"));
1536 ok(!ret, "got error %u\n", ret);
1537 ret = WritePrivateProfileStringA(NULL, NULL, NULL, "winetest_map.ini");
1538 todo_wine ok(ret, "got error %u\n", GetLastError());
1540 ret = WritePrivateProfileStringA("section6", "name2", "value2", "winetest_map.ini");
1541 ok(ret, "got error %u\n", GetLastError());
1542 ret = WritePrivateProfileStringA("section6", "name3", "value3", "winetest_map.ini");
1543 ok(ret, "got error %u\n", GetLastError());
1545 ret = RegOpenKeyExA(HKEY_CURRENT_USER, "winetest_default", 0, KEY_READ | KEY_WRITE, &mapped_key);
1546 ok(!ret, "got error %u\n", ret);
1547 check_registry_value(mapped_key, "name3", "value3");
1549 ret = RegSetValueExA(mapped_key, "name3", 0, REG_SZ, (BYTE *)"three", sizeof("three"));
1550 ok(!ret, "got error %u\n", ret);
1551 check_profile_string("section6", "name3", "winetest_map.ini", "three");
1553 memset(buffer, 0xcc, sizeof(buffer));
1554 ret = GetPrivateProfileSectionA("section6", buffer, sizeof(buffer), "winetest_map.ini");
1555 ok(ret == 25, "got %u\n", ret);
1556 todo_wine ok(!memcmp(buffer, "name2=value2\0name3=three\0", 26), "got %s\n", debugstr_an(buffer, ret));
1558 ret = WritePrivateProfileSectionA("section6", "name2=duo\0name3=treis\0", "winetest_map.ini");
1559 ok(ret, "got error %u\n", GetLastError());
1560 check_profile_string("section6", "name2", "winetest_map.ini", "duo");
1561 check_profile_string("section6", "name3", "winetest_map.ini", "treis");
1563 ret = WritePrivateProfileStringA("section6", NULL, NULL, "winetest_map.ini");
1564 ok(ret, "got error %u\n", GetLastError());
1565 check_profile_string("section6", "name2", "winetest_map.ini", "default");
1566 check_profile_string("section6", "name3", "winetest_map.ini", "default");
1568 ret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "Software\\winetest_name2");
1569 ok(!ret, "got error %u\n", ret);
1570 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "winetest_name1");
1571 ok(!ret, "got error %u\n", ret);
1572 ret = RegDeleteKeyA(mapped_key, "");
1573 ok(!ret, "got error %u\n", ret);
1574 RegCloseKey(mapped_key);
1576 ret = RegDeleteKeyA(mapping_subkey, "");
1577 ok(!ret, "got error %u\n", ret);
1578 RegCloseKey(mapping_subkey);
1580 ret = RegDeleteKeyA(mapping_key, "");
1581 ok(!ret, "got error %u\n", ret);
1582 RegCloseKey(mapping_key);
1584 ret = DeleteFileA("C:/windows/winetest_map.ini");
1585 ok(!ret, "expected failure\n");
1586 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError());
1587 ret = RevertToSelf();
1588 ok(ret, "got error %u\n", GetLastError());
1591 START_TEST(profile)
1593 test_profile_int();
1594 test_profile_string();
1595 test_profile_sections();
1596 test_profile_sections_names();
1597 test_profile_existing();
1598 test_profile_delete_on_close();
1599 test_profile_refresh();
1600 test_profile_directory_readonly();
1601 test_GetPrivateProfileString(
1602 "[section1]\r\n"
1603 "name1=val1\r\n"
1604 "name2=\"val2\"\r\n"
1605 "name3\r\n"
1606 "name4=a\r\n"
1607 "[section2]\r\n",
1608 "CR+LF");
1609 test_GetPrivateProfileString(
1610 "[section1]\r"
1611 "name1=val1\r"
1612 "name2=\"val2\"\r"
1613 "name3\r"
1614 "name4=a\r"
1615 "[section2]\r",
1616 "CR only");
1617 test_WritePrivateProfileString();
1618 test_profile_struct();
1619 test_registry_mapping();