[ros-diffs] [gedmurphy] 22491: Port RegGetValue() from WINE patch by Thomas Weidenmueller

gedmurphy at svn.reactos.org gedmurphy at svn.reactos.org
Wed Jun 21 23:19:48 CEST 2006


Author: gedmurphy
Date: Thu Jun 22 01:19:47 2006
New Revision: 22491

URL: http://svn.reactos.ru/svn/reactos?rev=22491&view=rev
Log:
Port RegGetValue() from WINE
patch by Thomas Weidenmueller


Modified:
    trunk/reactos/dll/win32/advapi32/advapi32.def
    trunk/reactos/dll/win32/advapi32/reg/reg.c

Modified: trunk/reactos/dll/win32/advapi32/advapi32.def
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/advapi32/advapi32.def?rev=22491&r1=22490&r2=22491&view=diff
==============================================================================
--- trunk/reactos/dll/win32/advapi32/advapi32.def (original)
+++ trunk/reactos/dll/win32/advapi32/advapi32.def Thu Jun 22 01:19:47 2006
@@ -494,6 +494,8 @@
 RegEnumValueW at 32
 RegFlushKey at 4
 RegGetKeySecurity at 16
+RegGetValueA at 28
+RegGetValueW at 28
 RegLoadKeyA at 12
 RegLoadKeyW at 12
 RegLoadMUIStringA at 24

Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL: http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg.c?rev=22491&r1=22490&r2=22491&view=diff
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/reg.c (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.c Thu Jun 22 01:19:47 2006
@@ -1680,6 +1680,258 @@
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
+/******************************************************************************
+ * RegpApplyRestrictions   [internal]
+ *
+ * Helper function for RegGetValueA/W.
+ */
+static VOID
+RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
+                       PLONG ret )
+{
+    /* Check if the type is restricted by the passed flags */
+    if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
+    {
+        DWORD dwMask = 0;
+
+        switch (dwType)
+        {
+        case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
+        case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
+        case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
+        case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
+        case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
+        case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
+        case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
+        }
+
+        if (dwFlags & dwMask)
+        {
+            /* Type is not restricted, check for size mismatch */
+            if (dwType == REG_BINARY)
+            {
+                DWORD cbExpect = 0;
+
+                if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
+                    cbExpect = 4;
+                else if ((dwFlags & RRF_RT_DWORD) == RRF_RT_QWORD)
+                    cbExpect = 8;
+
+                if (cbExpect && cbData != cbExpect)
+                    *ret = ERROR_DATATYPE_MISMATCH;
+            }
+        }
+        else *ret = ERROR_UNSUPPORTED_TYPE;
+    }
+}
+
+
+/******************************************************************************
+ * RegGetValueW   [ADVAPI32.@]
+ *
+ * Retrieves the type and data for a value name associated with a key 
+ * optionally expanding it's content and restricting it's type.
+ *
+ * PARAMS
+ *  hKey      [I] Handle to an open key.
+ *  pszSubKey [I] Name of the subkey of hKey.
+ *  pszValue  [I] Name of value under hKey/szSubKey to query.
+ *  dwFlags   [I] Flags restricting the value type to retrieve.
+ *  pdwType   [O] Destination for the values type, may be NULL.
+ *  pvData    [O] Destination for the values content, may be NULL.
+ *  pcbData   [I/O] Size of pvData, updated with the size required to 
+ *                  retrieve the whole content.
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: nonzero error code from Winerror.h
+ *
+ * NOTES
+ *  - Unless RRF_NOEXPAND is specified REG_EXPAND_SZ is automatically expanded
+ *    and REG_SZ is retrieved instead.
+ *  - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ 
+ *    without RRF_NOEXPAND is thus not allowed.
+ */
+LONG WINAPI
+RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, 
+              DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
+              LPDWORD pcbData )
+{
+    DWORD dwType, cbData = pcbData ? *pcbData : 0;
+    PVOID pvBuf = NULL;
+    LONG ret;
+
+    TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n", 
+          hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
+          pvData, pcbData, cbData);
+
+    if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
+        return ERROR_INVALID_PARAMETER;
+
+    if (pszSubKey && pszSubKey[0])
+    {
+        ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
+        if (ret != ERROR_SUCCESS) return ret;
+    }
+
+    ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
+    
+    /* If we are going to expand we need to read in the whole the value even
+     * if the passed buffer was too small as the expanded string might be
+     * smaller than the unexpanded one and could fit into cbData bytes. */
+    if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
+        (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
+    {
+        do {
+            if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
+            
+            pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
+            if (!pvBuf)
+            {
+                ret = ERROR_NOT_ENOUGH_MEMORY;
+                break;
+            }
+
+            if (ret == ERROR_MORE_DATA)
+                ret = RegQueryValueExW(hKey, pszValue, NULL, 
+                                       &dwType, pvBuf, &cbData);
+            else
+            {
+                /* Even if cbData was large enough we have to copy the 
+                 * string since ExpandEnvironmentStrings can't handle
+                 * overlapping buffers. */
+                CopyMemory(pvBuf, pvData, cbData);
+            }
+
+            /* Both the type or the value itself could have been modified in
+             * between so we have to keep retrying until the buffer is large
+             * enough or we no longer have to expand the value. */
+        } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
+
+        if (ret == ERROR_SUCCESS)
+        {
+            if (dwType == REG_EXPAND_SZ)
+            {
+                cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
+                                                   pcbData ? *pcbData : 0);
+                dwType = REG_SZ;
+                if(pcbData && cbData > *pcbData)
+                    ret = ERROR_MORE_DATA;
+            }
+            else if (pcbData)
+                CopyMemory(pvData, pvBuf, *pcbData);
+        }
+
+        if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
+    }
+
+    if (pszSubKey && pszSubKey[0])
+        RegCloseKey(hKey);
+
+    RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
+
+    if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
+        ZeroMemory(pvData, *pcbData);
+
+    if (pdwType) *pdwType = dwType;
+    if (pcbData) *pcbData = cbData;
+
+    return ret;
+}
+
+
+/******************************************************************************
+ * RegGetValueA   [ADVAPI32.@]
+ *
+ * See RegGetValueW.
+ */
+LONG WINAPI
+RegGetValueA( HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue, 
+              DWORD dwFlags, LPDWORD pdwType, PVOID pvData, 
+              LPDWORD pcbData )
+{
+    DWORD dwType, cbData = pcbData ? *pcbData : 0;
+    PVOID pvBuf = NULL;
+    LONG ret;
+
+    TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n", 
+          hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
+          cbData);
+
+    if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
+        return ERROR_INVALID_PARAMETER;
+
+    if (pszSubKey && pszSubKey[0])
+    {
+        ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
+        if (ret != ERROR_SUCCESS) return ret;
+    }
+
+    ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
+
+    /* If we are going to expand we need to read in the whole the value even
+     * if the passed buffer was too small as the expanded string might be
+     * smaller than the unexpanded one and could fit into cbData bytes. */
+    if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
+        (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
+    {
+        do {
+            if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
+
+            pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
+            if (!pvBuf)
+            {
+                ret = ERROR_NOT_ENOUGH_MEMORY;
+                break;
+            }
+
+            if (ret == ERROR_MORE_DATA)
+                ret = RegQueryValueExA(hKey, pszValue, NULL, 
+                                       &dwType, pvBuf, &cbData);
+            else
+            {
+                /* Even if cbData was large enough we have to copy the 
+                 * string since ExpandEnvironmentStrings can't handle
+                 * overlapping buffers. */
+                CopyMemory(pvBuf, pvData, cbData);
+            }
+
+            /* Both the type or the value itself could have been modified in
+             * between so we have to keep retrying until the buffer is large
+             * enough or we no longer have to expand the value. */
+        } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
+
+        if (ret == ERROR_SUCCESS)
+        {
+            if (dwType == REG_EXPAND_SZ)
+            {
+                cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
+                                                   pcbData ? *pcbData : 0);
+                dwType = REG_SZ;
+                if(pcbData && cbData > *pcbData)
+                    ret = ERROR_MORE_DATA;
+            }
+            else if (pcbData)
+                CopyMemory(pvData, pvBuf, *pcbData);
+        }
+
+        if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
+    }
+
+    if (pszSubKey && pszSubKey[0])
+        RegCloseKey(hKey);
+
+    RegpApplyRestrictions(dwFlags, dwType, cbData, &ret);
+
+    if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
+        ZeroMemory(pvData, *pcbData);
+
+    if (pdwType) *pdwType = dwType;
+    if (pcbData) *pcbData = cbData;
+
+    return ret;
+}
+
 
 /************************************************************************
  *  RegSetKeyValueW




More information about the Ros-diffs mailing list