Author: fireball
Date: Thu Oct 2 06:30:44 2008
New Revision: 36623
URL:
http://svn.reactos.org/svn/reactos?rev=36623&view=rev
Log:
- Sync RegGetValueA/W implementation (no functional changes though, mostly comments).
- Port RegQueryValueExW from Wine (but leaving RegQueryValueExA as a wrapper, with a
fix).
- Implement RegSetValueA/W based on Wine's implementation, and removing old, different
(A and W) versions of RegSetValue.
Modified:
trunk/reactos/dll/win32/advapi32/reg/reg.c
Modified: trunk/reactos/dll/win32/advapi32/reg/reg.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/reg/reg…
==============================================================================
--- trunk/reactos/dll/win32/advapi32/reg/reg.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/advapi32/reg/reg.c [iso-8859-1] Thu Oct 2 06:30:44 2008
@@ -1809,8 +1809,8 @@
/******************************************************************************
* 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.
+ * Retrieves the type and data for a value name associated with a key,
+ * optionally expanding its content and restricting its type.
*
* PARAMS
* hKey [I] Handle to an open key.
@@ -1819,23 +1819,25 @@
* 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.
+ * pcbData [I/O] Size of pvData, updated with the size in bytes required to
+ * retrieve the whole content, including the trailing '\0'
+ * for strings.
*
* 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
+ * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
+ * expanded and pdwType is set to REG_SZ 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 )
+ * An exception is the case where RRF_RT_ANY is specified, because then
+ * RRF_NOEXPAND is allowed.
+ */
+LSTATUS 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;
@@ -1847,7 +1849,6 @@
if (pvData && !pcbData)
return ERROR_INVALID_PARAMETER;
-
if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND)
&&
((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
return ERROR_INVALID_PARAMETER;
@@ -1864,7 +1865,7 @@
* 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)))
+ dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND))
{
do {
HeapFree(GetProcessHeap(), 0, pvBuf);
@@ -1930,10 +1931,9 @@
*
* See RegGetValueW.
*/
-LONG WINAPI
-RegGetValueA( HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue,
- DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
- LPDWORD pcbData )
+LSTATUS 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;
@@ -1945,7 +1945,6 @@
if (pvData && !pcbData)
return ERROR_INVALID_PARAMETER;
-
if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND)
&&
((dwFlags & RRF_RT_ANY) != RRF_RT_ANY))
return ERROR_INVALID_PARAMETER;
@@ -3793,120 +3792,84 @@
*
* @implemented
*/
-LONG STDCALL
-RegQueryValueExW (HKEY hKey,
- LPCWSTR lpValueName,
- LPDWORD lpReserved,
- LPDWORD lpType,
- LPBYTE lpData,
- LPDWORD lpcbData)
-{
- PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- ULONG BufferSize;
- ULONG ResultSize;
- HANDLE KeyHandle;
- LONG ErrorCode = ERROR_SUCCESS;
- ULONG MaxCopy = lpcbData != NULL && lpData != NULL ? *lpcbData : 0;
-
- TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
- hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
-
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- return RtlNtStatusToDosError (Status);
- }
-
- if (lpData != NULL && lpcbData == NULL)
- {
- ErrorCode = ERROR_INVALID_PARAMETER;
- goto Cleanup;
- }
-
- RtlInitUnicodeString (&ValueName,
- lpValueName);
- BufferSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MaxCopy;
- ValueInfo = RtlAllocateHeap (ProcessHeap,
- 0,
- BufferSize);
- if (ValueInfo == NULL)
- {
- ErrorCode = ERROR_OUTOFMEMORY;
- goto Cleanup;
- }
-
- Status = NtQueryValueKey (KeyHandle,
- &ValueName,
- KeyValuePartialInformation,
- ValueInfo,
- BufferSize,
- &ResultSize);
- TRACE("Status 0x%X\n", Status);
- if (Status == STATUS_BUFFER_OVERFLOW)
- {
- /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
- MaxCopy = 0;
- ErrorCode = lpData ? ERROR_MORE_DATA : ERROR_SUCCESS;
- }
- else if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- MaxCopy = 0;
- if (lpcbData != NULL)
- {
- ResultSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + *lpcbData;
- }
- }
-
- if ((lpType != NULL) && (NT_SUCCESS(Status) || (Status ==
STATUS_BUFFER_OVERFLOW)))
- {
- *lpType = ValueInfo->Type;
- }
-
- if (NT_SUCCESS(Status) && lpData != NULL)
- {
- RtlMoveMemory (lpData,
- ValueInfo->Data,
- min(ValueInfo->DataLength, MaxCopy));
- }
-
- if ((ValueInfo->Type == REG_SZ) ||
- (ValueInfo->Type == REG_MULTI_SZ) ||
- (ValueInfo->Type == REG_EXPAND_SZ))
- {
- if (lpData != NULL && MaxCopy > ValueInfo->DataLength)
- {
- ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
- }
-
- if (lpcbData != NULL)
- {
- *lpcbData = (ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]));
- TRACE("(string) Returning Size: %lu\n", *lpcbData);
- }
- }
- else
- {
- if (lpcbData != NULL)
- {
- *lpcbData = ResultSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
- TRACE("(other) Returning Size: %lu\n", *lpcbData);
- }
- }
-
- TRACE("Type %d Size %d\n", ValueInfo->Type, ValueInfo->DataLength);
-
- RtlFreeHeap (ProcessHeap,
- 0,
- ValueInfo);
-
-Cleanup:
- ClosePredefKey(KeyHandle);
-
- return ErrorCode;
+LONG
+WINAPI
+RegQueryValueExW(HKEY hkeyorg,
+ LPCWSTR name,
+ LPDWORD reserved,
+ LPDWORD type,
+ LPBYTE data,
+ LPDWORD count)
+{
+ HANDLE hkey;
+ NTSTATUS status;
+ UNICODE_STRING name_str;
+ DWORD total_size;
+ char buffer[256], *buf_ptr = buffer;
+ KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
+ static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
+
+ TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
+ hkey, debugstr_w(name), reserved, type, data, count,
+ (count && data) ? *count : 0 );
+
+ if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+ //if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
+
+ status = MapDefaultKey(&hkey, hkeyorg);
+ if (!NT_SUCCESS(status))
+ {
+ return RtlNtStatusToDosError(status);
+ }
+
+ RtlInitUnicodeString( &name_str, name );
+
+ if (data) total_size = min( sizeof(buffer), *count + info_size );
+ else
+ {
+ total_size = info_size;
+ if (count) *count = 0;
+ }
+
+ status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
+ buffer, total_size, &total_size );
+ if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
+
+ if (data)
+ {
+ /* retry with a dynamically allocated buffer */
+ while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <=
*count)
+ {
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+ return ERROR_NOT_ENOUGH_MEMORY;
+ info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+ status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
+ buf_ptr, total_size, &total_size );
+ }
+
+ if (!status)
+ {
+ memcpy( data, buf_ptr + info_size, total_size - info_size );
+ /* if the type is REG_SZ and data is not 0-terminated
+ * and there is enough space in the buffer NT appends a \0 */
+ if (total_size - info_size <= *count-sizeof(WCHAR) &&
is_string(info->Type))
+ {
+ WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
+ if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
+ }
+ }
+ else if (status != STATUS_BUFFER_OVERFLOW) goto done;
+ }
+ else status = STATUS_SUCCESS;
+
+ if (type) *type = info->Type;
+ if (count) *count = total_size - info_size;
+
+ done:
+ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+ ClosePredefKey(hkey);
+ return RtlNtStatusToDosError(status);
}
@@ -3955,6 +3918,9 @@
ValueData.Buffer = NULL;
ValueData.Length = 0;
ValueData.MaximumLength = 0;
+
+ if (lpcbData)
+ *lpcbData = 0;
}
RtlCreateUnicodeStringFromAsciiz (&ValueName,
@@ -4754,47 +4720,39 @@
* @implemented
*/
LONG STDCALL
-RegSetValueA (HKEY hKey,
+RegSetValueA (HKEY hKeyOriginal,
LPCSTR lpSubKey,
DWORD dwType,
LPCSTR lpData,
DWORD cbData)
{
- LONG ret;
- HKEY hSubKey;
-
- if (dwType != REG_SZ)
- {
- return ERROR_INVALID_PARAMETER;
- }
-
- if (lpSubKey != NULL && lpSubKey[0] != '\0')
- {
- ret = RegCreateKeyA(hKey,
- lpSubKey,
- &hSubKey);
-
- if (ret != ERROR_SUCCESS)
- {
- return ret;
- }
- }
- else
- hSubKey = hKey;
-
- ret = RegSetValueExA(hSubKey,
- NULL,
- 0,
- REG_SZ,
- (CONST BYTE*)lpData,
- strlen(lpData) + 1);
-
- if (hSubKey != hKey)
- {
- RegCloseKey(hSubKey);
- }
-
- return ret;
+ HKEY subkey;
+ HANDLE hKey;
+ DWORD ret;
+ NTSTATUS Status;
+
+ TRACE("(%p,%s,%d,%s,%d)\n", hKey, debugstr_a(lpSubKey), dwType,
debugstr_a(lpData), cbData );
+
+ if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
+
+ Status = MapDefaultKey(&hKey, hKeyOriginal);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ subkey = hKey;
+
+ if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
+ {
+ if ((ret = RegCreateKeyA( hKey, lpSubKey, &subkey )) != ERROR_SUCCESS) goto
Cleanup;
+ }
+ ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData, strlen(lpData)+1
);
+ if (subkey != hKey) RegCloseKey( subkey );
+
+Cleanup:
+ ClosePredefKey(hKey);
+
+ return ret;
}
@@ -4804,67 +4762,41 @@
* @implemented
*/
LONG STDCALL
-RegSetValueW (HKEY hKey,
+RegSetValueW (HKEY hKeyOriginal,
LPCWSTR lpSubKey,
DWORD dwType,
LPCWSTR lpData,
DWORD cbData)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING SubKeyString;
- HANDLE KeyHandle;
- HANDLE RealKey;
- BOOL CloseRealKey;
- NTSTATUS Status;
- LONG ErrorCode;
-
- Status = MapDefaultKey (&KeyHandle,
- hKey);
- if (!NT_SUCCESS(Status))
- {
- return RtlNtStatusToDosError (Status);
- }
-
- if ((lpSubKey) && (wcslen(lpSubKey) != 0))
- {
- RtlInitUnicodeString (&SubKeyString,
- (LPWSTR)lpSubKey);
- InitializeObjectAttributes (&ObjectAttributes,
- &SubKeyString,
- OBJ_CASE_INSENSITIVE,
- KeyHandle,
- NULL);
- Status = NtOpenKey (&RealKey,
- KEY_SET_VALUE,
- &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- ErrorCode = RtlNtStatusToDosError (Status);
- goto Cleanup;
- }
- CloseRealKey = TRUE;
- }
- else
- {
- RealKey = hKey;
- CloseRealKey = FALSE;
- }
-
- ErrorCode = RegSetValueExW (RealKey,
- NULL,
- 0,
- dwType,
- (LPBYTE)lpData,
- cbData);
- if (CloseRealKey == TRUE)
- {
- NtClose (RealKey);
- }
+ HKEY subkey;
+ HANDLE hKey;
+ DWORD ret;
+ NTSTATUS Status;
+
+ TRACE("(%p,%s,%d,%s,%d)\n", hKeyOriginal, debugstr_w(lpSubKey), dwType,
debugstr_w(lpData), cbData );
+
+ if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
+
+ Status = MapDefaultKey(&hKey, hKeyOriginal);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError (Status);
+ }
+ subkey = hKey;
+
+ if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
+ {
+ if ((ret = RegCreateKeyW( hKey, lpSubKey, &subkey )) != ERROR_SUCCESS) goto
Cleanup;
+ }
+
+ ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
+ (wcslen( lpData ) + 1) * sizeof(WCHAR) );
+ if (subkey != hKey) RegCloseKey( subkey );
Cleanup:
- ClosePredefKey(KeyHandle);
-
- return ErrorCode;
+ ClosePredefKey(hKey);
+
+ return ret;
}