Michael Karcher : kernel32: Fix profile cache logic and don' t cache new files.

Alexandre Julliard julliard at winehq.org
Wed Aug 20 08:14:07 CDT 2008


Module: wine
Branch: master
Commit: 34aa6b7002af0155c6f0cc31a013391b17f62eea
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=34aa6b7002af0155c6f0cc31a013391b17f62eea

Author: Michael Karcher <wine at 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();
 }




More information about the wine-cvs mailing list