Tests for RegGetValue

Felix Nawothnig felix.nawothnig at t-online.de
Fri Jul 1 18:50:08 CDT 2005


This (documented) function was introducted with Win2k3 SP1 - it's 
probably not used by any third-party app yet but it would be nice to 
have this so we can implement SHRegGetValue() (which was introduced in 
WinXP SP2 and is used by it's comctl32) on-top of it.

No implementation yet since I'm still wondering how to reproduce the 
strange expansion behaviour (see the last tests) without some ugly 
boolean logic (and no stubs because I'd like to avoid adding a todo_wine 
for a rather simple function)...

Tested on (surprise) Win2k3 SP1.

ChangeLog:
Added unit tests for RegGetValue
-------------- next part --------------
Index: include/winreg.h
===================================================================
RCS file: /home/wine/wine/include/winreg.h,v
retrieving revision 1.29
diff -u -r1.29 winreg.h
--- include/winreg.h	16 Jun 2005 09:45:43 -0000	1.29
+++ include/winreg.h	1 Jul 2005 23:36:42 -0000
@@ -64,6 +64,21 @@
 
 #define MAX_SHUTDOWN_TIMEOUT    (10*365*24*60*60)
 
+/*
+ * RegGetValue() restrictions
+ */
+
+#define RRF_RT_REG_NONE         (1 << 0)
+#define RRF_RT_REG_SZ           (1 << 1)
+#define RRF_RT_REG_EXPAND_SZ    (1 << 2)
+#define RRF_RT_REG_BINARY       (1 << 3)
+#define RRF_RT_REG_DWORD        (1 << 4)
+#define RRF_RT_REG_MULTI_SZ     (1 << 5)
+#define RRF_RT_REG_QWORD        (1 << 6)
+#define RRF_RT_DWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_DWORD)
+#define RRF_RT_QWORD            (RRF_RT_REG_BINARY | RRF_RT_REG_QWORD)
+#define RRF_NOEXPAND            (1 << 28)
+#define RRF_ZEROONFAILURE       (1 << 29)
 
 BOOL        WINAPI AbortSystemShutdownA(LPSTR);
 BOOL        WINAPI AbortSystemShutdownW(LPWSTR);
Index: dlls/advapi32/tests/registry.c
===================================================================
RCS file: /home/wine/wine/dlls/advapi32/tests/registry.c,v
retrieving revision 1.27
diff -u -r1.27 registry.c
--- dlls/advapi32/tests/registry.c	20 Jun 2005 14:18:05 -0000	1.27
+++ dlls/advapi32/tests/registry.c	1 Jul 2005 23:36:43 -0000
@@ -61,6 +61,8 @@
 
 static void create_test_entries(void)
 {
+    DWORD qw[2] = { 0x12345678, 0x87654321 };
+
     SetEnvironmentVariableA("LONGSYSTEMVAR", "bar");
     SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString");
 
@@ -70,6 +72,12 @@
         "RegSetValueExA failed\n");
     ok(!RegSetValueExA(hkey_main,"Test3",0,REG_EXPAND_SZ, sTestpath2, strlen(sTestpath2)+1), 
         "RegSetValueExA failed\n");
+    ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (PVOID)qw, 4),
+        "RegSetValueExA failed\n");
+    ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (PVOID)qw, 4),
+        "RegSetValueExA failed\n");
+    ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (PVOID)qw, 8),
+        "RegSetValueExA failed\n");
 }
         
 static void test_enum_value(void)
@@ -255,6 +263,140 @@
     ok(type == REG_SZ, "type %ld is not REG_SZ\n", type);
 }
 
+static void test_get_value(void)
+{
+    HMODULE hadvapi32;
+    DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
+    
+    DWORD ret;
+    DWORD size;
+    DWORD type;
+    DWORD dw, qw[2];
+    CHAR buf[80];
+    CHAR expanded[] = "bar\\subdir1";
+   
+    /* This function was introduced with Windows 2003 SP1 */
+    hadvapi32 = LoadLibraryA("advapi32.dll");
+    if(!hadvapi32) 
+    {
+        ok(0, "error=%ld\n", GetLastError());
+        return;
+    }
+    pRegGetValueA = (PVOID)GetProcAddress(hadvapi32, "RegGetValueA");
+    if(!pRegGetValueA) 
+        return;
+    
+    /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */
+    size = type = dw = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == 4, "size=%ld\n", size);
+    ok(type == REG_DWORD, "type=%ld\n", type);
+    ok(dw == 0x12345678, "dw=%ld\n", dw);
+
+    /* Query by subkey-name */
+    ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+
+    /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */
+    size = type = dw = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size);
+    ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
+    /* Although the function failed all values are retrieved */
+    ok(size == 4, "size=%ld\n", size);
+    ok(type == REG_DWORD, "type=%ld\n", type);
+    ok(dw == 0x12345678, "dw=%ld\n", dw);
+
+    /* Test RRF_ZEROONFAILURE */
+    type = dw = 0xdeadbeef; size = 4;
+    ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size);
+    ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
+    /* Again all values are retrieved ... */
+    ok(size == 4, "size=%ld\n", size);
+    ok(type == REG_DWORD, "type=%ld\n", type);
+    /* ... except the buffer, which is zeroed out */
+    ok(dw == 0, "dw=%ld\n", dw);
+
+    /* Query REG_DWORD using RRF_RT_DWORD (ok) */
+    size = type = dw = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == 4, "size=%ld\n", size);
+    ok(type == REG_DWORD, "type=%ld\n", type);
+    ok(dw == 0x12345678, "dw=%ld\n", dw);
+
+    /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */
+    size = type = dw = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == 4, "size=%ld\n", size);
+    ok(type == REG_BINARY, "type=%ld\n", type);
+    ok(dw == 0x12345678, "dw=%ld\n", dw);
+    
+    /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */
+    qw[0] = qw[1] = size = type = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size);
+    ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%ld\n", ret);
+    ok(size == 8, "size=%ld\n", size);
+    ok(type == REG_BINARY, "type=%ld\n", type);
+    ok(qw[0] == 0x12345678 && 
+       qw[1] == 0x87654321, "qw={%ld,%ld}\n", qw[0], qw[1]);
+    
+    /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */
+    type = dw = 0xdeadbeef; size = 4;
+    ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size);
+    ok(ret == ERROR_MORE_DATA, "ret=%ld\n", ret);
+    ok(dw == 0xdeadbeef, "dw=%ld\n", dw);
+    ok(size == 8, "size=%ld\n", size);
+
+    /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */
+    qw[0] = qw[1] = size = type = 0xdeadbeef;
+    ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == 8, "size=%ld\n", size);
+    ok(type == REG_BINARY, "type=%ld\n", type);
+    ok(qw[0] == 0x12345678 &&
+       qw[1] == 0x87654321, "qw={%ld,%ld}\n", qw[0], qw[1]);
+
+    /* This silly behaviour is not documented but since expanding REG_EXPAND_SZ
+     * values is one the two major features (with type restrictions being the
+     * other one) of this function and it doesn't work as one might expect we
+     * better test it... */
+
+    /* RRF_RT_REG_EXPAND_SZ without RRF_NOEXPAND is not allowed */
+    ret = pRegGetValueA(hkey_main, NULL, "Test1", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL);
+    ok(ret == ERROR_INVALID_PARAMETER, "ret=%ld\n", ret);
+    /* Instead you have to use RRF_RT_REG_SZ to expand a REG_EXPAND_SZ */
+    buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+    ret = pRegGetValueA(hkey_main, NULL, "Test1", RRF_RT_REG_SZ, &type, buf, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+#if 0
+    /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded length + 1 here. */
+    ok(size == strlen(expanded)+1, "strlen(expanded)=%ld size=%ld\n", strlen(expanded), size);
+#endif
+    ok(type == REG_SZ, "type=%ld\n", type);
+    ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf);
+
+    /* Query REG_SZ using RRF_RT_REG_SZ (should not expand it) */
+    buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+    ret = pRegGetValueA(hkey_main, NULL, "Test2", RRF_RT_REG_SZ, &type, buf, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%ld\n", strlen(sTestpath1), size);
+    ok(type == REG_SZ, "type=%ld\n", type);
+    ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
+
+    /* With RRF_RT_REG_SZ however, RRF_NOEXPAND is not allowed */
+    ret = pRegGetValueA(hkey_main, NULL, "Test1", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL);
+    ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%ld\n", ret);
+    /* So we use RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND to get the unexpanded REG_EXPAND_SZ */
+    buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf);
+    ret = pRegGetValueA(hkey_main, NULL, "Test1", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size);
+    ok(ret == ERROR_SUCCESS, "ret=%ld\n", ret);
+    ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%ld\n", strlen(sTestpath1), size);
+    ok(type == REG_EXPAND_SZ, "type=%ld\n", type);
+    ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf);
+} 
+
 static void test_reg_open_key(void)
 {
     DWORD ret = 0;
@@ -450,6 +592,7 @@
     create_test_entries();
     test_enum_value();
     test_query_value_ex();
+    test_get_value();
     test_reg_open_key();
     test_reg_create_key();
     test_reg_close_key();


More information about the wine-patches mailing list