Convert NtQueryKey and NtEnumerateKey to the new request mechanism.
Fixed a few bugs.
This commit is contained in:
parent
1871e660fd
commit
454355ece1
|
@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
|
|||
DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
|
||||
LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
|
||||
{
|
||||
DWORD ret, len, cls_len;
|
||||
struct enum_key_request *req = get_req_buffer();
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
|
||||
name_len ? *name_len : -1, reserved, class, class_len, ft );
|
||||
|
||||
if (reserved) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
req->index = index;
|
||||
if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
||||
len = strlenW( req->name ) + 1;
|
||||
cls_len = strlenW( req->class ) + 1;
|
||||
if (len > *name_len) return ERROR_MORE_DATA;
|
||||
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
|
||||
|
||||
memcpy( name, req->name, len * sizeof(WCHAR) );
|
||||
*name_len = len - 1;
|
||||
if (class_len)
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
|
||||
*class_len = cls_len - 1;
|
||||
/* retry with a dynamically allocated buffer */
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_NODE_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = info->NameLength / sizeof(WCHAR);
|
||||
DWORD cls_len = info->ClassLength / sizeof(WCHAR);
|
||||
|
||||
if (ft) *ft = info->LastWriteTime;
|
||||
|
||||
if (len >= *name_len || (class_len && (cls_len >= *class_len)))
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
else
|
||||
{
|
||||
*name_len = len;
|
||||
memcpy( name, info->Name, info->NameLength );
|
||||
name[len] = 0;
|
||||
if (class_len)
|
||||
{
|
||||
*class_len = cls_len;
|
||||
if (class)
|
||||
{
|
||||
memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
|
||||
class[cls_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
|
|||
DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
|
||||
LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
|
||||
{
|
||||
DWORD ret, len, cls_len;
|
||||
struct enum_key_request *req = get_req_buffer();
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
|
||||
name_len ? *name_len : -1, reserved, class, class_len, ft );
|
||||
|
||||
if (reserved) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
req->index = index;
|
||||
if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
||||
len = strlenW( req->name ) + 1;
|
||||
cls_len = strlenW( req->class ) + 1;
|
||||
if (len > *name_len) return ERROR_MORE_DATA;
|
||||
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
|
||||
|
||||
memcpyWtoA( name, req->name, len );
|
||||
*name_len = len - 1;
|
||||
if (class_len)
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class) memcpyWtoA( class, req->class, cls_len );
|
||||
*class_len = cls_len - 1;
|
||||
/* retry with a dynamically allocated buffer */
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_NODE_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
DWORD cls_len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength / sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
|
||||
if (ft) *ft = info->LastWriteTime;
|
||||
|
||||
if (len >= *name_len || (class_len && (cls_len >= *class_len)))
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
else
|
||||
{
|
||||
*name_len = len;
|
||||
WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
|
||||
name, len, NULL, NULL );
|
||||
name[len] = 0;
|
||||
if (class_len)
|
||||
{
|
||||
*class_len = cls_len;
|
||||
if (class)
|
||||
{
|
||||
WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength / sizeof(WCHAR),
|
||||
class, cls_len, NULL, NULL );
|
||||
class[cls_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
|
|||
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
|
||||
LPDWORD security, FILETIME *modif )
|
||||
{
|
||||
DWORD ret;
|
||||
struct query_key_info_request *req = get_req_buffer();
|
||||
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
|
||||
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
|
||||
|
@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
|
|||
if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
|
||||
|
||||
if (class)
|
||||
{
|
||||
if (class_len && (strlenW(req->class) + 1 > *class_len))
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
*class_len = strlenW(req->class);
|
||||
return ERROR_MORE_DATA;
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
|
||||
{
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
|
||||
class[info->ClassLength/sizeof(WCHAR)] = 0;
|
||||
}
|
||||
}
|
||||
strcpyW( class, req->class );
|
||||
}
|
||||
if (class_len) *class_len = strlenW( req->class );
|
||||
if (subkeys) *subkeys = req->subkeys;
|
||||
if (max_subkey) *max_subkey = req->max_subkey;
|
||||
if (max_class) *max_class = req->max_class;
|
||||
if (values) *values = req->values;
|
||||
if (max_value) *max_value = req->max_value;
|
||||
if (max_data) *max_data = req->max_data;
|
||||
if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status || status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
|
||||
if (subkeys) *subkeys = info->SubKeys;
|
||||
if (max_subkey) *max_subkey = info->MaxNameLen;
|
||||
if (max_class) *max_class = info->MaxClassLen;
|
||||
if (values) *values = info->Values;
|
||||
if (max_value) *max_value = info->MaxValueNameLen;
|
||||
if (max_data) *max_data = info->MaxValueDataLen;
|
||||
if (modif) *modif = info->LastWriteTime;
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
|
|||
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
|
||||
LPDWORD security, FILETIME *modif )
|
||||
{
|
||||
DWORD ret;
|
||||
struct query_key_info_request *req = get_req_buffer();
|
||||
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
|
||||
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
|
||||
|
@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
|
|||
if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
|
||||
|
||||
if (class)
|
||||
if (class || class_len)
|
||||
{
|
||||
if (class_len && (strlenW(req->class) + 1 > *class_len))
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
*class_len = strlenW(req->class);
|
||||
return ERROR_MORE_DATA;
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength/sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
if (class_len)
|
||||
{
|
||||
if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
|
||||
*class_len = len;
|
||||
}
|
||||
if (class && !status)
|
||||
{
|
||||
WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength/sizeof(WCHAR),
|
||||
class, len, NULL, NULL );
|
||||
class[len] = 0;
|
||||
}
|
||||
}
|
||||
lstrcpyWtoA( class, req->class );
|
||||
}
|
||||
if (class_len) *class_len = strlenW( req->class );
|
||||
if (subkeys) *subkeys = req->subkeys;
|
||||
if (max_subkey) *max_subkey = req->max_subkey;
|
||||
if (max_class) *max_class = req->max_class;
|
||||
if (values) *values = req->values;
|
||||
if (max_value) *max_value = req->max_value;
|
||||
if (max_data) *max_data = req->max_data;
|
||||
if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status || status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (subkeys) *subkeys = info->SubKeys;
|
||||
if (max_subkey) *max_subkey = info->MaxNameLen;
|
||||
if (max_class) *max_class = info->MaxClassLen;
|
||||
if (values) *values = info->Values;
|
||||
if (max_value) *max_value = info->MaxValueNameLen;
|
||||
if (max_data) *max_data = info->MaxValueDataLen;
|
||||
if (modif) *modif = info->LastWriteTime;
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
NTSTATUS status;
|
||||
UNICODE_STRING name_str;
|
||||
DWORD total_size;
|
||||
char buffer[256];
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||
static const int info_size = sizeof(*info) - sizeof(info->Data);
|
||||
|
||||
|
@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
|
||||
if (data)
|
||||
{
|
||||
char *buf_ptr = buffer;
|
||||
/* 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 )))
|
||||
status = STATUS_NO_MEMORY;
|
||||
else
|
||||
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &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)
|
||||
|
@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
|
||||
}
|
||||
}
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
else if (status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
}
|
||||
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = total_size - info_size;
|
||||
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
ANSI_STRING nameA;
|
||||
UNICODE_STRING nameW;
|
||||
DWORD total_size;
|
||||
char buffer[256];
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||
static const int info_size = sizeof(*info) - sizeof(info->Data);
|
||||
|
||||
|
@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
|
||||
RtlInitAnsiString( &nameA, name );
|
||||
/* FIXME: should use Unicode buffer in TEB */
|
||||
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
|
||||
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
|
||||
return RtlNtStatusToDosError(status);
|
||||
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
* because we need to compute the length of the ASCII string. */
|
||||
if (data || is_string(info->Type))
|
||||
{
|
||||
char *buf_ptr = buffer;
|
||||
/* 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 )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
else
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
goto done;
|
||||
}
|
||||
info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
|
@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
total_size = len + info_size;
|
||||
}
|
||||
else if (data) 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;
|
||||
}
|
||||
}
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
else if (status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
}
|
||||
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = total_size - info_size;
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
|
277
dlls/ntdll/reg.c
277
dlls/ntdll/reg.c
|
@ -167,6 +167,95 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
|
|||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* fill_key_info
|
||||
*
|
||||
* Helper function for NtQueryKey and NtEnumerateKey
|
||||
*/
|
||||
static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
|
||||
DWORD *result_len, const struct enum_key_request *req )
|
||||
{
|
||||
WCHAR *name_ptr = server_data_ptr(req);
|
||||
int name_size = *name_ptr++;
|
||||
WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
|
||||
int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
|
||||
int fixed_size;
|
||||
FILETIME modif;
|
||||
|
||||
RtlSecondsSince1970ToTime( req->modif, &modif );
|
||||
|
||||
switch(info_class)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
{
|
||||
KEY_BASIC_INFORMATION keyinfo;
|
||||
fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.NameLength = name_size;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
class_size = 0;
|
||||
}
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
{
|
||||
KEY_FULL_INFORMATION keyinfo;
|
||||
fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Class);
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = class_size;
|
||||
keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
|
||||
keyinfo.SubKeys = req->subkeys;
|
||||
keyinfo.MaxNameLen = req->max_subkey;
|
||||
keyinfo.MaxClassLen = req->max_class;
|
||||
keyinfo.Values = req->values;
|
||||
keyinfo.MaxValueNameLen = req->max_value;
|
||||
keyinfo.MaxValueDataLen = req->max_data;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
name_size = 0;
|
||||
}
|
||||
break;
|
||||
case KeyNodeInformation:
|
||||
{
|
||||
KEY_NODE_INFORMATION keyinfo;
|
||||
fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
|
||||
keyinfo.LastWriteTime = modif;
|
||||
keyinfo.TitleIndex = 0;
|
||||
keyinfo.ClassLength = class_size;
|
||||
keyinfo.ClassOffset = fixed_size + name_size;
|
||||
if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
|
||||
keyinfo.NameLength = name_size;
|
||||
memcpy( info, &keyinfo, min( length, fixed_size ) );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("Information class not implemented\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*result_len = fixed_size + name_size + class_size;
|
||||
if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
|
||||
length -= fixed_size;
|
||||
|
||||
/* copy the name */
|
||||
if (name_size)
|
||||
{
|
||||
memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
|
||||
if (length < name_size) return STATUS_BUFFER_OVERFLOW;
|
||||
length -= name_size;
|
||||
}
|
||||
|
||||
/* copy the class */
|
||||
if (class_size)
|
||||
{
|
||||
memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
|
||||
if (length < class_size) return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtEnumerateKey [NTDLL]
|
||||
* ZwEnumerateKey
|
||||
|
@ -174,164 +263,52 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
|
|||
* NOTES
|
||||
* the name copied into the buffer is NOT 0-terminated
|
||||
*/
|
||||
NTSTATUS WINAPI NtEnumerateKey(
|
||||
HANDLE KeyHandle,
|
||||
ULONG Index,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
struct enum_key_request *req = get_req_buffer();
|
||||
NTSTATUS ret;
|
||||
NTSTATUS ret;
|
||||
|
||||
TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
|
||||
KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
|
||||
/* -1 means query key, so avoid it here */
|
||||
if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
|
||||
|
||||
req->hkey = KeyHandle;
|
||||
req->index = Index;
|
||||
if ((ret = server_call_noerr(REQ_ENUM_KEY)) != STATUS_SUCCESS) return ret;
|
||||
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
{
|
||||
PKEY_BASIC_INFORMATION kbi = KeyInformation;
|
||||
UINT NameLength = strlenW(req->name) * sizeof(WCHAR);
|
||||
*ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kbi->LastWriteTime);
|
||||
kbi->TitleIndex = 0;
|
||||
kbi->NameLength = NameLength;
|
||||
memcpy (kbi->Name, req->name, NameLength);
|
||||
}
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
{
|
||||
PKEY_FULL_INFORMATION kfi = KeyInformation;
|
||||
kfi->ClassLength = strlenW(req->class) * sizeof(WCHAR);
|
||||
kfi->ClassOffset = (kfi->ClassLength) ?
|
||||
sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
|
||||
*ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kfi->LastWriteTime);
|
||||
kfi->TitleIndex = 0;
|
||||
/* kfi->SubKeys = req->subkeys;
|
||||
kfi->MaxNameLength = req->max_subkey;
|
||||
kfi->MaxClassLength = req->max_class;
|
||||
kfi->Values = req->values;
|
||||
kfi->MaxValueNameLen = req->max_value;
|
||||
kfi->MaxValueDataLen = req->max_data;
|
||||
*/
|
||||
FIXME("incomplete\n");
|
||||
if (kfi->ClassLength) memcpy (kfi->Class, req->class, kfi->ClassLength);
|
||||
}
|
||||
break;
|
||||
case KeyNodeInformation:
|
||||
{
|
||||
PKEY_NODE_INFORMATION kni = KeyInformation;
|
||||
kni->ClassLength = strlenW(req->class) * sizeof(WCHAR);
|
||||
kni->NameLength = strlenW(req->name) * sizeof(WCHAR);
|
||||
kni->ClassOffset = (kni->ClassLength) ?
|
||||
sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
|
||||
|
||||
*ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kni->LastWriteTime);
|
||||
kni->TitleIndex = 0;
|
||||
memcpy (kni->Name, req->name, kni->NameLength);
|
||||
if (kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("KeyInformationClass not implemented\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
TRACE("buf=%lu len=%lu\n", Length, *ResultLength);
|
||||
return ret;
|
||||
SERVER_START_REQ
|
||||
{
|
||||
struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
|
||||
req->hkey = handle;
|
||||
req->index = index;
|
||||
req->full = (info_class == KeyFullInformation);
|
||||
if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
|
||||
{
|
||||
ret = fill_key_info( info_class, info, length, result_len, req );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueryKey [NTDLL]
|
||||
* ZwQueryKey
|
||||
*/
|
||||
NTSTATUS WINAPI NtQueryKey(
|
||||
HANDLE KeyHandle,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength)
|
||||
NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
struct query_key_info_request *req = get_req_buffer();
|
||||
NTSTATUS ret;
|
||||
|
||||
TRACE("(0x%08x,0x%08x,%p,0x%08lx,%p) stub\n",
|
||||
KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
|
||||
|
||||
req->hkey = KeyHandle;
|
||||
if ((ret = server_call_noerr(REQ_QUERY_KEY_INFO)) != STATUS_SUCCESS) return ret;
|
||||
|
||||
switch (KeyInformationClass)
|
||||
{
|
||||
case KeyBasicInformation:
|
||||
{
|
||||
PKEY_BASIC_INFORMATION kbi = KeyInformation;
|
||||
UINT NameLength = strlenW(req->name) * sizeof(WCHAR);
|
||||
*ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
NTSTATUS ret;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kbi->LastWriteTime);
|
||||
kbi->TitleIndex = 0;
|
||||
kbi->NameLength = NameLength;
|
||||
memcpy (kbi->Name, req->name, NameLength);
|
||||
}
|
||||
break;
|
||||
case KeyFullInformation:
|
||||
{
|
||||
PKEY_FULL_INFORMATION kfi = KeyInformation;
|
||||
kfi->ClassLength = strlenW(req->class) * sizeof(WCHAR);
|
||||
kfi->ClassOffset = (kfi->ClassLength) ?
|
||||
sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
|
||||
|
||||
*ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kfi->LastWriteTime);
|
||||
kfi->TitleIndex = 0;
|
||||
kfi->SubKeys = req->subkeys;
|
||||
kfi->MaxNameLen = req->max_subkey;
|
||||
kfi->MaxClassLen = req->max_class;
|
||||
kfi->Values = req->values;
|
||||
kfi->MaxValueNameLen = req->max_value;
|
||||
kfi->MaxValueDataLen = req->max_data;
|
||||
if(kfi->ClassLength) memcpy ((char *) KeyInformation + kfi->ClassOffset, req->class, kfi->ClassLength);
|
||||
}
|
||||
break;
|
||||
case KeyNodeInformation:
|
||||
{
|
||||
PKEY_NODE_INFORMATION kni = KeyInformation;
|
||||
kni->ClassLength = strlenW(req->class) * sizeof(WCHAR);
|
||||
kni->NameLength = strlenW(req->name) * sizeof(WCHAR);
|
||||
kni->ClassOffset = (kni->ClassLength) ?
|
||||
sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
|
||||
|
||||
*ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
|
||||
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
RtlSecondsSince1970ToTime(req->modif, &kni->LastWriteTime);
|
||||
kni->TitleIndex = 0;
|
||||
memcpy (kni->Name, req->name, kni->NameLength);
|
||||
if(kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FIXME("KeyInformationClass not implemented\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
return ret;
|
||||
SERVER_START_REQ
|
||||
{
|
||||
struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
|
||||
req->hkey = handle;
|
||||
req->index = -1;
|
||||
req->full = (info_class == KeyFullInformation);
|
||||
if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
|
||||
{
|
||||
ret = fill_key_info( info_class, info, length, result_len, req );
|
||||
}
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -489,8 +466,6 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
|
|||
KEY_VALUE_INFORMATION_CLASS info_class,
|
||||
void *info, DWORD length, DWORD *result_len )
|
||||
{
|
||||
|
||||
|
||||
NTSTATUS ret;
|
||||
char *data_ptr;
|
||||
int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
|
||||
|
@ -523,7 +498,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
|
|||
do
|
||||
{
|
||||
size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
|
||||
reqlen = max( reqlen, name->Length );
|
||||
reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
|
||||
|
||||
SERVER_START_REQ
|
||||
{
|
||||
|
@ -554,7 +529,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
|
|||
|
||||
*result_len = total_len + fixed_size;
|
||||
|
||||
if (!data_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
|
||||
if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
|
||||
|
||||
switch(info_class)
|
||||
|
|
|
@ -821,17 +821,11 @@ NTSTATUS WINAPI NtDeleteKey(HANDLE);
|
|||
NTSTATUS WINAPI NtDeleteValueKey(HANDLE,const UNICODE_STRING*);
|
||||
NTSTATUS WINAPI NtOpenKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*);
|
||||
NTSTATUS WINAPI NtSetValueKey(HANDLE,const UNICODE_STRING*,ULONG,ULONG,const void*,ULONG);
|
||||
NTSTATUS WINAPI NtEnumerateKey(HANDLE,ULONG,KEY_INFORMATION_CLASS,void*,DWORD,DWORD*);
|
||||
NTSTATUS WINAPI NtQueryValueKey(HANDLE,const UNICODE_STRING*,KEY_VALUE_INFORMATION_CLASS,
|
||||
void*,DWORD,DWORD*);
|
||||
|
||||
|
||||
NTSTATUS WINAPI NtEnumerateKey(
|
||||
HANDLE KeyHandle,
|
||||
ULONG Index,
|
||||
KEY_INFORMATION_CLASS KeyInformationClass,
|
||||
PVOID KeyInformation,
|
||||
ULONG Length,
|
||||
PULONG ResultLength);
|
||||
|
||||
NTSTATUS WINAPI NtQueryKey(
|
||||
HANDLE KeyHandle,
|
||||
|
|
|
@ -1046,18 +1046,8 @@ struct enum_key_request
|
|||
{
|
||||
REQUEST_HEADER; /* request header */
|
||||
IN int hkey; /* handle to registry key */
|
||||
IN int index; /* index of subkey */
|
||||
OUT time_t modif; /* last modification time */
|
||||
OUT path_t name; /* subkey name */
|
||||
OUT WCHAR class[1]; /* class name */
|
||||
};
|
||||
|
||||
|
||||
/* Query information about a registry key */
|
||||
struct query_key_info_request
|
||||
{
|
||||
REQUEST_HEADER; /* request header */
|
||||
IN int hkey; /* handle to registry key */
|
||||
IN int index; /* index of subkey (or -1 for current key) */
|
||||
IN int full; /* return the full info? */
|
||||
OUT int subkeys; /* number of subkeys */
|
||||
OUT int max_subkey; /* longest subkey name */
|
||||
OUT int max_class; /* longest class name */
|
||||
|
@ -1065,8 +1055,8 @@ struct query_key_info_request
|
|||
OUT int max_value; /* longest value name */
|
||||
OUT int max_data; /* longest value data */
|
||||
OUT time_t modif; /* last modification time */
|
||||
OUT path_t name; /* key name */
|
||||
OUT WCHAR class[1]; /* class name */
|
||||
OUT VARARG(name,unicode_len_str); /* key name */
|
||||
OUT VARARG(class,unicode_str); /* class name */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1429,7 +1419,6 @@ enum request
|
|||
REQ_OPEN_KEY,
|
||||
REQ_DELETE_KEY,
|
||||
REQ_ENUM_KEY,
|
||||
REQ_QUERY_KEY_INFO,
|
||||
REQ_SET_KEY_VALUE,
|
||||
REQ_GET_KEY_VALUE,
|
||||
REQ_ENUM_KEY_VALUE,
|
||||
|
@ -1545,7 +1534,6 @@ union generic_request
|
|||
struct open_key_request open_key;
|
||||
struct delete_key_request delete_key;
|
||||
struct enum_key_request enum_key;
|
||||
struct query_key_info_request query_key_info;
|
||||
struct set_key_value_request set_key_value;
|
||||
struct get_key_value_request get_key_value;
|
||||
struct enum_key_value_request enum_key_value;
|
||||
|
@ -1574,7 +1562,7 @@ union generic_request
|
|||
struct set_serial_info_request set_serial_info;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 24
|
||||
#define SERVER_PROTOCOL_VERSION 25
|
||||
|
||||
/* ### make_requests end ### */
|
||||
/* Everything above this line is generated automatically by tools/make_requests */
|
||||
|
@ -1648,13 +1636,13 @@ static inline void server_strcpyAtoW( WCHAR *dst, const char *src )
|
|||
}
|
||||
|
||||
/* get a pointer to the variable part of the request */
|
||||
inline static void *server_data_ptr( void *req )
|
||||
inline static void *server_data_ptr( const void *req )
|
||||
{
|
||||
return (union generic_request *)req + 1;
|
||||
}
|
||||
|
||||
/* get the size of the variable part of the request */
|
||||
inline static size_t server_data_size( void *req )
|
||||
inline static size_t server_data_size( const void *req )
|
||||
{
|
||||
return ((struct request_header *)req)->var_size;
|
||||
}
|
||||
|
|
|
@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
|
|||
DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
|
||||
LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
|
||||
{
|
||||
DWORD ret, len, cls_len;
|
||||
struct enum_key_request *req = get_req_buffer();
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
|
||||
name_len ? *name_len : -1, reserved, class, class_len, ft );
|
||||
|
||||
if (reserved) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
req->index = index;
|
||||
if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
||||
len = strlenW( req->name ) + 1;
|
||||
cls_len = strlenW( req->class ) + 1;
|
||||
if (len > *name_len) return ERROR_MORE_DATA;
|
||||
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
|
||||
|
||||
memcpy( name, req->name, len * sizeof(WCHAR) );
|
||||
*name_len = len - 1;
|
||||
if (class_len)
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
|
||||
*class_len = cls_len - 1;
|
||||
/* retry with a dynamically allocated buffer */
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_NODE_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = info->NameLength / sizeof(WCHAR);
|
||||
DWORD cls_len = info->ClassLength / sizeof(WCHAR);
|
||||
|
||||
if (ft) *ft = info->LastWriteTime;
|
||||
|
||||
if (len >= *name_len || (class_len && (cls_len >= *class_len)))
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
else
|
||||
{
|
||||
*name_len = len;
|
||||
memcpy( name, info->Name, info->NameLength );
|
||||
name[len] = 0;
|
||||
if (class_len)
|
||||
{
|
||||
*class_len = cls_len;
|
||||
if (class)
|
||||
{
|
||||
memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
|
||||
class[cls_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
|
|||
DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
|
||||
LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
|
||||
{
|
||||
DWORD ret, len, cls_len;
|
||||
struct enum_key_request *req = get_req_buffer();
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
|
||||
name_len ? *name_len : -1, reserved, class, class_len, ft );
|
||||
|
||||
if (reserved) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
req->index = index;
|
||||
if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
||||
len = strlenW( req->name ) + 1;
|
||||
cls_len = strlenW( req->class ) + 1;
|
||||
if (len > *name_len) return ERROR_MORE_DATA;
|
||||
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
|
||||
|
||||
memcpyWtoA( name, req->name, len );
|
||||
*name_len = len - 1;
|
||||
if (class_len)
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class) memcpyWtoA( class, req->class, cls_len );
|
||||
*class_len = cls_len - 1;
|
||||
/* retry with a dynamically allocated buffer */
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_NODE_INFORMATION *)buf_ptr;
|
||||
status = NtEnumerateKey( hkey, index, KeyNodeInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
DWORD cls_len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength / sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
|
||||
if (ft) *ft = info->LastWriteTime;
|
||||
|
||||
if (len >= *name_len || (class_len && (cls_len >= *class_len)))
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
else
|
||||
{
|
||||
*name_len = len;
|
||||
WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
|
||||
name, len, NULL, NULL );
|
||||
name[len] = 0;
|
||||
if (class_len)
|
||||
{
|
||||
*class_len = cls_len;
|
||||
if (class)
|
||||
{
|
||||
WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength / sizeof(WCHAR),
|
||||
class, cls_len, NULL, NULL );
|
||||
class[cls_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
|
|||
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
|
||||
LPDWORD security, FILETIME *modif )
|
||||
{
|
||||
DWORD ret;
|
||||
struct query_key_info_request *req = get_req_buffer();
|
||||
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
|
||||
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
|
||||
|
@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
|
|||
if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
|
||||
|
||||
if (class)
|
||||
{
|
||||
if (class_len && (strlenW(req->class) + 1 > *class_len))
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
*class_len = strlenW(req->class);
|
||||
return ERROR_MORE_DATA;
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
|
||||
{
|
||||
status = STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
|
||||
class[info->ClassLength/sizeof(WCHAR)] = 0;
|
||||
}
|
||||
}
|
||||
strcpyW( class, req->class );
|
||||
}
|
||||
if (class_len) *class_len = strlenW( req->class );
|
||||
if (subkeys) *subkeys = req->subkeys;
|
||||
if (max_subkey) *max_subkey = req->max_subkey;
|
||||
if (max_class) *max_class = req->max_class;
|
||||
if (values) *values = req->values;
|
||||
if (max_value) *max_value = req->max_value;
|
||||
if (max_data) *max_data = req->max_data;
|
||||
if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status || status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
|
||||
if (subkeys) *subkeys = info->SubKeys;
|
||||
if (max_subkey) *max_subkey = info->MaxNameLen;
|
||||
if (max_class) *max_class = info->MaxClassLen;
|
||||
if (values) *values = info->Values;
|
||||
if (max_value) *max_value = info->MaxValueNameLen;
|
||||
if (max_data) *max_data = info->MaxValueDataLen;
|
||||
if (modif) *modif = info->LastWriteTime;
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
|
|||
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
|
||||
LPDWORD security, FILETIME *modif )
|
||||
{
|
||||
DWORD ret;
|
||||
struct query_key_info_request *req = get_req_buffer();
|
||||
|
||||
NTSTATUS status;
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
|
||||
DWORD total_size;
|
||||
|
||||
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
|
||||
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
|
||||
|
@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
|
|||
if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
req->hkey = hkey;
|
||||
if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
|
||||
|
||||
if (class)
|
||||
if (class || class_len)
|
||||
{
|
||||
if (class_len && (strlenW(req->class) + 1 > *class_len))
|
||||
/* retry with a dynamically allocated buffer */
|
||||
while (status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
*class_len = strlenW(req->class);
|
||||
return ERROR_MORE_DATA;
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
info = (KEY_FULL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
DWORD len = WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength/sizeof(WCHAR),
|
||||
NULL, 0, NULL, NULL );
|
||||
if (class_len)
|
||||
{
|
||||
if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
|
||||
*class_len = len;
|
||||
}
|
||||
if (class && !status)
|
||||
{
|
||||
WideCharToMultiByte( CP_ACP, 0,
|
||||
(WCHAR *)(buf_ptr + info->ClassOffset),
|
||||
info->ClassLength/sizeof(WCHAR),
|
||||
class, len, NULL, NULL );
|
||||
class[len] = 0;
|
||||
}
|
||||
}
|
||||
lstrcpyWtoA( class, req->class );
|
||||
}
|
||||
if (class_len) *class_len = strlenW( req->class );
|
||||
if (subkeys) *subkeys = req->subkeys;
|
||||
if (max_subkey) *max_subkey = req->max_subkey;
|
||||
if (max_class) *max_class = req->max_class;
|
||||
if (values) *values = req->values;
|
||||
if (max_value) *max_value = req->max_value;
|
||||
if (max_data) *max_data = req->max_data;
|
||||
if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
if (!status || status == STATUS_BUFFER_OVERFLOW)
|
||||
{
|
||||
if (subkeys) *subkeys = info->SubKeys;
|
||||
if (max_subkey) *max_subkey = info->MaxNameLen;
|
||||
if (max_class) *max_class = info->MaxClassLen;
|
||||
if (values) *values = info->Values;
|
||||
if (max_value) *max_value = info->MaxValueNameLen;
|
||||
if (max_data) *max_data = info->MaxValueDataLen;
|
||||
if (modif) *modif = info->LastWriteTime;
|
||||
}
|
||||
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
NTSTATUS status;
|
||||
UNICODE_STRING name_str;
|
||||
DWORD total_size;
|
||||
char buffer[256];
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||
static const int info_size = sizeof(*info) - sizeof(info->Data);
|
||||
|
||||
|
@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
|
||||
if (data)
|
||||
{
|
||||
char *buf_ptr = buffer;
|
||||
/* 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 )))
|
||||
status = STATUS_NO_MEMORY;
|
||||
else
|
||||
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &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)
|
||||
|
@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
|
|||
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
|
||||
}
|
||||
}
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
else if (status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
}
|
||||
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = total_size - info_size;
|
||||
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
ANSI_STRING nameA;
|
||||
UNICODE_STRING nameW;
|
||||
DWORD total_size;
|
||||
char buffer[256];
|
||||
char buffer[256], *buf_ptr = buffer;
|
||||
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
|
||||
static const int info_size = sizeof(*info) - sizeof(info->Data);
|
||||
|
||||
|
@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
|
||||
RtlInitAnsiString( &nameA, name );
|
||||
/* FIXME: should use Unicode buffer in TEB */
|
||||
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
|
||||
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
|
||||
return RtlNtStatusToDosError(status);
|
||||
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buffer, sizeof(buffer), &total_size );
|
||||
|
@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
* because we need to compute the length of the ASCII string. */
|
||||
if (data || is_string(info->Type))
|
||||
{
|
||||
char *buf_ptr = buffer;
|
||||
/* 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 )))
|
||||
{
|
||||
status = STATUS_NO_MEMORY;
|
||||
else
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
goto done;
|
||||
}
|
||||
info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
|
||||
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
|
||||
buf_ptr, total_size, &total_size );
|
||||
}
|
||||
|
||||
if (!status)
|
||||
|
@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
|
|||
total_size = len + info_size;
|
||||
}
|
||||
else if (data) 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;
|
||||
}
|
||||
}
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
else if (status != STATUS_BUFFER_OVERFLOW) goto done;
|
||||
}
|
||||
|
||||
if (type) *type = info->Type;
|
||||
if (count) *count = total_size - info_size;
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
|
||||
done:
|
||||
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
|
||||
RtlFreeUnicodeString( &nameW );
|
||||
return RtlNtStatusToDosError(status);
|
||||
}
|
||||
|
||||
|
|
|
@ -560,57 +560,80 @@ static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
|
|||
return key;
|
||||
}
|
||||
|
||||
/* find a subkey of a given key by its index */
|
||||
static void enum_key( struct key *parent, int index, WCHAR *name, WCHAR *class, time_t *modif )
|
||||
/* query information about a key or a subkey */
|
||||
static size_t enum_key( struct key *key, int index, struct enum_key_request *req )
|
||||
{
|
||||
struct key *key;
|
||||
|
||||
if ((index < 0) || (index > parent->last_subkey)) set_error( STATUS_NO_MORE_ENTRIES );
|
||||
else
|
||||
{
|
||||
key = parent->subkeys[index];
|
||||
*modif = key->modif;
|
||||
strcpyW( name, key->name );
|
||||
if (key->class) strcpyW( class, key->class ); /* FIXME: length */
|
||||
else *class = 0;
|
||||
if (debug_level > 1) dump_operation( key, NULL, "Enum" );
|
||||
}
|
||||
}
|
||||
|
||||
/* query information about a key */
|
||||
static void query_key( struct key *key, struct query_key_info_request *req )
|
||||
{
|
||||
int i, len;
|
||||
int i;
|
||||
size_t len, namelen, classlen;
|
||||
int max_subkey = 0, max_class = 0;
|
||||
int max_value = 0, max_data = 0;
|
||||
WCHAR *data = get_req_data(req);
|
||||
|
||||
for (i = 0; i <= key->last_subkey; i++)
|
||||
if (index != -1) /* -1 means use the specified key directly */
|
||||
{
|
||||
struct key *subkey = key->subkeys[i];
|
||||
len = strlenW( subkey->name );
|
||||
if (len > max_subkey) max_subkey = len;
|
||||
if (!subkey->class) continue;
|
||||
len = strlenW( subkey->class );
|
||||
if (len > max_class) max_class = len;
|
||||
if ((index < 0) || (index > key->last_subkey))
|
||||
{
|
||||
set_error( STATUS_NO_MORE_ENTRIES );
|
||||
return 0;
|
||||
}
|
||||
key = key->subkeys[index];
|
||||
}
|
||||
for (i = 0; i <= key->last_value; i++)
|
||||
|
||||
if (req->full)
|
||||
{
|
||||
len = strlenW( key->values[i].name );
|
||||
if (len > max_value) max_value = len;
|
||||
len = key->values[i].len;
|
||||
if (len > max_data) max_data = len;
|
||||
for (i = 0; i <= key->last_subkey; i++)
|
||||
{
|
||||
struct key *subkey = key->subkeys[i];
|
||||
len = strlenW( subkey->name );
|
||||
if (len > max_subkey) max_subkey = len;
|
||||
if (!subkey->class) continue;
|
||||
len = strlenW( subkey->class );
|
||||
if (len > max_class) max_class = len;
|
||||
}
|
||||
for (i = 0; i <= key->last_value; i++)
|
||||
{
|
||||
len = strlenW( key->values[i].name );
|
||||
if (len > max_value) max_value = len;
|
||||
len = key->values[i].len;
|
||||
if (len > max_data) max_data = len;
|
||||
}
|
||||
req->max_subkey = max_subkey;
|
||||
req->max_class = max_class;
|
||||
req->max_value = max_value;
|
||||
req->max_data = max_data;
|
||||
}
|
||||
req->subkeys = key->last_subkey + 1;
|
||||
req->max_subkey = max_subkey;
|
||||
req->max_class = max_class;
|
||||
req->values = key->last_value + 1;
|
||||
req->max_value = max_value;
|
||||
req->max_data = max_data;
|
||||
req->modif = key->modif;
|
||||
strcpyW( req->name, key->name);
|
||||
if (key->class) strcpyW( req->class, key->class ); /* FIXME: length */
|
||||
else req->class[0] = 0;
|
||||
if (debug_level > 1) dump_operation( key, NULL, "Query" );
|
||||
else
|
||||
{
|
||||
req->max_subkey = 0;
|
||||
req->max_class = 0;
|
||||
req->max_value = 0;
|
||||
req->max_data = 0;
|
||||
}
|
||||
req->subkeys = key->last_subkey + 1;
|
||||
req->values = key->last_value + 1;
|
||||
req->modif = key->modif;
|
||||
|
||||
namelen = strlenW(key->name) * sizeof(WCHAR);
|
||||
classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
|
||||
|
||||
len = namelen + classlen + sizeof(WCHAR);
|
||||
if (len > get_req_data_size(req))
|
||||
{
|
||||
len = get_req_data_size(req);
|
||||
if (len < sizeof(WCHAR)) return 0;
|
||||
}
|
||||
|
||||
*data++ = namelen;
|
||||
len -= sizeof(WCHAR);
|
||||
if (len > namelen)
|
||||
{
|
||||
memcpy( data, key->name, namelen );
|
||||
memcpy( (char *)data + namelen, key->class, min(classlen,len-namelen) );
|
||||
}
|
||||
else memcpy( data, key->name, len );
|
||||
|
||||
if (debug_level > 1) dump_operation( key, NULL, "Enum" );
|
||||
return len + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
/* delete a key and its values */
|
||||
|
@ -1537,31 +1560,29 @@ DECL_HANDLER(create_key)
|
|||
|
||||
if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */
|
||||
req->hkey = -1;
|
||||
if (!(name = copy_req_path( req, &len ))) return;
|
||||
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
|
||||
{
|
||||
if ((name = copy_req_path( req, &len )))
|
||||
if (len == get_req_data_size(req)) /* no class specified */
|
||||
{
|
||||
if (len == get_req_data_size(req)) /* no class specified */
|
||||
{
|
||||
key = create_key( parent, name, NULL, req->options, req->modif, &req->created );
|
||||
}
|
||||
else
|
||||
{
|
||||
const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data(req) + len);
|
||||
key = create_key( parent, name, NULL, req->options, req->modif, &req->created );
|
||||
}
|
||||
else
|
||||
{
|
||||
const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data(req) + len);
|
||||
|
||||
if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len )))
|
||||
{
|
||||
key = create_key( parent, name, class, req->options,
|
||||
req->modif, &req->created );
|
||||
free( class );
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len )))
|
||||
{
|
||||
req->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
release_object( key );
|
||||
key = create_key( parent, name, class, req->options,
|
||||
req->modif, &req->created );
|
||||
free( class );
|
||||
}
|
||||
}
|
||||
if (key)
|
||||
{
|
||||
req->hkey = alloc_handle( current->process, key, access, 0 );
|
||||
release_object( key );
|
||||
}
|
||||
release_object( parent );
|
||||
}
|
||||
}
|
||||
|
@ -1602,26 +1623,15 @@ DECL_HANDLER(delete_key)
|
|||
DECL_HANDLER(enum_key)
|
||||
{
|
||||
struct key *key;
|
||||
size_t len = 0;
|
||||
|
||||
req->name[0] = req->class[0] = 0;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_ENUMERATE_SUB_KEYS )))
|
||||
if ((key = get_hkey_obj( req->hkey,
|
||||
req->index == -1 ? KEY_QUERY_VALUE : KEY_ENUMERATE_SUB_KEYS )))
|
||||
{
|
||||
enum_key( key, req->index, req->name, req->class, &req->modif );
|
||||
release_object( key );
|
||||
}
|
||||
}
|
||||
|
||||
/* query information about a registry key */
|
||||
DECL_HANDLER(query_key_info)
|
||||
{
|
||||
struct key *key;
|
||||
|
||||
req->name[0] = req->class[0] = 0;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
|
||||
{
|
||||
query_key( key, req );
|
||||
len = enum_key( key, req->index, req );
|
||||
release_object( key );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* set a value of a registry key */
|
||||
|
@ -1631,15 +1641,13 @@ DECL_HANDLER(set_key_value)
|
|||
WCHAR *name;
|
||||
size_t len;
|
||||
|
||||
if (!(name = copy_req_path( req, &len ))) return;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
|
||||
{
|
||||
if ((name = copy_req_path( req, &len )))
|
||||
{
|
||||
size_t datalen = get_req_data_size(req) - len;
|
||||
const char *data = (char *)get_req_data(req) + len;
|
||||
size_t datalen = get_req_data_size(req) - len;
|
||||
const char *data = (char *)get_req_data(req) + len;
|
||||
|
||||
set_value( key, name, req->type, req->total, req->offset, datalen, data );
|
||||
}
|
||||
set_value( key, name, req->type, req->total, req->offset, datalen, data );
|
||||
release_object( key );
|
||||
}
|
||||
}
|
||||
|
@ -1649,19 +1657,17 @@ DECL_HANDLER(get_key_value)
|
|||
{
|
||||
struct key *key;
|
||||
WCHAR *name;
|
||||
size_t len;
|
||||
size_t len = 0, tmp;
|
||||
|
||||
req->len = 0;
|
||||
if (!(name = copy_req_path( req, &tmp ))) return;
|
||||
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
|
||||
{
|
||||
if ((name = copy_req_path( req, &len )))
|
||||
{
|
||||
len = get_value( key, name, req->offset, get_req_data_size(req),
|
||||
&req->type, &req->len, get_req_data(req) );
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
len = get_value( key, name, req->offset, get_req_data_size(req),
|
||||
&req->type, &req->len, get_req_data(req) );
|
||||
release_object( key );
|
||||
}
|
||||
set_req_data_size( req, len );
|
||||
}
|
||||
|
||||
/* enumerate the value of a registry key */
|
||||
|
|
|
@ -176,7 +176,6 @@ DECL_HANDLER(create_key);
|
|||
DECL_HANDLER(open_key);
|
||||
DECL_HANDLER(delete_key);
|
||||
DECL_HANDLER(enum_key);
|
||||
DECL_HANDLER(query_key_info);
|
||||
DECL_HANDLER(set_key_value);
|
||||
DECL_HANDLER(get_key_value);
|
||||
DECL_HANDLER(enum_key_value);
|
||||
|
@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_open_key,
|
||||
(req_handler)req_delete_key,
|
||||
(req_handler)req_enum_key,
|
||||
(req_handler)req_query_key_info,
|
||||
(req_handler)req_set_key_value,
|
||||
(req_handler)req_get_key_value,
|
||||
(req_handler)req_enum_key_value,
|
||||
|
|
|
@ -94,7 +94,7 @@ static void dump_exc_record( const EXCEPTION_RECORD *rec )
|
|||
fprintf( stderr, "{code=%lx,flags=%lx,rec=%p,addr=%p,params={",
|
||||
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionRecord,
|
||||
rec->ExceptionAddress );
|
||||
for (i = 0; i < rec->NumberParameters; i++)
|
||||
for (i = 0; i < min(rec->NumberParameters,EXCEPTION_MAXIMUM_PARAMETERS); i++)
|
||||
{
|
||||
if (i) fputc( ',', stderr );
|
||||
fprintf( stderr, "%lx", rec->ExceptionInformation[i] );
|
||||
|
@ -156,12 +156,12 @@ static size_t dump_varargs_string( const void *req )
|
|||
static size_t dump_varargs_unicode_len_str( const void *req )
|
||||
{
|
||||
const WCHAR *str = get_data(req);
|
||||
WCHAR len = *str++;
|
||||
int len = *str++ + sizeof(WCHAR);
|
||||
len = min( len, get_size(req) );
|
||||
fprintf( stderr, "L\"" );
|
||||
dump_strW( str, len / sizeof(WCHAR), stderr, "\"\"" );
|
||||
if (len >= sizeof(WCHAR)) dump_strW( str, (len / sizeof(WCHAR)) - 1, stderr, "\"\"" );
|
||||
fputc( '\"', stderr );
|
||||
return len + sizeof(WCHAR);
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t dump_varargs_unicode_str( const void *req )
|
||||
|
@ -1184,25 +1184,11 @@ static void dump_delete_key_request( const struct delete_key_request *req )
|
|||
static void dump_enum_key_request( const struct enum_key_request *req )
|
||||
{
|
||||
fprintf( stderr, " hkey=%d,", req->hkey );
|
||||
fprintf( stderr, " index=%d", req->index );
|
||||
fprintf( stderr, " index=%d,", req->index );
|
||||
fprintf( stderr, " full=%d", req->full );
|
||||
}
|
||||
|
||||
static void dump_enum_key_reply( const struct enum_key_request *req )
|
||||
{
|
||||
fprintf( stderr, " modif=%ld,", req->modif );
|
||||
fprintf( stderr, " name=" );
|
||||
dump_path_t( req, &req->name );
|
||||
fprintf( stderr, "," );
|
||||
fprintf( stderr, " class=" );
|
||||
dump_unicode_string( req, req->class );
|
||||
}
|
||||
|
||||
static void dump_query_key_info_request( const struct query_key_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " hkey=%d", req->hkey );
|
||||
}
|
||||
|
||||
static void dump_query_key_info_reply( const struct query_key_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " subkeys=%d,", req->subkeys );
|
||||
fprintf( stderr, " max_subkey=%d,", req->max_subkey );
|
||||
|
@ -1212,10 +1198,10 @@ static void dump_query_key_info_reply( const struct query_key_info_request *req
|
|||
fprintf( stderr, " max_data=%d,", req->max_data );
|
||||
fprintf( stderr, " modif=%ld,", req->modif );
|
||||
fprintf( stderr, " name=" );
|
||||
dump_path_t( req, &req->name );
|
||||
fprintf( stderr, "," );
|
||||
cur_pos += dump_varargs_unicode_len_str( req );
|
||||
fputc( ',', stderr );
|
||||
fprintf( stderr, " class=" );
|
||||
dump_unicode_string( req, req->class );
|
||||
cur_pos += dump_varargs_unicode_str( req );
|
||||
}
|
||||
|
||||
static void dump_set_key_value_request( const struct set_key_value_request *req )
|
||||
|
@ -1574,7 +1560,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_open_key_request,
|
||||
(dump_func)dump_delete_key_request,
|
||||
(dump_func)dump_enum_key_request,
|
||||
(dump_func)dump_query_key_info_request,
|
||||
(dump_func)dump_set_key_value_request,
|
||||
(dump_func)dump_get_key_value_request,
|
||||
(dump_func)dump_enum_key_value_request,
|
||||
|
@ -1686,7 +1671,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_open_key_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_enum_key_reply,
|
||||
(dump_func)dump_query_key_info_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_key_value_reply,
|
||||
(dump_func)dump_enum_key_value_reply,
|
||||
|
@ -1798,7 +1782,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"open_key",
|
||||
"delete_key",
|
||||
"enum_key",
|
||||
"query_key_info",
|
||||
"set_key_value",
|
||||
"get_key_value",
|
||||
"enum_key_value",
|
||||
|
|
Loading…
Reference in New Issue