[PATCH 1/2] kernel32/tests: Add new test of behavior when passing NULL filename.

Carlos Rivera carlos at superkaos.org
Fri Sep 4 15:42:45 CDT 2020


In Windows, when invoked with filename = NULL, these functions:

WritePrivateProfileStringW,
WritePrivateProfileSectionW,
GetPrivateProfileSectionNamesW,
GetPrivateProfileStringW

Behave as if filename is "win.ini"
If the corresponding map exists in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping
then this map gets used.

Since in freshly installed Wine and Windows 10 such a map exists this tests only verifies
that behavior. It does not verify actual writting/reading to C:\windows\win.ini.

Signed-off-by: Carlos Rivera <carlos at superkaos.org>
---

This IniFileMapping does not actually happen in Wine, which at least in the case of GetPrivateProfileStringW just
tries to read from C:\windows\win.ini

This explains the failure in Wine of the first test in function test_profile_int (get 70, expected 0),
where there is an invokation like this:

GetPrivateProfileIntA(NULL, NULL, 70, NULL)

    And which ends up calling GetPrivateProfileStringW which because the first parameters are NULL
invoke GetPrivateProfileSectionNamesW. It then gets the section names from win.ini. In wine,
the IniFileMapping is ignored and if there is no win.ini file, it returns a 0 and the default
value 70 ends up being returned to the user.
    If one creates a C:\win.ini file with just one section like:
[hello]

Then it gets the section name, and when trying to convert it into a integer it gets converted
to 0. The test passes. Thanks to zf in #winehackers for the tip that this bug had something to
do with the presence of win.ini.

Interestinly enough, if one names the section something like:
[42]

Then test fails with a value of 42 instead of the expected 0!

This behavior is the same in Windows except that it uses the entries in IniFileMapping. If the mapping
is removed the file is used as in Wine.

My next commit will make Wine to make use of the IniFileMapping too when filename=NULL-->win.ini, as
in Windows.
---
 dlls/kernel32/tests/Makefile.in |  2 +-
 dlls/kernel32/tests/profile.c   | 92 +++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 1 deletion(-)

diff --git a/dlls/kernel32/tests/Makefile.in b/dlls/kernel32/tests/Makefile.in
index e9516603ce..04c44e208a 100644
--- a/dlls/kernel32/tests/Makefile.in
+++ b/dlls/kernel32/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = kernel32.dll
-IMPORTS   = user32 advapi32
+IMPORTS   = user32 advapi32 kernelbase
 
 SOURCES = \
 	actctx.c \
diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c
index f981558548..9d89009e46 100644
--- a/dlls/kernel32/tests/profile.c
+++ b/dlls/kernel32/tests/profile.c
@@ -25,6 +25,7 @@
 #include "windef.h"
 #include "winbase.h"
 #include "windows.h"
+#include "shlwapi.h"
 #include "sddl.h"
 
 #define KEY      "ProfileInt"
@@ -1588,6 +1589,96 @@ static void test_registry_mapping(void)
     ok(ret, "got error %u\n", GetLastError());
 }
 
+static void test_null_filename(void)
+{
+    /* Some profile functions assume filename is win.ini if NULL is given
+       and if such a map exists in IniFileMapping then they use it */
+
+    HKEY mapping_key, mapped_key;
+    char buffer[1024];
+    char* p;
+    int found = 0;
+    LSTATUS ret;
+
+    ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                        "Software\\Microsoft\\Windows NT\\CurrentVersion\\IniFileMapping\\win.ini",
+                        0, KEY_READ | KEY_WRITE, &mapping_key);
+
+    if(ret)
+    {
+        skip("Failed to find a win.ini IniFileMapping registry entry\n");
+        return;
+    }
+
+    if (PathFileExistsA("C:/windows/win.ini"))
+    {
+        ret = MoveFileA("C:/windows/win.ini", "C:/windows/winini.bak");
+
+        if (!ret)
+        {
+            skip("Failed to move C:/windows/win.ini out of the way to prevent possibly destructive tests.\n");
+            return;
+        }
+    }
+
+    ret = RegSetValueExA(mapping_key, "section1", 0, REG_SZ, (BYTE *)"USR:section1_map", sizeof("USR:section1_map"));
+    ok(!ret, "got error %u\n", ret);
+    ret = WritePrivateProfileStringA(NULL, NULL, NULL, "win.ini");
+    todo_wine ok(ret, "got error %u\n", GetLastError());
+
+    ret = WritePrivateProfileStringA("section1", "name1", "42", NULL);
+    ok(ret, "got error %u\n", ret);
+
+    ret = DeleteFileA("C:/windows/win.ini");
+    ok(!ret, "expected failure\n");
+
+    ret = RegOpenKeyExA(HKEY_CURRENT_USER, "section1_map", 0, KEY_READ | KEY_WRITE, &mapped_key);
+    check_registry_value(mapped_key, "name1", "42");
+
+    check_profile_string("section1", "name1", NULL, "42");
+
+    memset(buffer, 0xc, sizeof(buffer));
+    ret = GetPrivateProfileSectionNamesA(buffer, sizeof(buffer), NULL);
+    ok(ret, "got error %u\n", ret);
+
+    if (ret)
+    {
+        p = buffer;
+        while (p < (buffer + sizeof(buffer) - 1))
+        {
+            if (!strncmp("section1", p, sizeof(buffer)))
+            {
+                found = 1;
+                break;
+            }
+            while (*p++ && p < (buffer + sizeof(buffer) - 1));
+        }
+    }
+
+    ok(found,
+       "Expected \"section1\" in buffer, but buffer is %s\n",
+       debugstr_an(buffer, (ret + 2 >= sizeof(buffer) ? sizeof(buffer) : ret + 1)));
+
+    ret = WritePrivateProfileSectionA("section1", "name2=mango\0", NULL);
+    ok(ret, "got error %u\n", ret);
+
+    check_registry_value(mapped_key, "name2", "mango");
+
+    ret = DeleteFileA("C:/windows/win.ini");
+    ok(!ret, "expected failure\n");
+
+    MoveFileA("C:/windows/winini.bak", "C:/windows/win.ini");
+
+    ret = RegDeleteValueA(mapping_key, "section1");
+    ok(!ret, "got error %u\n", ret);
+
+    ret = RegDeleteKeyA(HKEY_CURRENT_USER, "section1_map");
+    ok(!ret, "got error %u\n", ret);
+
+    RegCloseKey(mapped_key);
+    RegCloseKey(mapping_key);
+};
+
 START_TEST(profile)
 {
     test_profile_int();
@@ -1617,4 +1708,5 @@ START_TEST(profile)
     test_WritePrivateProfileString();
     test_profile_struct();
     test_registry_mapping();
+    test_null_filename();
 }
-- 
2.28.0




More information about the wine-devel mailing list