Reactos
at master 1688 lines 70 kB view raw
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 { 45 LPCSTR section; 46 LPCSTR key; 47 LPCSTR value; 48 LPCSTR iniFile; 49 INT defaultVal; 50 UINT result; 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 86 DeleteFileA( TESTFILE); 87 88 for (i=0; i < num_test; i++) { 89 if (profileInt[i].value) 90 WritePrivateProfileStringA(SECTION, KEY, 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 105 DeleteFileA( TESTFILE); 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"; 127 DeleteFileA( TESTFILE2); 128 h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 129 FILE_ATTRIBUTE_NORMAL, NULL); 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 153 h = CreateFileA( TESTFILE2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 154 FILE_ATTRIBUTE_NORMAL, NULL); 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); 162 todo_wine 163 ok(ret == 13, "expected 13, got %u\n", ret); 164 todo_wine 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 174 DeleteFileA( TESTFILE2); 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 ); 189 h = CreateFileA( testfile4, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 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); 197 ret = GetPrivateProfileSectionA( NULL, NULL, 0, NULL ); 198 ok( ret == 0, "expected return size 0, got %d\n", ret ); 199 ok( GetLastError() == ERROR_INVALID_PARAMETER || 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 ); 207 ok( GetLastError() == ERROR_INVALID_PARAMETER || 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 ); 222 ok( GetLastError() == ERROR_INVALID_PARAMETER, 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 ); 228 todo_wine 229 ok( GetLastError() == ERROR_FILE_NOT_FOUND, 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 ); 236 ok( GetLastError() == ERROR_SUCCESS, 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" ); 247 ok( GetLastError() == ERROR_SUCCESS, 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" ); 259 ok( GetLastError() == ERROR_SUCCESS, 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 273static void test_profile_sections_names(void) 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, 286 FILE_ATTRIBUTE_NORMAL, NULL); 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 ); 304 todo_wine 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"); 314 todo_wine 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 ); 329 if (ret == 0 && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) 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[] = { 375 {GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, 376 {GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, 377 {GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, 378 {GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, 379 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, 380 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, 381 {GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */}, 382 {GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */}, 383 /*Thief demo (bug 5024) opens .ini file like this*/ 384 {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE, ERROR_SHARING_VIOLATION /* nt4 */} 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, 396 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 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); 407 size = GetPrivateProfileStringA(SECTION, KEY, 0, buffer, MAX_PATH, testfile1); 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 { 415 DWORD err = GetLastError(); 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); 421 size = GetPrivateProfileStringA(SECTION, KEY, 0, buffer, MAX_PATH, testfile1); 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 428 h = CreateFileA(testfile2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 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, 436 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 437 ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i); 438 SetLastError(0xdeadbeef); 439 ret = GetPrivateProfileStringA(SECTION, KEY, NULL, buffer, MAX_PATH, testfile2); 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 449static void test_profile_delete_on_close(void) 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 456 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, 457 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 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 478 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, 479 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 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 492 h = CreateFileA(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, 493 CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 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 511static void create_test_file(LPCSTR name, LPCSTR data, DWORD size) 512{ 513 HANDLE hfile; 514 DWORD count; 515 516 hfile = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 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 536static void test_profile_directory_readonly(void) 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); 546 ret = ConvertStringSecurityDescriptorToSecurityDescriptorA(sddl_string_everyone_readonly, SDDL_REVISION_1, &attributes.lpSecurityDescriptor, NULL); 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 570 LocalFree(attributes.lpSecurityDescriptor); 571} 572 573static void test_GetPrivateProfileString(const char *content, const char *descript) 574{ 575 DWORD ret, len; 576 CHAR buf[MAX_PATH]; 577 CHAR def_val[MAX_PATH]; 578 CHAR path[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 589 create_test_file(filename, content, lstrlenA(content)); 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", 599 buf, MAX_PATH, filename); 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", 611 buf, MAX_PATH, filename); 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", 620 buf, MAX_PATH, filename); 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, 628 buf, MAX_PATH, filename); 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", "", 637 buf, MAX_PATH, filename); 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, 648 buf, MAX_PATH, filename); 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, 659 buf, MAX_PATH, filename); 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", 668 buf, MAX_PATH, filename); 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", 677 buf, MAX_PATH, filename); 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", 687 buf, MAX_PATH, filename); 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", 696 buf, MAX_PATH, filename); 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, 704 buf, MAX_PATH, filename); 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, "", 713 buf, MAX_PATH, filename); 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, 724 buf, MAX_PATH, filename); 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", 733 NULL, MAX_PATH, filename); 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", 788 buf, MAX_PATH, filename); 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); 807 todo_wine 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); 818 todo_wine 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", 827 buf, MAX_PATH, filename); 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", 835 buf, MAX_PATH, filename); 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 847 GetWindowsDirectoryA(windir, MAX_PATH); 848 SetLastError(0xdeadbeef); 849 ret = GetTempFileNameA(windir, "pre", 0, path); 850 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 851 { 852 skip("Not allowed to create a file in the Windows directory\n"); 853 DeleteFileA(filename); 854 return; 855 } 856 tempfile = strrchr(path, '\\') + 1; 857 create_test_file(path, content, lstrlenA(content)); 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", 871 buf, MAX_PATH, filename); 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", "", 879 buf, MAX_PATH, filename); 880 ok( ret == 0, "expected return size 0, got %ld\n", ret ); 881 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 882 todo_wine 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 888 DeleteFileA(path); 889 DeleteFileA(filename); 890} 891 892static BOOL check_binary_file_data(LPCSTR path, const VOID *data, DWORD size) 893{ 894 HANDLE file; 895 CHAR buf[MAX_PATH]; 896 BOOL ret; 897 898 file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); 899 if (file == INVALID_HANDLE_VALUE) 900 return FALSE; 901 902 if(size != GetFileSize(file, NULL) ) 903 { 904 CloseHandle(file); 905 return FALSE; 906 } 907 908 ret = ReadFile(file, buf, size, &size, NULL); 909 CloseHandle(file); 910 if (!ret) 911 return FALSE; 912 913 return !memcmp(buf, data, size); 914} 915 916static BOOL check_file_data(LPCSTR path, LPCSTR data) 917{ 918 return check_binary_file_data(path, data, lstrlenA(data)); 919} 920 921static void test_WritePrivateProfileString(void) 922{ 923 BOOL ret; 924 LPCSTR data; 925 CHAR path[MAX_PATH]; 926 CHAR temp[MAX_PATH]; 927 HANDLE file; 928 929 GetTempPathA(MAX_PATH, temp); 930 GetTempFileNameA(temp, "wine", 0, path); 931 DeleteFileA(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); 939 ok(GetLastError() == ERROR_FILE_NOT_FOUND, 940 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError()); 941 ok(GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES, 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); 951 ok(GetLastError() == ERROR_FILE_NOT_FOUND, 952 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError()); 953 ok(check_file_data(path, data), "File doesn't match\n"); 954 DeleteFileA(path); 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"); 964 DeleteFileA(path); 965 } 966 967 /* NULL lpKeyName */ 968 data = ""; 969 ret = WritePrivateProfileStringA("App", NULL, "string", path); 970 ok(ret == TRUE, "Expected TRUE, got %d\n", ret); 971 todo_wine 972 { 973 ok(check_file_data(path, data), "File doesn't match\n"); 974 } 975 DeleteFileA(path); 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); 984 todo_wine 985 { 986 ok(check_file_data(path, data), "File doesn't match\n"); 987 } 988 DeleteFileA(path); 989 } 990 991 /* NULL lpString */ 992 data = ""; 993 ret = WritePrivateProfileStringA("App", "key", NULL, path); 994 ok(ret == TRUE, "Expected TRUE, got %d\n", ret); 995 todo_wine 996 { 997 ok(check_file_data(path, data), "File doesn't match\n"); 998 } 999 DeleteFileA(path); 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"); 1007 DeleteFileA(path); 1008 1009 /* empty lpFileName */ 1010 SetLastError(0xdeadbeef); 1011 ret = WritePrivateProfileStringA("App", "key", "string", ""); 1012 ok(ret == FALSE, "Expected FALSE, got %d\n", ret); 1013 ok(GetLastError() == ERROR_ACCESS_DENIED, 1014 "Expected ERROR_ACCESS_DENIED, got %ld\n", GetLastError()); 1015 1016 /* Relative paths are relative to X:\\%WINDIR% */ 1017 GetWindowsDirectoryA(path, MAX_PATH); 1018 strcat(path, "\\win1.tmp"); 1019 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1020 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 1021 skip("Not allowed to create a file in the Windows directory\n"); 1022 else 1023 { 1024 CloseHandle(file); 1025 DeleteFileA(path); 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"); 1032 DeleteFileA(path); 1033 } 1034 1035 GetTempPathA(MAX_PATH, temp); 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"; 1093 ret = WritePrivateProfileStringA("App2", NULL, NULL, path); 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"); 1102 DeleteFileA(path); 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); 1109 create_test_file(path, data, 31); 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"); 1114 DeleteFileA(path); 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)); 1209 ret = RegQueryValueExA(key, value, 0, &type, (BYTE *)buffer, &size); 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 */ 1234 ret = ImpersonateSelf(SecurityImpersonation); 1235 ok(ret, "got error %lu\n", GetLastError()); 1236 1237 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, 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__ 1270 ret = GetFileAttributesA(path); 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__ 1396 ret = GetFileAttributesA(path); 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__ 1485 ret = GetFileAttributesA(path); 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 1659START_TEST(profile) 1660{ 1661 test_profile_int(); 1662 test_profile_string(); 1663 test_profile_sections(); 1664 test_profile_sections_names(); 1665 test_profile_existing(); 1666 test_profile_delete_on_close(); 1667 test_profile_refresh(); 1668 test_profile_directory_readonly(); 1669 test_GetPrivateProfileString( 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"); 1677 test_GetPrivateProfileString( 1678 "[section1]\r" 1679 "name1=val1\r" 1680 "name2=\"val2\"\r" 1681 "name3\r" 1682 "name4=a\r" 1683 "[section2]\r", 1684 "CR only"); 1685 test_WritePrivateProfileString(); 1686 test_profile_struct(); 1687 test_registry_mapping(); 1688}