diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c index a412e1e6dcf..9b6b1a1ac6a 100644 --- a/dlls/kernel32/profile.c +++ b/dlls/kernel32/profile.c @@ -708,7 +708,7 @@ static void PROFILE_ReleaseFile(void) * * Open a profile file, checking the cached file first. */ -static BOOL PROFILE_Open( LPCWSTR filename ) +static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access ) { WCHAR windirW[MAX_PATH]; WCHAR buffer[MAX_PATH]; @@ -754,8 +754,9 @@ static BOOL PROFILE_Open( LPCWSTR filename ) TRACE("path: %s\n", debugstr_w(buffer)); - hFile = CreateFileW(buffer, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + hFile = CreateFileW(buffer, GENERIC_READ | (write_access ? GENERIC_WRITE : 0), + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if ((hFile == INVALID_HANDLE_VALUE) && (GetLastError() != ERROR_FILE_NOT_FOUND)) { @@ -1104,7 +1105,7 @@ static int PROFILE_GetPrivateProfileString( LPCWSTR section, LPCWSTR entry, RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) { + if (PROFILE_Open( filename, FALSE )) { if (win32 && (section == NULL)) ret = PROFILE_GetSectionNames(buffer, len); else @@ -1336,7 +1337,7 @@ INT WINAPI GetPrivateProfileSectionW( LPCWSTR section, LPWSTR buffer, RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) + if (PROFILE_Open( filename, FALSE )) ret = PROFILE_GetSection(CurProfile->section, section, buffer, len, TRUE, FALSE); RtlLeaveCriticalSection( &PROFILE_CritSect ); @@ -1419,12 +1420,12 @@ BOOL WINAPI WritePrivateProfileStringW( LPCWSTR section, LPCWSTR entry, if (!section && !entry && !string) /* documented "file flush" case */ { - if (!filename || PROFILE_Open( filename )) + if (!filename || PROFILE_Open( filename, TRUE )) { if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ } } - else if (PROFILE_Open( filename )) + else if (PROFILE_Open( filename, TRUE )) { if (!section) { FIXME("(NULL?,%s,%s,%s)?\n", @@ -1479,12 +1480,12 @@ BOOL WINAPI WritePrivateProfileSectionW( LPCWSTR section, if (!section && !string) { - if (!filename || PROFILE_Open( filename )) + if (!filename || PROFILE_Open( filename, TRUE )) { if (CurProfile) PROFILE_ReleaseFile(); /* always return FALSE in this case */ } } - else if (PROFILE_Open( filename )) { + else if (PROFILE_Open( filename, TRUE )) { if (!string) {/* delete the named section*/ ret = PROFILE_SetString(section,NULL,NULL, FALSE); PROFILE_FlushFile(); @@ -1607,7 +1608,7 @@ DWORD WINAPI GetPrivateProfileSectionNamesW( LPWSTR buffer, DWORD size, RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) + if (PROFILE_Open( filename, FALSE )) ret = PROFILE_GetSectionNames(buffer, size); RtlLeaveCriticalSection( &PROFILE_CritSect ); @@ -1662,7 +1663,7 @@ BOOL WINAPI GetPrivateProfileStructW (LPCWSTR section, LPCWSTR key, RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) { + if (PROFILE_Open( filename, FALSE )) { PROFILEKEY *k = PROFILE_Find ( &CurProfile->section, section, key, FALSE, FALSE); if (k) { TRACE("value (at %p): %s\n", k->value, debugstr_w(k->value)); @@ -1782,7 +1783,7 @@ BOOL WINAPI WritePrivateProfileStructW (LPCWSTR section, LPCWSTR key, RtlEnterCriticalSection( &PROFILE_CritSect ); - if (PROFILE_Open( filename )) { + if (PROFILE_Open( filename, TRUE )) { ret = PROFILE_SetString( section, key, outstring, FALSE); PROFILE_FlushFile(); } diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c index 54ad6da0d5f..cddc9a00a3c 100644 --- a/dlls/kernel32/tests/profile.c +++ b/dlls/kernel32/tests/profile.c @@ -19,6 +19,7 @@ */ #include +#include #include "wine/test.h" #include "windef.h" @@ -29,7 +30,6 @@ #define SECTION "Test" #define TESTFILE ".\\testwine.ini" #define TESTFILE2 ".\\testwine2.ini" -#define TESTFILE3 ".\\testwine3.ini" struct _profileInt { LPCSTR section; @@ -270,21 +270,25 @@ static void test_profile_sections_names(void) /* If the ini-file has already been opened with CreateFile, WritePrivateProfileString failed in wine with an error ERROR_SHARING_VIOLATION, some testing here */ static void test_profile_existing(void) { + static const char *testfile1 = ".\\winesharing1.ini"; + static const char *testfile2 = ".\\winesharing2.ini"; + static const struct { DWORD dwDesiredAccess; DWORD dwShareMode; - DWORD error; + DWORD write_error; + BOOL read_error; } pe[] = { - {GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION}, - {GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION}, - {GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION}, - {GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION}, - {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION}, - {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION}, - {GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0}, - {GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0}, + {GENERIC_READ, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, + {GENERIC_READ, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, + {GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, + {GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, + {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ERROR_SHARING_VIOLATION, FALSE }, + {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, ERROR_SHARING_VIOLATION, TRUE }, + {GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE }, + {GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE }, /*Thief demo (bug 5024) opens .ini file like this*/ - {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0}, + {GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, FALSE } }; int i; @@ -295,28 +299,53 @@ static void test_profile_existing(void) for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++) { - h = CreateFile(TESTFILE3, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + h = CreateFile(testfile1, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i); SetLastError(0xdeadbeef); - ret = WritePrivateProfileString(SECTION, KEY, "12345", TESTFILE3); - if (!pe[i].error) + + ret = WritePrivateProfileString(SECTION, KEY, "12345", testfile1); + if (!pe[i].write_error) { ok( ret, "%d: WritePrivateProfileString failed with error %u\n", i, GetLastError() ); CloseHandle(h); - size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, TESTFILE3); + size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1); ok( size == 5, "%d: test failed, number of characters copied: %d instead of 5\n", i, size ); } else { DWORD err = GetLastError(); ok( !ret, "%d: WritePrivateProfileString succeeded\n", i ); - if (!ret) ok( err == pe[i].error, "%d: WritePrivateProfileString failed with error %u/%u\n", i, err, pe[i].error ); + if (!ret) + ok( err == pe[i].write_error, "%d: WritePrivateProfileString failed with error %u/%u\n", + i, err, pe[i].write_error ); CloseHandle(h); - size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, TESTFILE3); + size = GetPrivateProfileString(SECTION, KEY, 0, buffer, MAX_PATH, testfile1); ok( !size, "%d: test failed, number of characters copied: %d instead of 0\n", i, size ); } - ok( DeleteFile(TESTFILE3), "delete failed\n" ); + + ok( DeleteFile(testfile1), "delete failed\n" ); } + + h = CreateFile(testfile2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + sprintf( buffer, "[%s]\r\n%s=123\r\n", SECTION, KEY ); + ok( WriteFile( h, buffer, strlen(buffer), &size, NULL ), "failed to write\n" ); + CloseHandle( h ); + + for (i=0; i < sizeof(pe)/sizeof(pe[0]); i++) + { + h = CreateFile(testfile2, pe[i].dwDesiredAccess, pe[i].dwShareMode, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + ok(INVALID_HANDLE_VALUE != h, "%d: CreateFile failed\n",i); + SetLastError(0xdeadbeef); + ret = GetPrivateProfileStringA(SECTION, KEY, NULL, buffer, MAX_PATH, testfile2); + if (!pe[i].read_error) + ok( ret, "%d: GetPrivateProfileString failed with error %u\n", i, GetLastError() ); + else + ok( !ret, "%d: GetPrivateProfileString succeeded\n", i ); + CloseHandle(h); + } + ok( DeleteFile(testfile2), "delete failed\n" ); } START_TEST(profile)