mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
- 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. svn path=/trunk/; revision=36623
This commit is contained in:
parent
fa71aedefe
commit
629de52bc2
1 changed files with 130 additions and 198 deletions
|
@ -1809,8 +1809,8 @@ RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
|
|||
/******************************************************************************
|
||||
* 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 @@ RegpApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
|
|||
* 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.
|
||||
* An exception is the case where RRF_RT_ANY is specified, because then
|
||||
* RRF_NOEXPAND is allowed.
|
||||
*/
|
||||
LONG WINAPI
|
||||
RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
|
||||
DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
|
||||
LPDWORD pcbData )
|
||||
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 @@ RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
|
|||
|
||||
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 @@ RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
|
|||
* 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 @@ RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
|
|||
*
|
||||
* 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 @@ RegGetValueA( HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue,
|
|||
|
||||
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 @@ RegQueryReflectionKey(IN HKEY hBase,
|
|||
*
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegQueryValueExW (HKEY hKey,
|
||||
LPCWSTR lpValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData)
|
||||
LONG
|
||||
WINAPI
|
||||
RegQueryValueExW(HKEY hkeyorg,
|
||||
LPCWSTR name,
|
||||
LPDWORD reserved,
|
||||
LPDWORD type,
|
||||
LPBYTE data,
|
||||
LPDWORD count)
|
||||
{
|
||||
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;
|
||||
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("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
|
||||
hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
|
||||
TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
|
||||
hkey, debugstr_w(name), reserved, type, data, count,
|
||||
(count && data) ? *count : 0 );
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
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);
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
if (lpData != NULL && lpcbData == NULL)
|
||||
RtlInitUnicodeString( &name_str, name );
|
||||
|
||||
if (data) total_size = min( sizeof(buffer), *count + info_size );
|
||||
else
|
||||
{
|
||||
ErrorCode = ERROR_INVALID_PARAMETER;
|
||||
goto Cleanup;
|
||||
total_size = info_size;
|
||||
if (count) *count = 0;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString (&ValueName,
|
||||
lpValueName);
|
||||
BufferSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MaxCopy;
|
||||
ValueInfo = RtlAllocateHeap (ProcessHeap,
|
||||
0,
|
||||
BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
|
||||
buffer, total_size, &total_size );
|
||||
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
|
||||
if (data)
|
||||
{
|
||||
ErrorCode = ERROR_OUTOFMEMORY;
|
||||
goto Cleanup;
|
||||
/* 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;
|
||||
|
||||
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 (type) *type = info->Type;
|
||||
if (count) *count = total_size - info_size;
|
||||
|
||||
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;
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
ClosePredefKey(hkey);
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3955,6 +3918,9 @@ RegQueryValueExA (HKEY hKey,
|
|||
ValueData.Buffer = NULL;
|
||||
ValueData.Length = 0;
|
||||
ValueData.MaximumLength = 0;
|
||||
|
||||
if (lpcbData)
|
||||
*lpcbData = 0;
|
||||
}
|
||||
|
||||
RtlCreateUnicodeStringFromAsciiz (&ValueName,
|
||||
|
@ -4754,47 +4720,39 @@ RegSetValueExW (HKEY hKey,
|
|||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegSetValueA (HKEY hKey,
|
||||
RegSetValueA (HKEY hKeyOriginal,
|
||||
LPCSTR lpSubKey,
|
||||
DWORD dwType,
|
||||
LPCSTR lpData,
|
||||
DWORD cbData)
|
||||
{
|
||||
LONG ret;
|
||||
HKEY hSubKey;
|
||||
HKEY subkey;
|
||||
HANDLE hKey;
|
||||
DWORD ret;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (dwType != REG_SZ)
|
||||
{
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
TRACE("(%p,%s,%d,%s,%d)\n", hKey, debugstr_a(lpSubKey), dwType, debugstr_a(lpData), cbData );
|
||||
|
||||
if (lpSubKey != NULL && lpSubKey[0] != '\0')
|
||||
{
|
||||
ret = RegCreateKeyA(hKey,
|
||||
lpSubKey,
|
||||
&hSubKey);
|
||||
if (dwType != REG_SZ || !lpData) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (ret != ERROR_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
hSubKey = hKey;
|
||||
Status = MapDefaultKey(&hKey, hKeyOriginal);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return RtlNtStatusToDosError (Status);
|
||||
}
|
||||
subkey = hKey;
|
||||
|
||||
ret = RegSetValueExA(hSubKey,
|
||||
NULL,
|
||||
0,
|
||||
REG_SZ,
|
||||
(CONST BYTE*)lpData,
|
||||
strlen(lpData) + 1);
|
||||
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 );
|
||||
|
||||
if (hSubKey != hKey)
|
||||
{
|
||||
RegCloseKey(hSubKey);
|
||||
}
|
||||
Cleanup:
|
||||
ClosePredefKey(hKey);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4804,67 +4762,41 @@ RegSetValueA (HKEY hKey,
|
|||
* @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;
|
||||
HKEY subkey;
|
||||
HANDLE hKey;
|
||||
DWORD ret;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(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);
|
||||
return RtlNtStatusToDosError (Status);
|
||||
}
|
||||
subkey = hKey;
|
||||
|
||||
if (lpSubKey && lpSubKey[0]) /* need to create the subkey */
|
||||
{
|
||||
if ((ret = RegCreateKeyW( hKey, lpSubKey, &subkey )) != ERROR_SUCCESS) goto Cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)lpData,
|
||||
(wcslen( lpData ) + 1) * sizeof(WCHAR) );
|
||||
if (subkey != hKey) RegCloseKey( subkey );
|
||||
|
||||
Cleanup:
|
||||
ClosePredefKey(KeyHandle);
|
||||
ClosePredefKey(hKey);
|
||||
|
||||
return ErrorCode;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue