Converted some of the registry server requests to the new request

mechanism.
This commit is contained in:
Alexandre Julliard 2000-10-01 01:44:50 +00:00
parent d76f9f9637
commit bcf393a5e5
8 changed files with 940 additions and 786 deletions

View File

@ -29,14 +29,6 @@
DEFAULT_DEBUG_CHANNEL(reg);
/* Ansi->Unicode conversion without string delimiters */
static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n )
{
LPWSTR p = dst;
while (n-- > 0) *p++ = (WCHAR)*src++;
return dst;
}
/* Unicode->Ansi conversion without string delimiters */
static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n )
{
@ -104,29 +96,23 @@ DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR cl
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
debugstr_w(class), options, access, sa, retkey, dispos );
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW, classW;
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
RtlInitUnicodeString( &classW, class );
return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0,
&classW, options, dispos ) );
}
@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
debugstr_a(class), options, access, sa, retkey, dispos );
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW, classW;
ANSI_STRING nameA, classA;
NTSTATUS status;
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynAtoW( req->class, class ? class : "",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitAnsiString( &nameA, name );
RtlInitAnsiString( &classA, class );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
{
status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos );
RtlFreeUnicodeString( &classW );
}
RtlFreeUnicodeString( &nameW );
}
return ret;
return RtlNtStatusToDosError( status );
}
@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
*/
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
if (!retkey) return ERROR_INVALID_PARAMETER;
*retkey = 0;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
}
@ -231,20 +219,26 @@ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM acce
*/
DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
if (!retkey) return ERROR_INVALID_PARAMETER;
*retkey = 0;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtOpenKey( retkey, access, &attr );
RtlFreeUnicodeString( &nameW );
}
return RtlNtStatusToDosError( status );
}
@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
*/
DWORD WINAPI RegCloseKey( HKEY hkey )
{
struct close_key_request *req = get_req_buffer();
TRACE( "(0x%x)\n", hkey );
req->hkey = hkey;
return reg_server_call( REQ_CLOSE_KEY );
if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS;
return RtlNtStatusToDosError( NtClose( hkey ) );
}
@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey )
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return reg_server_call( REQ_DELETE_KEY );
if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp )))
{
ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
RegCloseKey( tmp );
}
return ret;
}
@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return reg_server_call( REQ_DELETE_KEY );
if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
{
ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
RegCloseKey( tmp );
}
return ret;
}
@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
if (count && is_string(type))
{
LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */
@ -584,24 +572,8 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
count += sizeof(WCHAR);
}
req->hkey = hkey;
req->type = type;
req->total = count;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
max = server_remaining( req->data );
pos = 0;
while (pos < count)
{
unsigned int len = count - pos;
if (len > max) len = max;
req->offset = pos;
req->len = len;
memcpy( req->data, data + pos, len );
if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
pos += len;
}
return ret;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
}
@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
* RegSetValueExA [ADVAPI32.169]
*/
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
CONST BYTE *data, DWORD count )
CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
UNICODE_STRING nameW;
ANSI_STRING nameA;
WCHAR *dataW = NULL;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
if (count && is_string(type))
{
/* if user forgot to count terminating null, add it (yes NT does this) */
if (data[count-1] && !data[count]) count++;
}
if (is_string( type )) /* need to convert to Unicode */
count *= sizeof(WCHAR);
req->hkey = hkey;
req->type = type;
req->total = count;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
max = server_remaining( req->data );
pos = 0;
while (pos < count)
{
unsigned int len = count - pos;
if (len > max) len = max;
req->offset = pos;
req->len = len;
if (is_string( type ))
memcpyAtoW( (LPWSTR)req->data, data + pos/sizeof(WCHAR), len/sizeof(WCHAR) );
else
memcpy( req->data, data + pos, len );
if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
pos += len;
DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 );
if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) )))
return ERROR_OUTOFMEMORY;
MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW );
count = lenW * sizeof(WCHAR);
data = (BYTE *)dataW;
}
return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtSetValueKey( hkey, &nameW, 0, type, data, count );
RtlFreeUnicodeString( &nameW );
}
if (dataW) HeapFree( GetProcessHeap(), 0, dataW );
return RtlNtStatusToDosError( status );
}
@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
LPBYTE data, LPDWORD count )
{
DWORD ret;
struct get_key_value_request *req = get_req_buffer();
NTSTATUS status;
UNICODE_STRING name_str;
DWORD total_size;
char buffer[256];
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
static const int info_size = sizeof(*info) - sizeof(info->Data);
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->offset = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
RtlInitUnicodeString( &name_str, name );
if (data) total_size = min( sizeof(buffer), *count + info_size );
else total_size = info_size;
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buffer, total_size, &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
if (data)
{
if (*count < req->len) ret = ERROR_MORE_DATA;
else
char *buf_ptr = buffer;
/* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
{
/* copy the data */
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
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 );
}
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{
unsigned int len = min( req->len - pos, max );
memcpy( data + pos, req->data, len );
if ((pos += len) >= req->len) break;
req->offset = pos;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
}
}
/* 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 (req->len && is_string(req->type) &&
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
}
if (type) *type = req->type;
if (count) *count = req->len;
return ret;
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
}
@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
* the documentation is wrong: if the buffer is to small it remains untouched
*/
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
LPBYTE data, LPDWORD count )
{
DWORD ret, total_len;
struct get_key_value_request *req = get_req_buffer();
NTSTATUS status;
ANSI_STRING nameA;
UNICODE_STRING nameW;
DWORD total_size;
char buffer[256];
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
static const int info_size = sizeof(*info) - sizeof(info->Data);
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->offset = 0;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len;
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
if (data)
/* 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 (data || is_string(info->Type))
{
if (*count < total_len) ret = ERROR_MORE_DATA;
else
char *buf_ptr = buffer;
/* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW)
{
/* copy the data */
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
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 );
}
if (!status)
{
if (is_string(info->Type))
{
unsigned int len = min( req->len - pos, max );
if (is_string( req->type ))
memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) );
else
memcpy( data + pos, req->data, len );
if ((pos += len) >= req->len) break;
req->offset = pos;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
NULL, 0, NULL, NULL );
if (data && len)
{
if (len > *count) status = STATUS_BUFFER_OVERFLOW;
else
{
WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
data, len, NULL, NULL );
/* 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;
}
}
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 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_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
data[total_len] = 0;
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
}
if (count) *count = total_len;
if (type) *type = req->type;
return ret;
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
RtlFreeUnicodeString( &nameW );
done:
return RtlNtStatusToDosError(status);
}
@ -1011,14 +1023,9 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou
*/
DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
return reg_server_call( REQ_DELETE_KEY_VALUE );
UNICODE_STRING nameW;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
}
@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
*/
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
UNICODE_STRING nameW;
STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
return reg_server_call( REQ_DELETE_KEY_VALUE );
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtDeleteValueKey( hkey, &nameW );
RtlFreeUnicodeString( &nameW );
}
return RtlNtStatusToDosError( status );
}

View File

@ -1,5 +1,8 @@
/*
* registry functions
* Registry functions
*
* Copyright (C) 1999 Juergen Schmied
* Copyright (C) 2000 Alexandre Julliard
*
* NOTES:
* HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
@ -26,21 +29,8 @@ static const UNICODE_STRING root_path =
(LPWSTR)root_name /* Buffer */
};
/* copy a key name into the request buffer */
static NTSTATUS copy_key_name( LPWSTR dest, const UNICODE_STRING *name )
{
int len = name->Length, pos = 0;
if (len >= MAX_PATH) return STATUS_BUFFER_OVERFLOW;
if (RtlPrefixUnicodeString( &root_path, name, TRUE ))
{
pos += root_path.Length / sizeof(WCHAR);
len -= root_path.Length;
}
if (len) memcpy( dest, name->Buffer + pos, len );
dest[len / sizeof(WCHAR)] = 0;
return STATUS_SUCCESS;
}
/* maximum length of a key/value name in bytes (without terminating null) */
#define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
/* copy a key name into the request buffer */
@ -61,31 +51,41 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT
ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
PULONG dispos )
{
struct create_key_request *req = get_req_buffer();
NTSTATUS ret;
DWORD len = attr->ObjectName->Length;
TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
debugstr_us(class), options, access, retkey );
if (!retkey) return STATUS_INVALID_PARAMETER;
req->parent = attr->RootDirectory;
req->access = access;
req->options = options;
req->modif = 0;
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
req->class[0] = 0;
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
len += sizeof(WCHAR); /* for storing name length */
if (class)
{
if ((ret = copy_nameU( req->class, class, server_remaining(req->class) ))) return ret;
len += class->Length;
if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
}
if (!retkey) return STATUS_INVALID_PARAMETER;
if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
SERVER_START_REQ
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
struct create_key_request *req = server_alloc_req( sizeof(*req), len );
WCHAR *data = server_data_ptr(req);
req->parent = attr->RootDirectory;
req->access = access;
req->options = options;
req->modif = 0;
*data++ = attr->ObjectName->Length;
memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
}
SERVER_END_REQ;
return ret;
}
@ -99,20 +99,25 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT
*/
NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
{
struct open_key_request *req = get_req_buffer();
NTSTATUS ret;
DWORD len = attr->ObjectName->Length;
TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
debugstr_us(attr->ObjectName), access, retkey );
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
if (!retkey) return STATUS_INVALID_PARAMETER;
*retkey = 0;
req->parent = attr->RootDirectory;
req->access = access;
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
SERVER_START_REQ
{
struct open_key_request *req = server_alloc_req( sizeof(*req), len );
req->parent = attr->RootDirectory;
req->access = access;
memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
}
SERVER_END_REQ;
return ret;
}
@ -123,12 +128,18 @@ NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTR
*/
NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
{
struct delete_key_request *req = get_req_buffer();
NTSTATUS ret;
TRACE( "(%x)\n", hkey );
req->hkey = hkey;
req->name[0] = 0;
return server_call_noerr( REQ_DELETE_KEY );
SERVER_START_REQ
{
struct delete_key_request *req = server_alloc_req( sizeof(*req), 0 );
req->hkey = hkey;
ret = server_call_noerr( REQ_DELETE_KEY );
}
SERVER_END_REQ;
return ret;
}
@ -139,13 +150,19 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
{
NTSTATUS ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
req->hkey = hkey;
if (!(ret = copy_nameU( req->name, name, MAX_PATH )))
SERVER_START_REQ
{
struct delete_key_value_request *req = server_alloc_req( sizeof(*req), name->Length );
req->hkey = hkey;
memcpy( server_data_ptr(req), name->Buffer, name->Length );
ret = server_call_noerr( REQ_DELETE_KEY_VALUE );
}
SERVER_END_REQ;
return ret;
}
@ -468,70 +485,113 @@ NTSTATUS WINAPI NtQueryMultipleValueKey(
* NOTES
* the name in the KeyValueInformation is never set
*/
NTSTATUS WINAPI NtQueryValueKey(
IN HANDLE KeyHandle,
IN PUNICODE_STRING ValueName,
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
KEY_VALUE_INFORMATION_CLASS info_class,
void *info, DWORD length, DWORD *result_len )
{
struct get_key_value_request *req = get_req_buffer();
NTSTATUS ret;
TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n",
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
req->hkey = KeyHandle;
if (copy_nameU(req->name, ValueName, MAX_PATH) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW;
if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret;
NTSTATUS ret;
char *data_ptr;
int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
switch(KeyValueInformationClass)
{
case KeyValueBasicInformation:
{
PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation;
kbi->Type = req->type;
TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR);
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
kbi->NameLength = 0;
}
break;
case KeyValueFullInformation:
{
PKEY_VALUE_FULL_INFORMATION kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation;
ULONG DataOffset;
kfi->Type = req->type;
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR);
*ResultLength = DataOffset + req->len;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
/* compute the length we want to retrieve */
switch(info_class)
{
case KeyValueBasicInformation:
fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR);
data_ptr = NULL;
break;
case KeyValueFullInformation:
fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR);
data_ptr = (char *)info + fixed_size;
break;
case KeyValuePartialInformation:
fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR);
data_ptr = (char *)info + fixed_size;
break;
default:
FIXME( "Information class %d not implemented\n", info_class );
return STATUS_INVALID_PARAMETER;
}
if (data_ptr && length > fixed_size) data_len = length - fixed_size;
kfi->NameLength = 0;
kfi->DataOffset = DataOffset;
kfi->DataLength = req->len;
memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len);
}
break;
case KeyValuePartialInformation:
{
PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
kpi->Type = req->type;
do
{
size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
reqlen = max( reqlen, name->Length );
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
SERVER_START_REQ
{
struct get_key_value_request *req = server_alloc_req( sizeof(*req), reqlen );
WCHAR *nameptr = server_data_ptr(req);
kpi->DataLength = req->len;
memcpy(kpi->Data, req->data, req->len);
}
break;
default:
FIXME("KeyValueInformationClass not implemented\n");
return STATUS_UNSUCCESSFUL;
}
return ret;
req->hkey = handle;
req->offset = offset;
*nameptr++ = name->Length;
memcpy( nameptr, name->Buffer, name->Length );
if (!(ret = server_call_noerr( REQ_GET_KEY_VALUE )))
{
size_t size = min( server_data_size(req), data_len );
type = req->type;
total_len = req->len;
if (size)
{
memcpy( data_ptr + offset, server_data_ptr(req), size );
offset += size;
data_len -= size;
}
}
}
SERVER_END_REQ;
if (ret) return ret;
} while (data_len && offset < total_len);
*result_len = total_len + fixed_size;
if (!data_len) ret = STATUS_BUFFER_OVERFLOW;
if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
switch(info_class)
{
case KeyValueBasicInformation:
{
KEY_VALUE_BASIC_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.NameLength = 0;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
case KeyValueFullInformation:
{
KEY_VALUE_FULL_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.DataOffset = fixed_size;
keyinfo.DataLength = total_len;
keyinfo.NameLength = 0;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
case KeyValuePartialInformation:
{
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.DataLength = total_len;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
default:
break;
}
return ret;
}
/******************************************************************************
@ -587,22 +647,52 @@ NTSTATUS WINAPI NtSetInformationKey(
KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
return STATUS_SUCCESS;
}
/******************************************************************************
* NtSetValueKey [NTDLL]
* ZwSetValueKey
*
* NOTES
* win95 does not care about count for REG_SZ and finds out the len by itself (js)
* NT does definitely care (aj)
*/
NTSTATUS WINAPI NtSetValueKey(
HANDLE KeyHandle,
PUNICODE_STRING ValueName,
ULONG TitleIndex,
ULONG Type,
PVOID Data,
ULONG DataSize)
NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
ULONG type, const void *data, ULONG count )
{
FIXME("(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n",
KeyHandle, ValueName,debugstr_us(ValueName), TitleIndex, Type, Data, DataSize);
return STATUS_SUCCESS;
NTSTATUS ret;
ULONG namelen, pos;
TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
namelen = name->Length + sizeof(WCHAR); /* for storing length */
pos = 0;
do
{
ULONG len = count - pos;
if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen;
SERVER_START_REQ
{
struct set_key_value_request *req = server_alloc_req( sizeof(*req), namelen + len );
WCHAR *name_ptr = server_data_ptr(req);
req->hkey = hkey;
req->type = type;
req->total = count;
req->offset = pos;
*name_ptr++ = name->Length;
memcpy( name_ptr, name->Buffer, name->Length );
memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len );
pos += len;
ret = server_call_noerr( REQ_SET_KEY_VALUE );
}
SERVER_END_REQ;
} while (!ret && pos < count);
return ret;
}
/******************************************************************************

View File

@ -1018,11 +1018,10 @@ struct create_key_request
IN time_t modif; /* last modification time */
OUT int hkey; /* handle to the created key */
OUT int created; /* has it been newly created? */
IN path_t name; /* key name */
IN WCHAR class[1]; /* class name */
IN VARARG(name,unicode_len_str); /* key name */
IN VARARG(class,unicode_str); /* class name */
};
/* Open a registry key */
struct open_key_request
{
@ -1030,7 +1029,7 @@ struct open_key_request
IN int parent; /* handle to the parent key */
IN unsigned int access; /* desired access rights */
OUT int hkey; /* handle to the open key */
IN path_t name; /* key name */
IN VARARG(name,unicode_str); /* key name */
};
@ -1038,16 +1037,7 @@ struct open_key_request
struct delete_key_request
{
REQUEST_HEADER; /* request header */
IN int hkey; /* handle to the parent key */
IN path_t name; /* key name */
};
/* Close a registry key */
struct close_key_request
{
REQUEST_HEADER; /* request header */
IN int hkey; /* key to close */
IN int hkey; /* handle to the key */
};
@ -1088,9 +1078,8 @@ struct set_key_value_request
IN int type; /* value type */
IN unsigned int total; /* total value len */
IN unsigned int offset; /* offset for setting data */
IN unsigned int len; /* value data len */
IN path_t name; /* value name */
IN unsigned char data[1]; /* value data */
IN VARARG(name,unicode_len_str); /* value name */
IN VARARG(data,bytes); /* value data */
};
@ -1102,8 +1091,8 @@ struct get_key_value_request
IN unsigned int offset; /* offset for getting data */
OUT int type; /* value type */
OUT int len; /* value data len */
IN WCHAR name[1]; /* value name */
OUT unsigned char data[1]; /* value data */
IN VARARG(name,unicode_len_str); /* value name */
OUT VARARG(data,bytes); /* value data */
};
@ -1126,7 +1115,7 @@ struct delete_key_value_request
{
REQUEST_HEADER; /* request header */
IN int hkey; /* handle to registry key */
IN path_t name; /* value name */
IN VARARG(name,unicode_str); /* value name */
};
@ -1439,7 +1428,6 @@ enum request
REQ_CREATE_KEY,
REQ_OPEN_KEY,
REQ_DELETE_KEY,
REQ_CLOSE_KEY,
REQ_ENUM_KEY,
REQ_QUERY_KEY_INFO,
REQ_SET_KEY_VALUE,
@ -1556,7 +1544,6 @@ union generic_request
struct create_key_request create_key;
struct open_key_request open_key;
struct delete_key_request delete_key;
struct close_key_request close_key;
struct enum_key_request enum_key;
struct query_key_info_request query_key_info;
struct set_key_value_request set_key_value;
@ -1587,7 +1574,7 @@ union generic_request
struct set_serial_info_request set_serial_info;
};
#define SERVER_PROTOCOL_VERSION 23
#define SERVER_PROTOCOL_VERSION 24
/* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */

View File

@ -29,14 +29,6 @@
DEFAULT_DEBUG_CHANNEL(reg);
/* Ansi->Unicode conversion without string delimiters */
static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n )
{
LPWSTR p = dst;
while (n-- > 0) *p++ = (WCHAR)*src++;
return dst;
}
/* Unicode->Ansi conversion without string delimiters */
static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n )
{
@ -104,29 +96,23 @@ DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR cl
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
debugstr_w(class), options, access, sa, retkey, dispos );
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW, classW;
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
RtlInitUnicodeString( &classW, class );
return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0,
&classW, options, dispos ) );
}
@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
debugstr_a(class), options, access, sa, retkey, dispos );
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW, classW;
ANSI_STRING nameA, classA;
NTSTATUS status;
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynAtoW( req->class, class ? class : "",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitAnsiString( &nameA, name );
RtlInitAnsiString( &classA, class );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
{
status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos );
RtlFreeUnicodeString( &classW );
}
RtlFreeUnicodeString( &nameW );
}
return ret;
return RtlNtStatusToDosError( status );
}
@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
*/
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
if (!retkey) return ERROR_INVALID_PARAMETER;
*retkey = 0;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
}
@ -231,20 +219,26 @@ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM acce
*/
DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
if (!retkey) return ERROR_INVALID_PARAMETER;
*retkey = 0;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtOpenKey( retkey, access, &attr );
RtlFreeUnicodeString( &nameW );
}
return RtlNtStatusToDosError( status );
}
@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
*/
DWORD WINAPI RegCloseKey( HKEY hkey )
{
struct close_key_request *req = get_req_buffer();
TRACE( "(0x%x)\n", hkey );
req->hkey = hkey;
return reg_server_call( REQ_CLOSE_KEY );
if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS;
return RtlNtStatusToDosError( NtClose( hkey ) );
}
@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey )
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return reg_server_call( REQ_DELETE_KEY );
if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp )))
{
ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
RegCloseKey( tmp );
}
return ret;
}
@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return reg_server_call( REQ_DELETE_KEY );
if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
{
ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
RegCloseKey( tmp );
}
return ret;
}
@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
if (count && is_string(type))
{
LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */
@ -584,24 +572,8 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
count += sizeof(WCHAR);
}
req->hkey = hkey;
req->type = type;
req->total = count;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
max = server_remaining( req->data );
pos = 0;
while (pos < count)
{
unsigned int len = count - pos;
if (len > max) len = max;
req->offset = pos;
req->len = len;
memcpy( req->data, data + pos, len );
if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
pos += len;
}
return ret;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
}
@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
* RegSetValueExA [ADVAPI32.169]
*/
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
CONST BYTE *data, DWORD count )
CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
UNICODE_STRING nameW;
ANSI_STRING nameA;
WCHAR *dataW = NULL;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
if (count && is_string(type))
{
/* if user forgot to count terminating null, add it (yes NT does this) */
if (data[count-1] && !data[count]) count++;
}
if (is_string( type )) /* need to convert to Unicode */
count *= sizeof(WCHAR);
req->hkey = hkey;
req->type = type;
req->total = count;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
max = server_remaining( req->data );
pos = 0;
while (pos < count)
{
unsigned int len = count - pos;
if (len > max) len = max;
req->offset = pos;
req->len = len;
if (is_string( type ))
memcpyAtoW( (LPWSTR)req->data, data + pos/sizeof(WCHAR), len/sizeof(WCHAR) );
else
memcpy( req->data, data + pos, len );
if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
pos += len;
DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 );
if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) )))
return ERROR_OUTOFMEMORY;
MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW );
count = lenW * sizeof(WCHAR);
data = (BYTE *)dataW;
}
return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtSetValueKey( hkey, &nameW, 0, type, data, count );
RtlFreeUnicodeString( &nameW );
}
if (dataW) HeapFree( GetProcessHeap(), 0, dataW );
return RtlNtStatusToDosError( status );
}
@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
LPBYTE data, LPDWORD count )
{
DWORD ret;
struct get_key_value_request *req = get_req_buffer();
NTSTATUS status;
UNICODE_STRING name_str;
DWORD total_size;
char buffer[256];
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
static const int info_size = sizeof(*info) - sizeof(info->Data);
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->offset = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
RtlInitUnicodeString( &name_str, name );
if (data) total_size = min( sizeof(buffer), *count + info_size );
else total_size = info_size;
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buffer, total_size, &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
if (data)
{
if (*count < req->len) ret = ERROR_MORE_DATA;
else
char *buf_ptr = buffer;
/* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
{
/* copy the data */
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
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 );
}
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{
unsigned int len = min( req->len - pos, max );
memcpy( data + pos, req->data, len );
if ((pos += len) >= req->len) break;
req->offset = pos;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
}
}
/* 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 (req->len && is_string(req->type) &&
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
}
if (type) *type = req->type;
if (count) *count = req->len;
return ret;
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
}
@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
* the documentation is wrong: if the buffer is to small it remains untouched
*/
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
LPBYTE data, LPDWORD count )
{
DWORD ret, total_len;
struct get_key_value_request *req = get_req_buffer();
NTSTATUS status;
ANSI_STRING nameA;
UNICODE_STRING nameW;
DWORD total_size;
char buffer[256];
KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
static const int info_size = sizeof(*info) - sizeof(info->Data);
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->offset = 0;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len;
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buffer, sizeof(buffer), &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
if (data)
/* 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 (data || is_string(info->Type))
{
if (*count < total_len) ret = ERROR_MORE_DATA;
else
char *buf_ptr = buffer;
/* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW)
{
/* copy the data */
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
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 );
}
if (!status)
{
if (is_string(info->Type))
{
unsigned int len = min( req->len - pos, max );
if (is_string( req->type ))
memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) );
else
memcpy( data + pos, req->data, len );
if ((pos += len) >= req->len) break;
req->offset = pos;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
NULL, 0, NULL, NULL );
if (data && len)
{
if (len > *count) status = STATUS_BUFFER_OVERFLOW;
else
{
WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
data, len, NULL, NULL );
/* 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;
}
}
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 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_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
data[total_len] = 0;
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
}
if (count) *count = total_len;
if (type) *type = req->type;
return ret;
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
RtlFreeUnicodeString( &nameW );
done:
return RtlNtStatusToDosError(status);
}
@ -1011,14 +1023,9 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou
*/
DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
return reg_server_call( REQ_DELETE_KEY_VALUE );
UNICODE_STRING nameW;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
}
@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
*/
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
UNICODE_STRING nameW;
STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
return reg_server_call( REQ_DELETE_KEY_VALUE );
RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{
status = NtDeleteValueKey( hkey, &nameW );
RtlFreeUnicodeString( &nameW );
}
return RtlNtStatusToDosError( status );
}

View File

@ -286,51 +286,66 @@ static void key_destroy( struct object *obj )
/* duplicate a key path from the request buffer */
/* returns a pointer to a static buffer, so only useable once per request */
static WCHAR *copy_path( const path_t path )
static WCHAR *copy_path( const WCHAR *path, size_t len )
{
static WCHAR buffer[MAX_PATH+1];
WCHAR *p = buffer;
while (p < buffer + sizeof(buffer) - 1) if (!(*p++ = *path++)) break;
*p = 0;
if (len > sizeof(buffer)-sizeof(buffer[0]))
{
set_error( STATUS_BUFFER_OVERFLOW );
return NULL;
}
memcpy( buffer, path, len );
buffer[len / sizeof(WCHAR)] = 0;
return buffer;
}
/* copy a path from the request buffer, in cases where the length is stored in front of the path */
static WCHAR *copy_req_path( void *req, size_t *len )
{
const WCHAR *name_ptr = get_req_data(req);
if ((*len = sizeof(WCHAR) + *name_ptr++) > get_req_data_size(req))
{
fatal_protocol_error( current, "copy_req_path: invalid length %d/%d\n",
*len, get_req_data_size(req) );
return NULL;
}
return copy_path( name_ptr, *len - sizeof(WCHAR) );
}
/* return the next token in a given path */
/* returns a pointer to a static buffer, so only useable once per request */
static WCHAR *get_path_token( const WCHAR *initpath, size_t maxlen )
static WCHAR *get_path_token( WCHAR *initpath )
{
static const WCHAR *path;
static const WCHAR *end;
static WCHAR buffer[MAX_PATH+1];
WCHAR *p = buffer;
static WCHAR *path;
WCHAR *ret;
if (initpath)
{
/* path cannot start with a backslash */
if (*initpath == '\\')
{
set_error( STATUS_OBJECT_PATH_INVALID );
return NULL;
}
path = initpath;
end = path + maxlen / sizeof(WCHAR);
}
while ((path < end) && (*path == '\\')) path++;
while ((path < end) && (p < buffer + sizeof(buffer) - 1))
{
WCHAR ch = *path;
if (!ch || (ch == '\\')) break;
*p++ = ch;
path++;
}
*p = 0;
return buffer;
else while (*path == '\\') path++;
ret = path;
while (*path && *path != '\\') path++;
if (*path) *path++ = 0;
return ret;
}
/* duplicate a Unicode string from the request buffer */
static WCHAR *req_strdupW( const void *req, const WCHAR *str )
static WCHAR *req_strdupW( const void *req, const WCHAR *str, size_t len )
{
WCHAR *name;
size_t len = get_req_strlenW( req, str );
if ((name = mem_alloc( (len + 1) * sizeof(WCHAR) )) != NULL)
if ((name = mem_alloc( len + sizeof(WCHAR) )) != NULL)
{
memcpy( name, str, len * sizeof(WCHAR) );
name[len] = 0;
memcpy( name, str, len );
name[len / sizeof(WCHAR)] = 0;
}
return name;
}
@ -466,12 +481,13 @@ static struct key *find_subkey( struct key *key, const WCHAR *name, int *index )
}
/* open a subkey */
static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen )
/* warning: the key name must be writeable (use copy_path) */
static struct key *open_key( struct key *key, WCHAR *name )
{
int index;
WCHAR *path;
path = get_path_token( name, maxlen );
if (!(path = get_path_token( name ))) return NULL;
while (*path)
{
if (!(key = find_subkey( key, path, &index )))
@ -479,7 +495,7 @@ static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen )
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
break;
}
path = get_path_token( NULL, 0 );
path = get_path_token( NULL );
}
if (debug_level > 1) dump_operation( key, NULL, "Open" );
@ -488,7 +504,8 @@ static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen )
}
/* create a subkey */
static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen, WCHAR *class,
/* warning: the key name must be writeable (use copy_path) */
static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
unsigned int options, time_t modif, int *created )
{
struct key *base;
@ -508,14 +525,14 @@ static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen
}
if (!modif) modif = time(NULL);
path = get_path_token( name, maxlen );
if (!(path = get_path_token( name ))) return NULL;
*created = 0;
while (*path)
{
struct key *subkey;
if (!(subkey = find_subkey( key, path, &index ))) break;
key = subkey;
path = get_path_token( NULL, 0 );
path = get_path_token( NULL );
}
/* create the remaining part */
@ -528,7 +545,7 @@ static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen
while (key)
{
key->flags |= flags;
path = get_path_token( NULL, 0 );
path = get_path_token( NULL );
if (!*path) goto done;
/* we know the index is always 0 in a new key */
key = alloc_subkey( key, path, 0, modif );
@ -597,40 +614,25 @@ static void query_key( struct key *key, struct query_key_info_request *req )
}
/* delete a key and its values */
static void delete_key( struct key *key, const WCHAR *name, size_t maxlen )
static void delete_key( struct key *key )
{
int index;
struct key *parent;
WCHAR *path;
path = get_path_token( name, maxlen );
if (!*path)
/* must find parent and index */
if (key->flags & KEY_ROOT)
{
/* deleting this key, must find parent and index */
if (key->flags & KEY_ROOT)
{
set_error( STATUS_ACCESS_DENIED );
return;
}
if (!(parent = key->parent) || (key->flags & KEY_DELETED))
{
set_error( STATUS_KEY_DELETED );
return;
}
for (index = 0; index <= parent->last_subkey; index++)
if (parent->subkeys[index] == key) break;
assert( index <= parent->last_subkey );
set_error( STATUS_ACCESS_DENIED );
return;
}
else while (*path)
if (!(parent = key->parent) || (key->flags & KEY_DELETED))
{
parent = key;
if (!(key = find_subkey( parent, path, &index )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return;
}
path = get_path_token( NULL, 0 );
set_error( STATUS_KEY_DELETED );
return;
}
for (index = 0; index <= parent->last_subkey; index++)
if (parent->subkeys[index] == key) break;
assert( index <= parent->last_subkey );
/* we can only delete a key that has no subkeys (FIXME) */
if ((key->flags & KEY_ROOT) || (key->last_subkey >= 0))
@ -716,7 +718,7 @@ static struct key_value *insert_value( struct key *key, const WCHAR *name )
/* set a key value */
static void set_value( struct key *key, WCHAR *name, int type, unsigned int total_len,
unsigned int offset, unsigned int data_len, void *data )
unsigned int offset, unsigned int data_len, const void *data )
{
struct key_value *value;
void *ptr = NULL;
@ -767,11 +769,12 @@ static void set_value( struct key *key, WCHAR *name, int type, unsigned int tota
}
/* get a key value */
static void get_value( struct key *key, WCHAR *name, unsigned int offset,
unsigned int maxlen, int *type, int *len, void *data )
static size_t get_value( struct key *key, WCHAR *name, unsigned int offset,
unsigned int maxlen, int *type, int *len, void *data )
{
struct key_value *value;
int index;
size_t ret = 0;
if ((value = find_value( key, name, &index )))
{
@ -781,6 +784,7 @@ static void get_value( struct key *key, WCHAR *name, unsigned int offset,
{
if (maxlen > value->len - offset) maxlen = value->len - offset;
memcpy( data, (char *)value->data + offset, maxlen );
ret = maxlen;
}
if (debug_level > 1) dump_operation( key, value, "Get" );
}
@ -789,6 +793,7 @@ static void get_value( struct key *key, WCHAR *name, unsigned int offset,
*type = -1;
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
}
return ret;
}
/* enumerate a key value */
@ -871,7 +876,7 @@ static struct key *create_root_key( int hkey )
}
keyname[i++] = 0;
if ((key = create_key( root_key, keyname, i*sizeof(WCHAR), NULL, 0, time(NULL), &dummy )))
if ((key = create_key( root_key, keyname, NULL, 0, time(NULL), &dummy )))
{
special_root_keys[hkey - HKEY_SPECIAL_ROOT_FIRST] = key;
key->flags |= KEY_ROOT;
@ -1047,7 +1052,7 @@ static int get_data_type( const char *buffer, int *type, int *parse_type )
static struct key *load_key( struct key *base, const char *buffer, unsigned int options,
int prefix_len, struct file_load_info *info )
{
WCHAR *p;
WCHAR *p, *name;
int res, len, modif;
len = strlen(buffer) * sizeof(WCHAR);
@ -1073,7 +1078,12 @@ static struct key *load_key( struct key *base, const char *buffer, unsigned int
/* empty key name, return base key */
return (struct key *)grab_object( base );
}
return create_key( base, p, len - ((char *)p - info->tmp), NULL, options, modif, &res );
if (!(name = copy_path( p, len - ((char *)p - info->tmp) )))
{
file_read_error( "Key is too long", info );
return NULL;
}
return create_key( base, name, NULL, options, modif, &res );
}
/* parse a comma-separated list of hex digits */
@ -1325,7 +1335,7 @@ void init_registry(void)
int dummy;
/* create the config key */
if (!(key = create_key( root_key, config_name, sizeof(config_name),
if (!(key = create_key( root_key, copy_path( config_name, sizeof(config_name) ),
NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create config key\n" );
key->flags |= KEY_VOLATILE;
@ -1520,23 +1530,37 @@ void close_registry(void)
/* create a registry key */
DECL_HANDLER(create_key)
{
struct key *key, *parent;
WCHAR *class;
struct key *key = NULL, *parent;
unsigned int access = req->access;
WCHAR *name, *class;
size_t len;
if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */
req->hkey = -1;
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
{
if ((class = req_strdupW( req, req->class )))
if ((name = copy_req_path( req, &len )))
{
if ((key = create_key( parent, req->name, sizeof(req->name), class, req->options,
req->modif, &req->created )))
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);
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)
{
req->hkey = alloc_handle( current->process, key, access, 0 );
release_object( key );
}
free( class );
}
release_object( parent );
}
@ -1552,7 +1576,8 @@ DECL_HANDLER(open_key)
req->hkey = -1;
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
{
if ((key = open_key( parent, req->name, sizeof(req->name) )))
WCHAR *name = copy_path( get_req_data(req), get_req_data_size(req) );
if (name && (key = open_key( parent, name )))
{
req->hkey = alloc_handle( current->process, key, access, 0 );
release_object( key );
@ -1568,19 +1593,11 @@ DECL_HANDLER(delete_key)
if ((key = get_hkey_obj( req->hkey, 0 /*FIXME*/ )))
{
delete_key( key, req->name, sizeof(req->name) );
delete_key( key );
release_object( key );
}
}
/* close a registry key */
DECL_HANDLER(close_key)
{
int hkey = req->hkey;
/* ignore attempts to close a root key */
if (hkey && !IS_SPECIAL_ROOT_HKEY(hkey)) close_handle( current->process, hkey );
}
/* enumerate registry subkeys */
DECL_HANDLER(enum_key)
{
@ -1611,14 +1628,18 @@ DECL_HANDLER(query_key_info)
DECL_HANDLER(set_key_value)
{
struct key *key;
unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) );
unsigned int datalen = req->len;
WCHAR *name;
size_t len;
if (datalen > max) datalen = max;
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
{
set_value( key, copy_path( req->name ), req->type, req->total,
req->offset, datalen, req->data );
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;
set_value( key, name, req->type, req->total, req->offset, datalen, data );
}
release_object( key );
}
}
@ -1627,13 +1648,18 @@ DECL_HANDLER(set_key_value)
DECL_HANDLER(get_key_value)
{
struct key *key;
unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) );
WCHAR *name;
size_t len;
req->len = 0;
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
{
get_value( key, copy_path( req->name ), req->offset, max,
&req->type, &req->len, req->data );
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 );
}
release_object( key );
}
}
@ -1662,7 +1688,7 @@ DECL_HANDLER(delete_key_value)
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
{
if ((name = req_strdupW( req, req->name )))
if ((name = req_strdupW( req, get_req_data(req), get_req_data_size(req) )))
{
delete_value( key, name );
free( name );

View File

@ -175,7 +175,6 @@ DECL_HANDLER(write_process_memory);
DECL_HANDLER(create_key);
DECL_HANDLER(open_key);
DECL_HANDLER(delete_key);
DECL_HANDLER(close_key);
DECL_HANDLER(enum_key);
DECL_HANDLER(query_key_info);
DECL_HANDLER(set_key_value);
@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_create_key,
(req_handler)req_open_key,
(req_handler)req_delete_key,
(req_handler)req_close_key,
(req_handler)req_enum_key,
(req_handler)req_query_key_info,
(req_handler)req_set_key_value,

View File

@ -15,9 +15,20 @@
#include "request.h"
#include "unicode.h"
static int cur_pos;
/* utility functions */
static const void *get_data( const void *req )
{
return (char *)get_req_data(req) + cur_pos;
}
static size_t get_size( const void *req )
{
return get_req_data_size(req) - cur_pos;
}
static void dump_uints( const int *ptr, int len )
{
fputc( '{', stderr );
@ -59,63 +70,8 @@ static void dump_path_t( const void *req, const path_t *path )
dump_unicode_string( req, *path );
}
static void dump_exc_record( const EXCEPTION_RECORD *rec )
static void dump_context( const CONTEXT *context )
{
int i;
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++)
{
if (i) fputc( ',', stderr );
fprintf( stderr, "%lx", rec->ExceptionInformation[i] );
}
fputc( '}', stderr );
}
static void dump_varargs_ints( const void *ptr, size_t len )
{
const int *data = ptr;
len /= sizeof(*data);
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%d", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
}
static void dump_varargs_ptrs( const void *ptr, size_t len )
{
void * const *data = ptr;
len /= sizeof(*data);
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%p", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
}
static void dump_varargs_string( const void *ptr, size_t len )
{
fprintf( stderr, "\"%.*s\"", (int)len, (char *)ptr );
}
static void dump_varargs_unicode_str( const void *ptr, size_t len )
{
fprintf( stderr, "L\"" );
dump_strW( ptr, len / sizeof(WCHAR), stderr, "\"\"" );
fputc( '\"', stderr );
}
static void dump_varargs_context( const void *ptr, size_t len )
{
const CONTEXT *context = ptr;
#ifdef __i386__
fprintf( stderr, "{flags=%08lx,eax=%08lx,ebx=%08lx,ecx=%08lx,edx=%08lx,esi=%08lx,edi=%08lx,"
"ebp=%08lx,eip=%08lx,esp=%08lx,eflags=%08lx,cs=%04lx,ds=%04lx,es=%04lx,"
@ -132,23 +88,115 @@ static void dump_varargs_context( const void *ptr, size_t len )
#endif
}
static void dump_varargs_exc_event( const void *ptr, size_t len )
static void dump_exc_record( const EXCEPTION_RECORD *rec )
{
fprintf( stderr, "{context=" );
dump_varargs_context( ptr, sizeof(CONTEXT) );
fprintf( stderr, ",rec=" );
dump_exc_record( (EXCEPTION_RECORD *)((CONTEXT *)ptr + 1) );
int i;
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++)
{
if (i) fputc( ',', stderr );
fprintf( stderr, "%lx", rec->ExceptionInformation[i] );
}
fputc( '}', stderr );
}
static void dump_varargs_debug_event( const void *ptr, size_t len )
static size_t dump_varargs_ints( const void *req )
{
const debug_event_t *event = ptr;
const int *data = get_data(req);
size_t len = get_size(req) / sizeof(*data);
if (!len)
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%d", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
return get_size(req);
}
static size_t dump_varargs_ptrs( const void *req )
{
void * const *data = get_data(req);
size_t len = get_size(req) / sizeof(*data);
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%p", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
return get_size(req);
}
static size_t dump_varargs_bytes( const void *req )
{
const unsigned char *data = get_data(req);
size_t len = get_size(req);
fputc( '{', stderr );
while (len > 0)
{
fprintf( stderr, "%02x", *data++ );
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
return get_size(req);
}
static size_t dump_varargs_string( const void *req )
{
fprintf( stderr, "\"%.*s\"", (int)get_size(req), (char *)get_data(req) );
return get_size(req);
}
static size_t dump_varargs_unicode_len_str( const void *req )
{
const WCHAR *str = get_data(req);
WCHAR len = *str++;
len = min( len, get_size(req) );
fprintf( stderr, "L\"" );
dump_strW( str, len / sizeof(WCHAR), stderr, "\"\"" );
fputc( '\"', stderr );
return len + sizeof(WCHAR);
}
static size_t dump_varargs_unicode_str( const void *req )
{
fprintf( stderr, "L\"" );
dump_strW( get_data(req), get_size(req) / sizeof(WCHAR), stderr, "\"\"" );
fputc( '\"', stderr );
return get_size(req);
}
static size_t dump_varargs_context( const void *req )
{
dump_context( get_data(req) );
return get_size(req);
}
static size_t dump_varargs_exc_event( const void *req )
{
const CONTEXT *ptr = get_data(req);
fprintf( stderr, "{context=" );
dump_context( ptr );
fprintf( stderr, ",rec=" );
dump_exc_record( (EXCEPTION_RECORD *)(ptr + 1) );
fputc( '}', stderr );
return get_size(req);
}
static size_t dump_varargs_debug_event( const void *req )
{
const debug_event_t *event = get_data(req);
if (!get_size(req))
{
fprintf( stderr, "{}" );
return;
return 0;
}
switch(event->code)
{
@ -202,12 +250,13 @@ static void dump_varargs_debug_event( const void *ptr, size_t len )
fprintf( stderr, "{code=??? (%d)}", event->code );
break;
}
return get_size(req);
}
static void dump_varargs_input_records( const void *ptr, size_t len )
static size_t dump_varargs_input_records( const void *req )
{
const INPUT_RECORD *rec = ptr;
len /= sizeof(*rec);
const INPUT_RECORD *rec = get_data(req);
size_t len = get_size(req) / sizeof(*rec);
fputc( '{', stderr );
while (len > 0)
@ -217,6 +266,7 @@ static void dump_varargs_input_records( const void *ptr, size_t len )
if (--len) fputc( ',', stderr );
}
fputc( '}', stderr );
return get_size(req);
}
/* dumping for functions for requests that have a variable part */
@ -233,18 +283,6 @@ static void dump_varargs_write_process_memory_request( const struct write_proces
dump_bytes( (unsigned char *)req->data, count * sizeof(int) );
}
static void dump_varargs_set_key_value_request( const struct set_key_value_request *req )
{
int count = min( req->len, get_req_size( req, req->data, 1 ));
dump_bytes( req->data, count );
}
static void dump_varargs_get_key_value_reply( const struct get_key_value_request *req )
{
int count = min( req->len - req->offset, get_req_size( req, req->data, 1 ));
dump_bytes( req->data, count );
}
static void dump_varargs_enum_key_value_reply( const struct enum_key_value_request *req )
{
int count = min( req->len - req->offset, get_req_size( req, req->data, 1 ));
@ -268,7 +306,7 @@ static void dump_new_process_request( const struct new_process_request *req )
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " alloc_fd=%d,", req->alloc_fd );
fprintf( stderr, " filename=" );
dump_varargs_string( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_string( req );
}
static void dump_wait_process_request( const struct wait_process_request *req )
@ -322,7 +360,7 @@ static void dump_init_process_reply( const struct init_process_request *req )
fprintf( stderr, " hstderr=%d,", req->hstderr );
fprintf( stderr, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " filename=" );
dump_varargs_string( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_string( req );
}
static void dump_init_process_done_request( const struct init_process_done_request *req )
@ -475,7 +513,7 @@ static void dump_get_apc_reply( const struct get_apc_request *req )
fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " args=" );
dump_varargs_ptrs( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_ptrs( req );
}
static void dump_close_handle_request( const struct close_handle_request *req )
@ -532,7 +570,7 @@ static void dump_select_request( const struct select_request *req )
fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " timeout=%d,", req->timeout );
fprintf( stderr, " handles=" );
dump_varargs_ints( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_ints( req );
}
static void dump_select_reply( const struct select_request *req )
@ -546,7 +584,7 @@ static void dump_create_event_request( const struct create_event_request *req )
fprintf( stderr, " initial_state=%d,", req->initial_state );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_create_event_reply( const struct create_event_request *req )
@ -565,7 +603,7 @@ static void dump_open_event_request( const struct open_event_request *req )
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_event_reply( const struct open_event_request *req )
@ -578,7 +616,7 @@ static void dump_create_mutex_request( const struct create_mutex_request *req )
fprintf( stderr, " owned=%d,", req->owned );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_create_mutex_reply( const struct create_mutex_request *req )
@ -596,7 +634,7 @@ static void dump_open_mutex_request( const struct open_mutex_request *req )
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_mutex_reply( const struct open_mutex_request *req )
@ -610,7 +648,7 @@ static void dump_create_semaphore_request( const struct create_semaphore_request
fprintf( stderr, " max=%08x,", req->max );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_create_semaphore_reply( const struct create_semaphore_request *req )
@ -634,7 +672,7 @@ static void dump_open_semaphore_request( const struct open_semaphore_request *re
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_semaphore_reply( const struct open_semaphore_request *req )
@ -650,7 +688,7 @@ static void dump_create_file_request( const struct create_file_request *req )
fprintf( stderr, " create=%d,", req->create );
fprintf( stderr, " attrs=%08x,", req->attrs );
fprintf( stderr, " filename=" );
dump_varargs_string( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_string( req );
}
static void dump_create_file_reply( const struct create_file_request *req )
@ -804,7 +842,7 @@ static void dump_get_socket_event_reply( const struct get_socket_event_request *
fprintf( stderr, " pmask=%08x,", req->pmask );
fprintf( stderr, " state=%08x,", req->state );
fprintf( stderr, " errors=" );
dump_varargs_ints( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_ints( req );
}
static void dump_enable_socket_event_request( const struct enable_socket_event_request *req )
@ -873,7 +911,7 @@ static void dump_set_console_info_request( const struct set_console_info_request
fprintf( stderr, " cursor_size=%d,", req->cursor_size );
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
fprintf( stderr, " title=" );
dump_varargs_string( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_string( req );
}
static void dump_get_console_info_request( const struct get_console_info_request *req )
@ -887,14 +925,14 @@ static void dump_get_console_info_reply( const struct get_console_info_request *
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
fprintf( stderr, " pid=%d,", req->pid );
fprintf( stderr, " title=" );
dump_varargs_string( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_string( req );
}
static void dump_write_console_input_request( const struct write_console_input_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " rec=" );
dump_varargs_input_records( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_input_records( req );
}
static void dump_write_console_input_reply( const struct write_console_input_request *req )
@ -912,7 +950,7 @@ static void dump_read_console_input_reply( const struct read_console_input_reque
{
fprintf( stderr, " read=%d,", req->read );
fprintf( stderr, " rec=" );
dump_varargs_input_records( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_input_records( req );
}
static void dump_create_change_notification_request( const struct create_change_notification_request *req )
@ -934,7 +972,7 @@ static void dump_create_mapping_request( const struct create_mapping_request *re
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " file_handle=%d,", req->file_handle );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_create_mapping_reply( const struct create_mapping_request *req )
@ -947,7 +985,7 @@ static void dump_open_mapping_request( const struct open_mapping_request *req )
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_mapping_reply( const struct open_mapping_request *req )
@ -1046,21 +1084,21 @@ static void dump_wait_debug_event_reply( const struct wait_debug_event_request *
fprintf( stderr, " pid=%p,", req->pid );
fprintf( stderr, " tid=%p,", req->tid );
fprintf( stderr, " event=" );
dump_varargs_debug_event( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_debug_event( req );
}
static void dump_exception_event_request( const struct exception_event_request *req )
{
fprintf( stderr, " first=%d,", req->first );
fprintf( stderr, " record=" );
dump_varargs_exc_event( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_exc_event( req );
}
static void dump_exception_event_reply( const struct exception_event_request *req )
{
fprintf( stderr, " status=%d,", req->status );
fprintf( stderr, " context=" );
dump_varargs_context( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_context( req );
}
static void dump_output_debug_string_request( const struct output_debug_string_request *req )
@ -1113,10 +1151,10 @@ static void dump_create_key_request( const struct create_key_request *req )
fprintf( stderr, " options=%08x,", req->options );
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_create_key_reply( const struct create_key_request *req )
@ -1130,7 +1168,7 @@ static void dump_open_key_request( const struct open_key_request *req )
fprintf( stderr, " parent=%d,", req->parent );
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " name=" );
dump_path_t( req, &req->name );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_key_reply( const struct open_key_request *req )
@ -1139,13 +1177,6 @@ static void dump_open_key_reply( const struct open_key_request *req )
}
static void dump_delete_key_request( const struct delete_key_request *req )
{
fprintf( stderr, " hkey=%d,", req->hkey );
fprintf( stderr, " name=" );
dump_path_t( req, &req->name );
}
static void dump_close_key_request( const struct close_key_request *req )
{
fprintf( stderr, " hkey=%d", req->hkey );
}
@ -1193,12 +1224,11 @@ static void dump_set_key_value_request( const struct set_key_value_request *req
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " total=%08x,", req->total );
fprintf( stderr, " offset=%08x,", req->offset );
fprintf( stderr, " len=%08x,", req->len );
fprintf( stderr, " name=" );
dump_path_t( req, &req->name );
fprintf( stderr, "," );
cur_pos += dump_varargs_unicode_len_str( req );
fputc( ',', stderr );
fprintf( stderr, " data=" );
dump_varargs_set_key_value_request( req );
cur_pos += dump_varargs_bytes( req );
}
static void dump_get_key_value_request( const struct get_key_value_request *req )
@ -1206,7 +1236,7 @@ static void dump_get_key_value_request( const struct get_key_value_request *req
fprintf( stderr, " hkey=%d,", req->hkey );
fprintf( stderr, " offset=%08x,", req->offset );
fprintf( stderr, " name=" );
dump_unicode_string( req, req->name );
cur_pos += dump_varargs_unicode_len_str( req );
}
static void dump_get_key_value_reply( const struct get_key_value_request *req )
@ -1214,7 +1244,7 @@ static void dump_get_key_value_reply( const struct get_key_value_request *req )
fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " len=%d,", req->len );
fprintf( stderr, " data=" );
dump_varargs_get_key_value_reply( req );
cur_pos += dump_varargs_bytes( req );
}
static void dump_enum_key_value_request( const struct enum_key_value_request *req )
@ -1239,7 +1269,7 @@ static void dump_delete_key_value_request( const struct delete_key_value_request
{
fprintf( stderr, " hkey=%d,", req->hkey );
fprintf( stderr, " name=" );
dump_path_t( req, &req->name );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_load_registry_request( const struct load_registry_request *req )
@ -1275,7 +1305,7 @@ static void dump_create_timer_request( const struct create_timer_request *req )
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " manual=%d,", req->manual );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_create_timer_reply( const struct create_timer_request *req )
@ -1288,7 +1318,7 @@ static void dump_open_timer_request( const struct open_timer_request *req )
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_open_timer_reply( const struct open_timer_request *req )
@ -1320,7 +1350,7 @@ static void dump_get_thread_context_request( const struct get_thread_context_req
static void dump_get_thread_context_reply( const struct get_thread_context_request *req )
{
fprintf( stderr, " context=" );
dump_varargs_context( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_context( req );
}
static void dump_set_thread_context_request( const struct set_thread_context_request *req )
@ -1328,7 +1358,7 @@ static void dump_set_thread_context_request( const struct set_thread_context_req
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " context=" );
dump_varargs_context( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_context( req );
}
static void dump_get_selector_entry_request( const struct get_selector_entry_request *req )
@ -1348,7 +1378,7 @@ static void dump_add_atom_request( const struct add_atom_request *req )
{
fprintf( stderr, " local=%d,", req->local );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_add_atom_reply( const struct add_atom_request *req )
@ -1366,7 +1396,7 @@ static void dump_find_atom_request( const struct find_atom_request *req )
{
fprintf( stderr, " local=%d,", req->local );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_find_atom_reply( const struct find_atom_request *req )
@ -1384,7 +1414,7 @@ static void dump_get_atom_name_reply( const struct get_atom_name_request *req )
{
fprintf( stderr, " count=%d,", req->count );
fprintf( stderr, " name=" );
dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) );
cur_pos += dump_varargs_unicode_str( req );
}
static void dump_init_atom_table_request( const struct init_atom_table_request *req )
@ -1543,7 +1573,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_key_request,
(dump_func)dump_open_key_request,
(dump_func)dump_delete_key_request,
(dump_func)dump_close_key_request,
(dump_func)dump_enum_key_request,
(dump_func)dump_query_key_info_request,
(dump_func)dump_set_key_value_request,
@ -1656,7 +1685,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_create_key_reply,
(dump_func)dump_open_key_reply,
(dump_func)0,
(dump_func)0,
(dump_func)dump_enum_key_reply,
(dump_func)dump_query_key_info_reply,
(dump_func)0,
@ -1769,7 +1797,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_key",
"open_key",
"delete_key",
"close_key",
"enum_key",
"query_key_info",
"set_key_value",
@ -1805,10 +1832,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
void trace_request( enum request req )
{
cur_pos = 0;
current->last_req = req;
if (req < REQ_NB_REQUESTS)
{
fprintf( stderr, "%08x: %s(", (unsigned int)current, req_names[req] );
cur_pos = 0;
req_dumpers[req]( current->buffer );
}
else
@ -1824,8 +1853,9 @@ void trace_reply( struct thread *thread )
if (reply_dumpers[thread->last_req])
{
fprintf( stderr, " {" );
cur_pos = 0;
reply_dumpers[thread->last_req]( thread->buffer );
fprintf( stderr, " }" );
fprintf( stderr, " }" );
}
if (thread->pass_fd != -1) fprintf( stderr, " fd=%d\n", thread->pass_fd );
else fprintf( stderr, "\n" );

View File

@ -179,7 +179,8 @@ sub DO_DUMP_FUNC
{
my $func = $1;
push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
push @trace_lines, " $func( get_req_data(req), get_req_data_size(req) );\n";
push @trace_lines, " cur_pos += $func( req );\n";
push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0);
}
else
{