kernel32: fix PROFILE_Load to handle mac line endings (try 3)

Erik Inge Bolsø knan-wine at anduin.net
Sat Sep 20 19:15:36 CDT 2008


Fixes bug 15281. With testcase.
---
 dlls/kernel32/profile.c       |    1 +
 dlls/kernel32/tests/profile.c |  168 ++++++++++++++++++++++-------------------
 2 files changed, 90 insertions(+), 79 deletions(-)

Testcase has been run on win2k by Nicolas Le Cam:
http://www.winehq.org/pipermail/wine-devel/2008-September/069107.html

Change from v1: removed unneeded hunk, ref Michael Karcher
Change from v2: refactored testcase, ref Paul Vriens

diff --git a/dlls/kernel32/profile.c b/dlls/kernel32/profile.c
index ab26533..3ed2dcd 100644
--- a/dlls/kernel32/profile.c
+++ b/dlls/kernel32/profile.c
@@ -405,6 +405,7 @@ static PROFILESECTION *PROFILE_Load(HANDLE hFile, ENCODING * pEncoding)
     {
         szLineStart = next_line;
         next_line = memchrW(szLineStart, '\n', szEnd - szLineStart);
+        if (!next_line) next_line = memchrW(szLineStart, '\r', szEnd - szLineStart);
         if (!next_line) next_line = szEnd;
         else next_line++;
         szLineEnd = next_line;
diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c
index 8a3e83b..d697de8 100644
--- a/dlls/kernel32/tests/profile.c
+++ b/dlls/kernel32/tests/profile.c
@@ -428,7 +428,7 @@ static BOOL emptystr_ok(CHAR emptystr[MAX_PATH])
     return TRUE;
 }
 
-static void test_GetPrivateProfileString(void)
+static void test_GetPrivateProfileString(const char *content, int run)
 {
     DWORD ret;
     CHAR buf[MAX_PATH];
@@ -441,15 +441,10 @@ static void test_GetPrivateProfileString(void)
     LPSTR tempfile;
 
     static const char filename[] = ".\\winetest.ini";
-    static const char content[]=
-        "[section1]\r\n"
-        "name1=val1\r\n"
-        "name2=\"val2\"\r\n"
-        "name3\r\n"
-        "name4=a\r\n"
-        "[section2]\r\n";
 
-    create_test_file(filename, content, sizeof(content));
+    ok(1, "%s\n", content);
+
+    create_test_file(filename, content, lstrlenA(content));
 
     /* Run this test series with caching. Wine won't cache profile
        files younger than 2.1 seconds. */
@@ -459,40 +454,40 @@ static void test_GetPrivateProfileString(void)
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(NULL, "name1", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 18, "Expected 18, got %d\n", ret);
+    ok(ret == 18, "Run %d: Expected 18, got %d\n", run, ret);
     ok(!memcmp(buf, "section1\0section2\0", ret + 1),
-       "Expected \"section1\\0section2\\0\", got \"%s\"\n", buf);
+       "Run %d: Expected \"section1\\0section2\\0\", got \"%s\"\n", run, buf);
 
     /* lpAppName is empty */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(emptystr, "name1", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpAppName is missing */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("notasection", "name1", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     /* lpAppName is empty, lpDefault is NULL */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(emptystr, "name1", NULL,
                                    buf, MAX_PATH, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, ""), "Run %d: Expected \"\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpAppName is empty, lpDefault is empty */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(emptystr, "name1", "",
                                    buf, MAX_PATH, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, ""), "Run %d: Expected \"\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpAppName is empty, lpDefault has trailing blank characters */
     lstrcpyA(buf, "kumquat");
@@ -500,9 +495,9 @@ static void test_GetPrivateProfileString(void)
     lstrcpyA(def_val, "default  ");
     ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpAppName is empty, many blank characters in lpDefault */
     lstrcpyA(buf, "kumquat");
@@ -510,56 +505,56 @@ static void test_GetPrivateProfileString(void)
     lstrcpyA(def_val, "one two  ");
     ret = GetPrivateProfileStringA(emptystr, "name1", def_val,
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "one two"), "Run %d: Expected \"one two\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpAppName is empty, blank character but not trailing in lpDefault */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(emptystr, "name1", "one two",
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "AppName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "one two"), "Run %d: Expected \"one two\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: AppName modified\n", run);
 
     /* lpKeyName is NULL */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", NULL, "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 18, "Expected 18, got %d\n", ret);
+    ok(ret == 18, "Run %d: Expected 18, got %d\n", run, ret);
     ok(!memcmp(buf, "name1\0name2\0name4\0", ret + 1),
-       "Expected \"name1\\0name2\\0name4\\0\", got \"%s\"\n", buf);
+       "Run %d: Expected \"name1\\0name2\\0name4\\0\", got \"%s\"\n", run, buf);
 
     /* lpKeyName is empty */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", emptystr, "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "KeyName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: KeyName modified\n", run);
 
     /* lpKeyName is missing */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "notakey", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     /* lpKeyName is empty, lpDefault is NULL */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", emptystr, NULL,
                                    buf, MAX_PATH, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "KeyName modified\n");
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, ""), "Run %d: Expected \"\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: KeyName modified\n", run);
 
     /* lpKeyName is empty, lpDefault is empty */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", emptystr, "",
                                    buf, MAX_PATH, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "KeyName modified\n");
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, ""), "Run %d: Expected \"\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: KeyName modified\n", run);
 
     /* lpKeyName is empty, lpDefault has trailing blank characters */
     lstrcpyA(buf, "kumquat");
@@ -567,9 +562,9 @@ static void test_GetPrivateProfileString(void)
     lstrcpyA(def_val, "default  ");
     ret = GetPrivateProfileStringA("section1", emptystr, def_val,
                                    buf, MAX_PATH, filename);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
-    ok(emptystr_ok(emptystr), "KeyName modified\n");
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
+    ok(emptystr_ok(emptystr), "Run %d: KeyName modified\n", run);
 
     if (0) /* crashes */
     {
@@ -582,113 +577,113 @@ static void test_GetPrivateProfileString(void)
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, MAX_PATH, NULL);
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     /* lpFileName is empty */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, MAX_PATH, "");
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     /* lpFileName is nonexistent */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, MAX_PATH, "nonexistent");
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     /* nSize is 0 */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, 0, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, "kumquat"), "Expected buf to be unchanged, got \"%s\"\n", buf);
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "kumquat"), "Run %d: Expected buf to be unchanged, got \"%s\"\n", run, buf);
 
     /* nSize is exact size of output */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, 4, filename);
-    ok(ret == 3, "Expected 3, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val"), "Expected \"val\", got \"%s\"\n", buf);
+    ok(ret == 3, "Run %d: Expected 3, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val"), "Run %d: Expected \"val\", got \"%s\"\n", run, buf);
 
     /* nSize has room for NULL terminator */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, 5, filename);
-    ok(ret == 4, "Expected 4, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
+    ok(ret == 4, "Run %d: Expected 4, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val1"), "Run %d: Expected \"val1\", got \"%s\"\n", run, buf);
 
     /* output is 1 character */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name4", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 1, "Expected 1, got %d\n", ret);
-    ok(!lstrcmpA(buf, "a"), "Expected \"a\", got \"%s\"\n", buf);
+    ok(ret == 1, "Run %d: Expected 1, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "a"), "Run %d: Expected \"a\", got \"%s\"\n", run, buf);
 
     /* output is 1 character, no room for NULL terminator */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name4", "default",
                                    buf, 1, filename);
-    ok(ret == 0, "Expected 0, got %d\n", ret);
-    ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
+    ok(ret == 0, "Run %d: Expected 0, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, ""), "Run %d: Expected \"\", got \"%s\"\n", run, buf);
 
     /* lpAppName is NULL, not enough room for final section name */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA(NULL, "name1", "default",
                                    buf, 16, filename);
-    ok(ret == 14, "Expected 14, got %d\n", ret);
+    ok(ret == 14, "Run %d: Expected 14, got %d\n", run, ret);
     ok(!memcmp(buf, "section1\0secti\0", ret + 1),
-       "Expected \"section1\\0secti\\0\", got \"%s\"\n", buf);
+       "Run %d: Expected \"section1\\0secti\\0\", got \"%s\"\n", run, buf);
 
     /* lpKeyName is NULL, not enough room for final key name */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", NULL, "default",
                                    buf, 16, filename);
-    ok(ret == 14, "Expected 14, got %d\n", ret);
+    ok(ret == 14, "Run %d: Expected 14, got %d\n", run, ret);
     ok(!memcmp(buf, "name1\0name2\0na\0", ret + 1),
-       "Expected \"name1\\0name2\\0na\\0\", got \"%s\"\n", buf);
+       "Run %d: Expected \"name1\\0name2\\0na\\0\", got \"%s\"\n", run, buf);
 
     /* key value has quotation marks which are stripped */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name2", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 4, "Expected 4, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val2"), "Expected \"val2\", got \"%s\"\n", buf);
+    ok(ret == 4, "Run %d: Expected 4, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val2"), "Run %d: Expected \"val2\", got \"%s\"\n", run, buf);
 
     /* case does not match */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 4, "Expected 4, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
+    ok(ret == 4, "Run %d: Expected 4, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val1"), "Run %d: Expected \"val1\", got \"%s\"\n", run, buf);
 
     /* only filename is used */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
                                    buf, MAX_PATH, "winetest.ini");
-    ok(ret == 7, "Expected 7, got %d\n", ret);
-    ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf);
+    ok(ret == 7, "Run %d: Expected 7, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "default"), "Run %d: Expected \"default\", got \"%s\"\n", run, buf);
 
     GetWindowsDirectoryA(windir, MAX_PATH);
     GetTempFileNameA(windir, "pre", 0, path);
     tempfile = strrchr(path, '\\') + 1;
-    create_test_file(path, content, sizeof(content));
+    create_test_file(path, content, lstrlenA(content));
 
     /* only filename is used, file exists in windows directory */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "NaMe1", "default",
                                    buf, MAX_PATH, tempfile);
-    ok(ret == 4, "Expected 4, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
+    ok(ret == 4, "Run %d: Expected 4, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val1"), "Run %d: Expected \"val1\", got \"%s\"\n", run, buf);
 
     /* successful case */
     lstrcpyA(buf, "kumquat");
     ret = GetPrivateProfileStringA("section1", "name1", "default",
                                    buf, MAX_PATH, filename);
-    ok(ret == 4, "Expected 4, got %d\n", ret);
-    ok(!lstrcmpA(buf, "val1"), "Expected \"val1\", got \"%s\"\n", buf);
+    ok(ret == 4, "Run %d: Expected 4, got %d\n", run, ret);
+    ok(!lstrcmpA(buf, "val1"), "Run %d: Expected \"val1\", got \"%s\"\n", run, buf);
 
     DeleteFileA(path);
     DeleteFileA(filename);
@@ -703,5 +698,20 @@ START_TEST(profile)
     test_profile_existing();
     test_profile_delete_on_close();
     test_profile_refresh();
-    test_GetPrivateProfileString();
+    test_GetPrivateProfileString(
+        "[section1]\r\n"
+        "name1=val1\r\n"
+        "name2=\"val2\"\r\n"
+        "name3\r\n"
+        "name4=a\r\n"
+        "[section2]\r\n",
+        1);
+    test_GetPrivateProfileString(
+        "[section1]\r"
+        "name1=val1\r"
+        "name2=\"val2\"\r"
+        "name3\r"
+        "name4=a\r"
+        "[section2]\r",
+        2);
 }
-- 
1.5.4.3



More information about the wine-patches mailing list