Module: wine Branch: master Commit: 34aa6b7002af0155c6f0cc31a013391b17f62eea URL: http://source.winehq.org/git/wine.git/?a=commit;h=34aa6b7002af0155c6f0cc31a0...
Author: Michael Karcher wine@mkarcher.dialup.fu-berlin.de Date: Sun Aug 17 19:03:24 2008 +0200
kernel32: Fix profile cache logic and don't cache new files.
---
dlls/kernel32/profile.c | 37 +++++++++++++++++++++++++++++-------- dlls/kernel32/tests/profile.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c index ac983ff..22d4cb5 100644 --- a/dlls/kernel32/profile.c +++ b/dlls/kernel32/profile.c @@ -702,6 +702,25 @@ static void PROFILE_ReleaseFile(void) ZeroMemory(&CurProfile->LastWriteTime, sizeof(CurProfile->LastWriteTime)); }
+/*********************************************************************** + * + * Compares a file time with the current time. If the file time is + * at least 2.1 seconds in the past, return true. + * + * Intended as cache safety measure: The time resolution on FAT is + * two seconds, so files that are not at least two seconds old might + * keep their time even on modification, so don't cache them. + */ +static BOOL is_not_current(FILETIME * ft) +{ + FILETIME Now; + LONGLONG ftll, nowll; + GetSystemTimeAsFileTime(&Now); + ftll = ((LONGLONG)ft->dwHighDateTime << 32) + ft->dwLowDateTime; + nowll = ((LONGLONG)Now.dwHighDateTime << 32) + Now.dwLowDateTime; + TRACE("%08x;%08x\n",(unsigned)ftll+21000000,(unsigned)nowll); + return ftll + 21000000 < nowll; +}
/*********************************************************************** * PROFILE_Open @@ -780,15 +799,17 @@ static BOOL PROFILE_Open( LPCWSTR filename, BOOL write_access )
if (hFile != INVALID_HANDLE_VALUE) { - if (TRACE_ON(profile)) + GetFileTime(hFile, NULL, NULL, &LastWriteTime); + if (!memcmp( &CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME) ) && + is_not_current(&LastWriteTime)) + TRACE("(%s): already opened (mru=%d)\n", + debugstr_w(buffer), i); + else { - GetFileTime(hFile, NULL, NULL, &LastWriteTime); - if (memcmp(&CurProfile->LastWriteTime, &LastWriteTime, sizeof(FILETIME))) - TRACE("(%s): already opened (mru=%d)\n", - debugstr_w(buffer), i); - else - TRACE("(%s): already opened, needs refreshing (mru=%d)\n", - debugstr_w(buffer), i); + TRACE("(%s): already opened, needs refreshing (mru=%d)\n", + debugstr_w(buffer), i); + CurProfile->section = PROFILE_Load(hFile, &CurProfile->encoding); + CurProfile->LastWriteTime = LastWriteTime; } CloseHandle(hFile); } diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c index 4463f50..9cccac2 100644 --- a/dlls/kernel32/tests/profile.c +++ b/dlls/kernel32/tests/profile.c @@ -362,9 +362,42 @@ static void test_profile_delete_on_close() ok( size == sizeof contents - 1, "Test file: partial write\n");
res = GetPrivateProfileInt(SECTION, KEY, 0, testfile); + ok( res == 123, "Got %d instead of 123\n", res); + + /* This also deletes the file */ + CloseHandle(h); +} + +static void test_profile_refresh(void) +{ + static CHAR testfile[] = ".\winetest4.ini"; + HANDLE h; + DWORD size, res; + static const char contents1[] = "[" SECTION "]\n" KEY "=123\n"; + static const char contents2[] = "[" SECTION "]\n" KEY "=124\n"; + + h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); + ok( WriteFile( h, contents1, sizeof contents1 - 1, &size, NULL ), + "Cannot write test file: %x\n", GetLastError() ); + ok( size == sizeof contents1 - 1, "Test file: partial write\n");
+ res = GetPrivateProfileInt(SECTION, KEY, 0, testfile); ok( res == 123, "Got %d instead of 123\n", res);
+ CloseHandle(h); + + /* Test proper invalidation of wine's profile file cache */ + + h = CreateFile(testfile, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); + ok( WriteFile( h, contents2, sizeof contents2 - 1, &size, NULL ), + "Cannot write test file: %x\n", GetLastError() ); + ok( size == sizeof contents2 - 1, "Test file: partial write\n"); + + res = GetPrivateProfileInt(SECTION, KEY, 0, testfile); + ok( res == 124, "Got %d instead of 124\n", res); + /* This also deletes the file */ CloseHandle(h); } @@ -417,6 +450,10 @@ static void test_GetPrivateProfileString(void)
create_test_file(filename, content, sizeof(content));
+ /* Run this test series with caching. Wine won't cache profile + files younger than 2.1 seconds. */ + Sleep(2500); + /* lpAppName is NULL */ lstrcpyA(buf, "kumquat"); ret = GetPrivateProfileStringA(NULL, "name1", "default", @@ -664,5 +701,6 @@ START_TEST(profile) test_profile_sections_names(); test_profile_existing(); test_profile_delete_on_close(); + test_profile_refresh(); test_GetPrivateProfileString(); }