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…
==============================================================================
--- 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@32
RegFlushKey@4
RegGetKeySecurity@16
+RegGetValueA@28
+RegGetValueW@28
RegLoadKeyA@12
RegLoadKeyW@12
RegLoadMUIStringA@24
Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL:
http://svn.reactos.ru/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg.…
==============================================================================
--- 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