mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
RegOpenKey, RegOpenKeyEx A/W imported and ported from WINE. This keeps the current test set in advapi32_test registry on 85/0 level
svn path=/trunk/; revision=14969
This commit is contained in:
parent
8460c6e770
commit
d534342503
1 changed files with 266 additions and 512 deletions
|
@ -8,6 +8,7 @@
|
|||
* UPDATE HISTORY:
|
||||
* Created 01/11/98
|
||||
* 19990309 EA Stubs
|
||||
* 20050502 Fireball imported some stuff from WINE
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -22,6 +23,9 @@
|
|||
#define REG_MAX_NAME_SIZE 256
|
||||
#define REG_MAX_DATA_SIZE 2048
|
||||
|
||||
/* FIXME: should go into msvcrt.h header? */
|
||||
#define offsetof(s,m) (size_t)&(((s*)NULL)->m)
|
||||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
static RTL_CRITICAL_SECTION HandleTableCS;
|
||||
|
@ -40,6 +44,11 @@ static NTSTATUS OpenCurrentConfigKey(PHANDLE KeyHandle);
|
|||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
/* check if value type needs string conversion (Ansi<->Unicode) */
|
||||
inline static int is_string( DWORD type )
|
||||
{
|
||||
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* RegInitDefaultHandles
|
||||
|
@ -1161,417 +1170,226 @@ RegEnumKeyExW (HKEY hKey,
|
|||
return ErrorCode;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* RegEnumValueA
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegEnumValueA (HKEY hKey,
|
||||
DWORD dwIndex,
|
||||
LPSTR lpValueName,
|
||||
LPDWORD lpcbValueName, // lpValueName buffer len
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData) // lpData buffer len
|
||||
RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
|
||||
LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
|
||||
{
|
||||
union
|
||||
{
|
||||
KEY_VALUE_FULL_INFORMATION Full;
|
||||
KEY_VALUE_BASIC_INFORMATION Basic;
|
||||
} *ValueInfo;
|
||||
|
||||
ULONG NameLength;
|
||||
ULONG BufferSize;
|
||||
ULONG DataLength = 0;
|
||||
ULONG ResultSize;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING StringU;
|
||||
ANSI_STRING StringA;
|
||||
BOOL IsStringType;
|
||||
NTSTATUS status;
|
||||
DWORD total_size;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
|
||||
static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
|
||||
|
||||
ErrorCode = ERROR_SUCCESS;
|
||||
//TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
|
||||
// hkey, index, value, val_count, reserved, type, data, count );
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* NT only checks count, not val_count */
|
||||
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
|
||||
status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
LONG ErrorCode;
|
||||
ErrorCode = RtlNtStatusToDosError (status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (*lpcbValueName > 0)
|
||||
NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
|
||||
else
|
||||
NameLength = 0;
|
||||
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
|
||||
if (data) total_size += *count;
|
||||
total_size = min( sizeof(buffer), total_size );
|
||||
|
||||
if (lpData)
|
||||
{
|
||||
DataLength = min (*lpcbData * sizeof(WCHAR), REG_MAX_DATA_SIZE);
|
||||
BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
|
||||
}
|
||||
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
|
||||
buffer, total_size, &total_size );
|
||||
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
|
||||
ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
/* we need to fetch the contents for a string type even if not requested,
|
||||
* because we need to compute the length of the ASCII string. */
|
||||
if (value || data || is_string(info->Type))
|
||||
{
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
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_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
Status = NtEnumerateValueKey (KeyHandle,
|
||||
(ULONG)dwIndex,
|
||||
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (status) goto done;
|
||||
|
||||
DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
if (is_string(info->Type))
|
||||
{
|
||||
DWORD len;
|
||||
RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
|
||||
total_size - info->DataOffset );
|
||||
if (data && len)
|
||||
{
|
||||
if (len > *count) status = STATUS_BUFFER_OVERFLOW;
|
||||
else
|
||||
{
|
||||
RtlUnicodeToMultiByteN( data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
|
||||
total_size - info->DataOffset );
|
||||
/* 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 (len < *count && data[len-1]) data[len] = 0;
|
||||
}
|
||||
}
|
||||
info->DataLength = len;
|
||||
}
|
||||
else if (data)
|
||||
{
|
||||
if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
|
||||
else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
|
||||
}
|
||||
|
||||
// handle case when BufferSize was too small
|
||||
// we must let caller know the minimum accepted size
|
||||
// and value type
|
||||
if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
if (value && !status)
|
||||
{
|
||||
DWORD len;
|
||||
|
||||
// query now with the sufficient buffer size
|
||||
RtlFreeHeap (ProcessHeap, 0, ValueInfo);
|
||||
BufferSize = ResultSize;
|
||||
ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize); // will be freed at the bottom, as usual
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
|
||||
if (len >= *val_count)
|
||||
{
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
if (*val_count)
|
||||
{
|
||||
len = *val_count - 1;
|
||||
RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
|
||||
value[len] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
|
||||
value[len] = 0;
|
||||
*val_count = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
else status = STATUS_SUCCESS;
|
||||
|
||||
Status = NtEnumerateValueKey (KeyHandle,
|
||||
(ULONG)dwIndex,
|
||||
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// ok, some other error
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have information now, pass it to the caller
|
||||
// but don't touch valueName length here
|
||||
IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
|
||||
(ValueInfo->Full.Type == REG_MULTI_SZ) ||
|
||||
(ValueInfo->Full.Type == REG_EXPAND_SZ); //FIXME: Include REG_LINK ?
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = info->DataLength;
|
||||
|
||||
if (lpData)
|
||||
{
|
||||
if (lpcbData)
|
||||
{
|
||||
if (IsStringType)
|
||||
*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
|
||||
else
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
}
|
||||
}
|
||||
|
||||
// pass type also
|
||||
if (lpType)
|
||||
*lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IsStringType = (ValueInfo->Full.Type == REG_SZ) ||
|
||||
(ValueInfo->Full.Type == REG_MULTI_SZ) ||
|
||||
(ValueInfo->Full.Type == REG_EXPAND_SZ);
|
||||
if (lpData)
|
||||
{
|
||||
if (ValueInfo->Full.NameLength > NameLength ||
|
||||
(!IsStringType && ValueInfo->Full.DataLength > *lpcbData) ||
|
||||
ValueInfo->Full.DataLength > DataLength)
|
||||
{
|
||||
// overflow data
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
|
||||
// return correct information for data length and type
|
||||
if (lpcbData)
|
||||
{
|
||||
if (IsStringType)
|
||||
*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
|
||||
else
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
}
|
||||
|
||||
if (lpType)
|
||||
*lpType = ValueInfo->Full.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsStringType)
|
||||
{
|
||||
StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
|
||||
StringU.Length = ValueInfo->Full.DataLength;
|
||||
StringU.MaximumLength = DataLength;
|
||||
StringA.Buffer = (PCHAR)lpData;
|
||||
StringA.Length = 0;
|
||||
StringA.MaximumLength = *lpcbData;
|
||||
RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
|
||||
*lpcbData = StringA.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory (lpData,
|
||||
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
|
||||
ValueInfo->Full.DataLength);
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
}
|
||||
|
||||
StringU.Buffer = ValueInfo->Full.Name;
|
||||
StringU.Length = ValueInfo->Full.NameLength;
|
||||
StringU.MaximumLength = NameLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ValueInfo->Basic.NameLength > NameLength)
|
||||
{
|
||||
// overflow name
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
|
||||
if (IsStringType)
|
||||
*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
|
||||
else
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
|
||||
if (lpType)
|
||||
*lpType = ValueInfo->Basic.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringU.Buffer = ValueInfo->Basic.Name;
|
||||
StringU.Length = ValueInfo->Basic.NameLength;
|
||||
StringU.MaximumLength = NameLength;
|
||||
}
|
||||
}
|
||||
|
||||
if (ErrorCode == ERROR_SUCCESS)
|
||||
{
|
||||
StringA.Buffer = (PCHAR)lpValueName;
|
||||
StringA.Length = 0;
|
||||
StringA.MaximumLength = *lpcbValueName;
|
||||
RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
|
||||
StringA.Buffer[StringA.Length] = 0;
|
||||
*lpcbValueName = StringA.Length;
|
||||
if (lpType)
|
||||
{
|
||||
*lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RtlFreeHeap (ProcessHeap, 0, ValueInfo);
|
||||
|
||||
if (ErrorCode != ERROR_SUCCESS)
|
||||
SetLastError(ErrorCode);
|
||||
|
||||
return ErrorCode;
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* RegEnumValueW
|
||||
*
|
||||
/******************************************************************************
|
||||
* RegEnumValueW [ADVAPI32.@]
|
||||
* @implemented
|
||||
*
|
||||
* PARAMS
|
||||
* hkey [I] Handle to key to query
|
||||
* index [I] Index of value to query
|
||||
* value [O] Value string
|
||||
* val_count [I/O] Size of value buffer (in wchars)
|
||||
* reserved [I] Reserved
|
||||
* type [O] Type code
|
||||
* data [O] Value data
|
||||
* count [I/O] Size of data buffer (in bytes)
|
||||
*
|
||||
* RETURNS
|
||||
* Success: ERROR_SUCCESS
|
||||
* Failure: nonzero error code from Winerror.h
|
||||
*/
|
||||
LONG STDCALL
|
||||
RegEnumValueW (HKEY hKey,
|
||||
DWORD dwIndex,
|
||||
LPWSTR lpValueName,
|
||||
LPDWORD lpcbValueName,
|
||||
LPDWORD lpReserved,
|
||||
LPDWORD lpType,
|
||||
LPBYTE lpData,
|
||||
LPDWORD lpcbData)
|
||||
RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
|
||||
PDWORD reserved, PDWORD type, LPBYTE data, PDWORD count )
|
||||
{
|
||||
union
|
||||
{
|
||||
KEY_VALUE_FULL_INFORMATION Full;
|
||||
KEY_VALUE_BASIC_INFORMATION Basic;
|
||||
} *ValueInfo;
|
||||
|
||||
ULONG NameLength;
|
||||
ULONG BufferSize;
|
||||
ULONG DataLength = 0;
|
||||
ULONG ResultSize;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
NTSTATUS status;
|
||||
DWORD total_size;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
|
||||
static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
|
||||
|
||||
ErrorCode = ERROR_SUCCESS;
|
||||
//TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
|
||||
// hkey, index, value, val_count, reserved, type, data, count );
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* NT only checks count, not val_count */
|
||||
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
LONG ErrorCode;
|
||||
ErrorCode = RtlNtStatusToDosError (status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
if (*lpcbValueName > 0)
|
||||
NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
|
||||
else
|
||||
NameLength = 0;
|
||||
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
|
||||
if (data) total_size += *count;
|
||||
total_size = min( sizeof(buffer), total_size );
|
||||
|
||||
if (lpData)
|
||||
{
|
||||
DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
|
||||
BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
|
||||
}
|
||||
ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
SetLastError (ERROR_OUTOFMEMORY);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
Status = NtEnumerateValueKey (KeyHandle,
|
||||
(ULONG)dwIndex,
|
||||
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
|
||||
buffer, total_size, &total_size );
|
||||
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
|
||||
DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
if (value || data)
|
||||
{
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
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_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
// handle case when BufferSize was too small
|
||||
// we must let caller know the minimum accepted size
|
||||
// and value type
|
||||
if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
if (status) goto done;
|
||||
|
||||
// query now with the sufficient buffer size
|
||||
RtlFreeHeap (ProcessHeap, 0, ValueInfo);
|
||||
BufferSize = ResultSize;
|
||||
ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize); // will be freed at the bottom, as usual
|
||||
if (ValueInfo == NULL)
|
||||
{
|
||||
SetLastError(ERROR_OUTOFMEMORY);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
if (value)
|
||||
{
|
||||
if (info->NameLength/sizeof(WCHAR) >= *val_count)
|
||||
{
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
goto overflow;
|
||||
}
|
||||
memcpy( value, info->Name, info->NameLength );
|
||||
*val_count = info->NameLength / sizeof(WCHAR);
|
||||
value[*val_count] = 0;
|
||||
}
|
||||
|
||||
Status = NtEnumerateValueKey (KeyHandle,
|
||||
(ULONG)dwIndex,
|
||||
lpData ? KeyValueFullInformation : KeyValueBasicInformation,
|
||||
ValueInfo,
|
||||
BufferSize,
|
||||
&ResultSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
// ok, some other error
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have information now, pass it to the caller
|
||||
// but don't touch valueName length here
|
||||
if (lpData && lpcbData)
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
if (data)
|
||||
{
|
||||
if (total_size - info->DataOffset > *count)
|
||||
{
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
goto overflow;
|
||||
}
|
||||
memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
|
||||
if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
|
||||
{
|
||||
/* if the type is REG_SZ and data is not 0-terminated
|
||||
* and there is enough space in the buffer NT appends a \0 */
|
||||
WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
|
||||
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else status = STATUS_SUCCESS;
|
||||
|
||||
// pass type also
|
||||
if (lpType)
|
||||
*lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lpData)
|
||||
{
|
||||
if (ValueInfo->Full.DataLength > DataLength ||
|
||||
ValueInfo->Full.NameLength > NameLength)
|
||||
{
|
||||
// overflow data
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
overflow:
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = info->DataLength;
|
||||
|
||||
// return correct information for data length and type
|
||||
if (lpcbData)
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
|
||||
if (lpType)
|
||||
*lpType = ValueInfo->Full.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory (lpValueName, ValueInfo->Full.Name, ValueInfo->Full.NameLength);
|
||||
*lpcbValueName = (DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
|
||||
lpValueName[*lpcbValueName] = 0;
|
||||
RtlCopyMemory (lpData,
|
||||
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
|
||||
ValueInfo->Full.DataLength);
|
||||
*lpcbData = (DWORD)ValueInfo->Full.DataLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ValueInfo->Basic.NameLength > NameLength)
|
||||
{
|
||||
// overflow name
|
||||
ErrorCode = ERROR_MORE_DATA;
|
||||
|
||||
if (lpcbData)
|
||||
*lpcbData = ValueInfo->Full.DataLength;
|
||||
|
||||
if (lpType)
|
||||
*lpType = ValueInfo->Basic.Type;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCopyMemory (lpValueName, ValueInfo->Basic.Name, ValueInfo->Basic.NameLength);
|
||||
*lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
|
||||
lpValueName[*lpcbValueName] = 0;
|
||||
}
|
||||
|
||||
if (NULL != lpcbData)
|
||||
{
|
||||
*lpcbData = (DWORD)ValueInfo->Full.DataLength;
|
||||
DPRINT1("BUG: Using ValueInfo as FULL when it is really BASIC\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
|
||||
{
|
||||
*lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
|
||||
}
|
||||
}
|
||||
|
||||
RtlFreeHeap (ProcessHeap, 0, ValueInfo);
|
||||
|
||||
if (ErrorCode != ERROR_SUCCESS)
|
||||
SetLastError (ErrorCode);
|
||||
|
||||
return ErrorCode;
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* RegFlushKey
|
||||
*
|
||||
|
@ -1818,6 +1636,8 @@ RegNotifyChangeKeyValue (HKEY hKey,
|
|||
/************************************************************************
|
||||
* RegOpenKeyA
|
||||
*
|
||||
* 20050503 Fireball - imported from WINE
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
LONG STDCALL
|
||||
|
@ -1825,45 +1645,15 @@ RegOpenKeyA (HKEY hKey,
|
|||
LPCSTR lpSubKey,
|
||||
PHKEY phkResult)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
|
||||
|
||||
DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
|
||||
if (!lpSubKey || !*lpSubKey)
|
||||
{
|
||||
*phkResult = hKey;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Check input params
|
||||
if (phkResult == NULL) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
|
||||
(LPSTR)lpSubKey);
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
Status = NtOpenKey ((PHANDLE)phkResult,
|
||||
MAXIMUM_ALLOWED,
|
||||
&ObjectAttributes);
|
||||
RtlFreeUnicodeString (&SubKeyString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return RegOpenKeyExA( hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1872,6 +1662,7 @@ RegOpenKeyA (HKEY hKey,
|
|||
*
|
||||
* 19981101 Ariadne
|
||||
* 19990525 EA
|
||||
* 20050503 Fireball - imported from WINE
|
||||
*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -1880,44 +1671,14 @@ RegOpenKeyW (HKEY hKey,
|
|||
LPCWSTR lpSubKey,
|
||||
PHKEY phkResult)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
|
||||
|
||||
DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
|
||||
|
||||
// Check input params
|
||||
if (phkResult == NULL) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return Status;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString (&SubKeyString,
|
||||
(LPWSTR)lpSubKey);
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
Status = NtOpenKey ((PHANDLE)phkResult,
|
||||
MAXIMUM_ALLOWED,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError(ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
if (!lpSubKey || !*lpSubKey)
|
||||
{
|
||||
*phkResult = hKey;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
return RegOpenKeyExW(hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1933,42 +1694,40 @@ RegOpenKeyExA (HKEY hKey,
|
|||
REGSAM samDesired,
|
||||
PHKEY phkResult)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
|
||||
hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
|
||||
hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||||
|
||||
RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
|
||||
(LPSTR)lpSubKey);
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
Status = NtOpenKey ((PHANDLE)phkResult,
|
||||
samDesired,
|
||||
&ObjectAttributes);
|
||||
RtlFreeUnicodeString (&SubKeyString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
Status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
RtlCreateUnicodeStringFromAsciiz (&SubKeyString, (LPSTR)lpSubKey);
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
|
||||
RtlFreeUnicodeString (&SubKeyString);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1984,49 +1743,44 @@ RegOpenKeyExW (HKEY hKey,
|
|||
REGSAM samDesired,
|
||||
PHKEY phkResult)
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING SubKeyString;
|
||||
HANDLE KeyHandle;
|
||||
LONG ErrorCode;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
|
||||
hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||||
Status = MapDefaultKey (&KeyHandle,
|
||||
hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
|
||||
hKey, lpSubKey, ulOptions, samDesired, phkResult);
|
||||
|
||||
if (lpSubKey != NULL)
|
||||
{
|
||||
RtlInitUnicodeString (&SubKeyString,
|
||||
(LPWSTR)lpSubKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitUnicodeString (&SubKeyString,
|
||||
(LPWSTR)L"");
|
||||
}
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
Status = NtOpenKey ((PHANDLE)phkResult,
|
||||
samDesired,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
Status = MapDefaultKey (&KeyHandle, hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
if (lpSubKey != NULL)
|
||||
RtlInitUnicodeString (&SubKeyString, (LPWSTR)lpSubKey);
|
||||
else
|
||||
RtlInitUnicodeString (&SubKeyString, (LPWSTR)L"");
|
||||
|
||||
InitializeObjectAttributes (&ObjectAttributes,
|
||||
&SubKeyString,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
KeyHandle,
|
||||
NULL);
|
||||
|
||||
Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ErrorCode = RtlNtStatusToDosError (Status);
|
||||
SetLastError (ErrorCode);
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue