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; }