Converted some of the registry server requests to the new request

mechanism.
oldstable
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); 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 */ /* Unicode->Ansi conversion without string delimiters */
static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n ) 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, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos ) LPHKEY retkey, LPDWORD dispos )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct create_key_request *req = get_req_buffer(); UNICODE_STRING nameW, classW;
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 );
if (reserved) return ERROR_INVALID_PARAMETER; if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey; attr.Length = sizeof(attr);
req->access = access; attr.RootDirectory = hkey;
req->options = options; attr.ObjectName = &nameW;
req->modif = time(NULL); attr.Attributes = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; attr.SecurityDescriptor = NULL;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; attr.SecurityQualityOfService = NULL;
lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0", RtlInitUnicodeString( &nameW, name );
server_remaining(req->class) / sizeof(WCHAR) ); RtlInitUnicodeString( &classW, class );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{ return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0,
*retkey = req->hkey; &classW, options, dispos ) );
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
} }
@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos ) LPHKEY retkey, LPDWORD dispos )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct create_key_request *req = get_req_buffer(); UNICODE_STRING nameW, classW;
ANSI_STRING nameA, classA;
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved, NTSTATUS status;
debugstr_a(class), options, access, sa, retkey, dispos );
if (reserved) return ERROR_INVALID_PARAMETER; if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey; attr.Length = sizeof(attr);
req->access = access; attr.RootDirectory = hkey;
req->options = options; attr.ObjectName = &nameW;
req->modif = time(NULL); attr.Attributes = 0;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; attr.SecurityDescriptor = NULL;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; attr.SecurityQualityOfService = NULL;
lstrcpynAtoW( req->class, class ? class : "", RtlInitAnsiString( &nameA, name );
server_remaining(req->class) / sizeof(WCHAR) ); RtlInitAnsiString( &classA, class );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{ {
*retkey = req->hkey; if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; {
status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos );
RtlFreeUnicodeString( &classW );
} }
return ret; RtlFreeUnicodeString( &nameW );
}
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 WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct open_key_request *req = get_req_buffer(); UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey ); attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
if (!retkey) return ERROR_INVALID_PARAMETER; attr.ObjectName = &nameW;
*retkey = 0; attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
req->parent = hkey; attr.SecurityQualityOfService = NULL;
req->access = access; RtlInitUnicodeString( &nameW, name );
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
} }
@ -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 WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct open_key_request *req = get_req_buffer(); 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; RtlInitAnsiString( &nameA, name );
*retkey = 0; /* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
req->parent = hkey; {
req->access = access; status = NtOpenKey( retkey, access, &attr );
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; RtlFreeUnicodeString( &nameW );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; }
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; return RtlNtStatusToDosError( status );
return ret;
} }
@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
*/ */
DWORD WINAPI RegCloseKey( HKEY hkey ) DWORD WINAPI RegCloseKey( HKEY hkey )
{ {
struct close_key_request *req = get_req_buffer(); if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS;
TRACE( "(0x%x)\n", hkey ); return RtlNtStatusToDosError( NtClose( hkey ) );
req->hkey = hkey;
return reg_server_call( REQ_CLOSE_KEY );
} }
@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey )
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
{ {
DWORD ret; DWORD ret;
struct delete_key_request *req = get_req_buffer(); HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp )))
req->hkey = hkey; {
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; RegCloseKey( tmp );
return reg_server_call( REQ_DELETE_KEY ); }
return ret;
} }
@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
{ {
DWORD ret; DWORD ret;
struct delete_key_request *req = get_req_buffer(); HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
req->hkey = hkey; {
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; RegCloseKey( tmp );
return reg_server_call( REQ_DELETE_KEY ); }
return ret;
} }
@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count ) DWORD type, CONST BYTE *data, DWORD count )
{ {
DWORD ret; UNICODE_STRING nameW;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count ); if (count && is_string(type))
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{ {
LPCWSTR str = (LPCWSTR)data; LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */ /* 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); count += sizeof(WCHAR);
} }
req->hkey = hkey; RtlInitUnicodeString( &nameW, name );
req->type = type; return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
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;
} }
@ -611,44 +583,36 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
CONST BYTE *data, DWORD count ) CONST BYTE *data, DWORD count )
{ {
DWORD ret; UNICODE_STRING nameW;
struct set_key_value_request *req = get_req_buffer(); ANSI_STRING nameA;
unsigned int max, pos; WCHAR *dataW = NULL;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count ); if (count && is_string(type))
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{ {
/* if user forgot to count terminating null, add it (yes NT does this) */ /* if user forgot to count terminating null, add it (yes NT does this) */
if (data[count-1] && !data[count]) count++; if (data[count-1] && !data[count]) count++;
} }
if (is_string( type )) /* need to convert to Unicode */ 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; DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 );
if (len > max) len = max; if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) )))
req->offset = pos; return ERROR_OUTOFMEMORY;
req->len = len; MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW );
count = lenW * sizeof(WCHAR);
if (is_string( type )) data = (BYTE *)dataW;
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;
} }
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 );
} }
@ -722,45 +686,60 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count ) LPBYTE data, LPDWORD count )
{ {
DWORD ret; NTSTATUS status;
struct get_key_value_request *req = get_req_buffer(); 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", TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 ); hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey; RtlInitUnicodeString( &name_str, name );
req->offset = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; if (data) total_size = min( sizeof(buffer), *count + info_size );
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; 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 (data)
{ {
if (*count < req->len) ret = ERROR_MORE_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 else
{ status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
/* copy the data */ buf_ptr, total_size, &total_size );
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
{
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;
}
} }
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated /* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */ * and there is enough space in the buffer NT appends a \0 */
if (req->len && is_string(req->type) && if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0; {
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
} }
if (type) *type = req->type; }
if (count) *count = req->len; if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
return ret; }
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
} }
@ -773,51 +752,84 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count ) LPBYTE data, LPDWORD count )
{ {
DWORD ret, total_len; NTSTATUS status;
struct get_key_value_request *req = get_req_buffer(); 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", TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey; RtlInitAnsiString( &nameA, name );
req->offset = 0; /* FIXME: should use Unicode buffer in TEB */
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
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; 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 );
}
if (!status)
{
if (is_string(info->Type))
{
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 else
{ {
/* copy the data */ WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
unsigned int max = server_remaining( req->data ); (total_size - info_size) /sizeof(WCHAR),
unsigned int pos = 0; data, len, NULL, NULL );
while (pos < req->len)
{
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;
}
}
/* if the type is REG_SZ and data is not 0-terminated /* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */ * 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]) if (len < *count && data[len-1]) data[len] = 0;
data[total_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 (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
} }
if (count) *count = total_len; if (type) *type = info->Type;
if (type) *type = req->type; if (count) *count = total_size - info_size;
return ret; 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 WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{ {
DWORD ret; UNICODE_STRING nameW;
struct delete_key_value_request *req = get_req_buffer(); RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
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 );
} }
@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
*/ */
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
{ {
DWORD ret; UNICODE_STRING nameW;
struct delete_key_value_request *req = get_req_buffer(); STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
req->hkey = hkey; if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; {
return reg_server_call( REQ_DELETE_KEY_VALUE ); 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: * NOTES:
* HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
@ -26,21 +29,8 @@ static const UNICODE_STRING root_path =
(LPWSTR)root_name /* Buffer */ (LPWSTR)root_name /* Buffer */
}; };
/* copy a key name into the request buffer */ /* maximum length of a key/value name in bytes (without terminating null) */
static NTSTATUS copy_key_name( LPWSTR dest, const UNICODE_STRING *name ) #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
{
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;
}
/* copy a key name into the request buffer */ /* 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, ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
PULONG dispos ) PULONG dispos )
{ {
struct create_key_request *req = get_req_buffer();
NTSTATUS ret; NTSTATUS ret;
DWORD len = attr->ObjectName->Length;
TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
debugstr_us(class), options, access, retkey ); debugstr_us(class), options, access, retkey );
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
len += sizeof(WCHAR); /* for storing name length */
if (class)
{
len += class->Length;
if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
}
if (!retkey) return STATUS_INVALID_PARAMETER; if (!retkey) return STATUS_INVALID_PARAMETER;
SERVER_START_REQ
{
struct create_key_request *req = server_alloc_req( sizeof(*req), len );
WCHAR *data = server_data_ptr(req);
req->parent = attr->RootDirectory; req->parent = attr->RootDirectory;
req->access = access; req->access = access;
req->options = options; req->options = options;
req->modif = 0; req->modif = 0;
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret; *data++ = attr->ObjectName->Length;
req->class[0] = 0; memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
if (class) if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
{
if ((ret = copy_nameU( req->class, class, server_remaining(req->class) ))) return ret;
}
if (!(ret = server_call_noerr( REQ_CREATE_KEY ))) if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
{ {
*retkey = req->hkey; *retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
} }
}
SERVER_END_REQ;
return ret; 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 ) NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
{ {
struct open_key_request *req = get_req_buffer();
NTSTATUS ret; NTSTATUS ret;
DWORD len = attr->ObjectName->Length;
TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory, TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
debugstr_us(attr->ObjectName), access, retkey ); debugstr_us(attr->ObjectName), access, retkey );
if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
if (!retkey) return STATUS_INVALID_PARAMETER; if (!retkey) return STATUS_INVALID_PARAMETER;
*retkey = 0; *retkey = 0;
SERVER_START_REQ
{
struct open_key_request *req = server_alloc_req( sizeof(*req), len );
req->parent = attr->RootDirectory; req->parent = attr->RootDirectory;
req->access = access; req->access = access;
memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey; if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
}
SERVER_END_REQ;
return ret; return ret;
} }
@ -123,12 +128,18 @@ NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTR
*/ */
NTSTATUS WINAPI NtDeleteKey( HANDLE hkey ) NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
{ {
struct delete_key_request *req = get_req_buffer(); NTSTATUS ret;
TRACE( "(%x)\n", hkey ); TRACE( "(%x)\n", hkey );
SERVER_START_REQ
{
struct delete_key_request *req = server_alloc_req( sizeof(*req), 0 );
req->hkey = hkey; req->hkey = hkey;
req->name[0] = 0; ret = server_call_noerr( REQ_DELETE_KEY );
return 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 WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
{ {
NTSTATUS ret; NTSTATUS ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) ); TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
SERVER_START_REQ
{
struct delete_key_value_request *req = server_alloc_req( sizeof(*req), name->Length );
req->hkey = hkey; req->hkey = hkey;
if (!(ret = copy_nameU( req->name, name, MAX_PATH ))) memcpy( server_data_ptr(req), name->Buffer, name->Length );
ret = server_call_noerr( REQ_DELETE_KEY_VALUE ); ret = server_call_noerr( REQ_DELETE_KEY_VALUE );
}
SERVER_END_REQ;
return ret; return ret;
} }
@ -468,68 +485,111 @@ NTSTATUS WINAPI NtQueryMultipleValueKey(
* NOTES * NOTES
* the name in the KeyValueInformation is never set * the name in the KeyValueInformation is never set
*/ */
NTSTATUS WINAPI NtQueryValueKey( NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
IN HANDLE KeyHandle, KEY_VALUE_INFORMATION_CLASS info_class,
IN PUNICODE_STRING ValueName, void *info, DWORD length, DWORD *result_len )
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
OUT PVOID KeyValueInformation,
IN ULONG Length,
OUT PULONG ResultLength)
{ {
struct get_key_value_request *req = get_req_buffer();
NTSTATUS ret; NTSTATUS ret;
char *data_ptr;
int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n", TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
req->hkey = KeyHandle; if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
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;
switch(KeyValueInformationClass) /* 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;
do
{
size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
reqlen = max( reqlen, name->Length );
SERVER_START_REQ
{
struct get_key_value_request *req = server_alloc_req( sizeof(*req), reqlen );
WCHAR *nameptr = server_data_ptr(req);
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: case KeyValueBasicInformation:
{ {
PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation; KEY_VALUE_BASIC_INFORMATION keyinfo;
kbi->Type = req->type; keyinfo.TitleIndex = 0;
keyinfo.Type = type;
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR); keyinfo.NameLength = 0;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; memcpy( info, &keyinfo, min(fixed_size,length) );
kbi->NameLength = 0;
}
break; break;
}
case KeyValueFullInformation: case KeyValueFullInformation:
{ {
PKEY_VALUE_FULL_INFORMATION kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation; KEY_VALUE_FULL_INFORMATION keyinfo;
ULONG DataOffset; keyinfo.TitleIndex = 0;
kfi->Type = req->type; keyinfo.Type = type;
keyinfo.DataOffset = fixed_size;
DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR); keyinfo.DataLength = total_len;
*ResultLength = DataOffset + req->len; keyinfo.NameLength = 0;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; memcpy( info, &keyinfo, min(fixed_size,length) );
kfi->NameLength = 0;
kfi->DataOffset = DataOffset;
kfi->DataLength = req->len;
memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len);
}
break; break;
}
case KeyValuePartialInformation: case KeyValuePartialInformation:
{ {
PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; KEY_VALUE_PARTIAL_INFORMATION keyinfo;
kpi->Type = req->type; keyinfo.TitleIndex = 0;
keyinfo.Type = type;
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len; keyinfo.DataLength = total_len;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; memcpy( info, &keyinfo, min(fixed_size,length) );
kpi->DataLength = req->len;
memcpy(kpi->Data, req->data, req->len);
}
break; break;
}
default: default:
FIXME("KeyValueInformationClass not implemented\n"); break;
return STATUS_UNSUCCESSFUL;
} }
return ret; return ret;
} }
@ -587,22 +647,52 @@ NTSTATUS WINAPI NtSetInformationKey(
KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength); KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/****************************************************************************** /******************************************************************************
* NtSetValueKey [NTDLL] * NtSetValueKey [NTDLL]
* ZwSetValueKey * 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( NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
HANDLE KeyHandle, ULONG type, const void *data, ULONG count )
PUNICODE_STRING ValueName,
ULONG TitleIndex,
ULONG Type,
PVOID Data,
ULONG DataSize)
{ {
FIXME("(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n", NTSTATUS ret;
KeyHandle, ValueName,debugstr_us(ValueName), TitleIndex, Type, Data, DataSize); ULONG namelen, pos;
return STATUS_SUCCESS;
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 */ IN time_t modif; /* last modification time */
OUT int hkey; /* handle to the created key */ OUT int hkey; /* handle to the created key */
OUT int created; /* has it been newly created? */ OUT int created; /* has it been newly created? */
IN path_t name; /* key name */ IN VARARG(name,unicode_len_str); /* key name */
IN WCHAR class[1]; /* class name */ IN VARARG(class,unicode_str); /* class name */
}; };
/* Open a registry key */ /* Open a registry key */
struct open_key_request struct open_key_request
{ {
@ -1030,7 +1029,7 @@ struct open_key_request
IN int parent; /* handle to the parent key */ IN int parent; /* handle to the parent key */
IN unsigned int access; /* desired access rights */ IN unsigned int access; /* desired access rights */
OUT int hkey; /* handle to the open key */ 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 struct delete_key_request
{ {
REQUEST_HEADER; /* request header */ REQUEST_HEADER; /* request header */
IN int hkey; /* handle to the parent key */ IN int hkey; /* handle to the 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 */
}; };
@ -1088,9 +1078,8 @@ struct set_key_value_request
IN int type; /* value type */ IN int type; /* value type */
IN unsigned int total; /* total value len */ IN unsigned int total; /* total value len */
IN unsigned int offset; /* offset for setting data */ IN unsigned int offset; /* offset for setting data */
IN unsigned int len; /* value data len */ IN VARARG(name,unicode_len_str); /* value name */
IN path_t name; /* value name */ IN VARARG(data,bytes); /* value data */
IN unsigned char data[1]; /* value data */
}; };
@ -1102,8 +1091,8 @@ struct get_key_value_request
IN unsigned int offset; /* offset for getting data */ IN unsigned int offset; /* offset for getting data */
OUT int type; /* value type */ OUT int type; /* value type */
OUT int len; /* value data len */ OUT int len; /* value data len */
IN WCHAR name[1]; /* value name */ IN VARARG(name,unicode_len_str); /* value name */
OUT unsigned char data[1]; /* value data */ OUT VARARG(data,bytes); /* value data */
}; };
@ -1126,7 +1115,7 @@ struct delete_key_value_request
{ {
REQUEST_HEADER; /* request header */ REQUEST_HEADER; /* request header */
IN int hkey; /* handle to registry key */ 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_CREATE_KEY,
REQ_OPEN_KEY, REQ_OPEN_KEY,
REQ_DELETE_KEY, REQ_DELETE_KEY,
REQ_CLOSE_KEY,
REQ_ENUM_KEY, REQ_ENUM_KEY,
REQ_QUERY_KEY_INFO, REQ_QUERY_KEY_INFO,
REQ_SET_KEY_VALUE, REQ_SET_KEY_VALUE,
@ -1556,7 +1544,6 @@ union generic_request
struct create_key_request create_key; struct create_key_request create_key;
struct open_key_request open_key; struct open_key_request open_key;
struct delete_key_request delete_key; struct delete_key_request delete_key;
struct close_key_request close_key;
struct enum_key_request enum_key; struct enum_key_request enum_key;
struct query_key_info_request query_key_info; struct query_key_info_request query_key_info;
struct set_key_value_request set_key_value; struct set_key_value_request set_key_value;
@ -1587,7 +1574,7 @@ union generic_request
struct set_serial_info_request set_serial_info; struct set_serial_info_request set_serial_info;
}; };
#define SERVER_PROTOCOL_VERSION 23 #define SERVER_PROTOCOL_VERSION 24
/* ### make_requests end ### */ /* ### make_requests end ### */
/* Everything above this line is generated automatically by tools/make_requests */ /* Everything above this line is generated automatically by tools/make_requests */

View File

@ -29,14 +29,6 @@
DEFAULT_DEBUG_CHANNEL(reg); 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 */ /* Unicode->Ansi conversion without string delimiters */
static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n ) 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, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos ) LPHKEY retkey, LPDWORD dispos )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct create_key_request *req = get_req_buffer(); UNICODE_STRING nameW, classW;
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 );
if (reserved) return ERROR_INVALID_PARAMETER; if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey; attr.Length = sizeof(attr);
req->access = access; attr.RootDirectory = hkey;
req->options = options; attr.ObjectName = &nameW;
req->modif = time(NULL); attr.Attributes = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; attr.SecurityDescriptor = NULL;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; attr.SecurityQualityOfService = NULL;
lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0", RtlInitUnicodeString( &nameW, name );
server_remaining(req->class) / sizeof(WCHAR) ); RtlInitUnicodeString( &classW, class );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{ return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0,
*retkey = req->hkey; &classW, options, dispos ) );
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
} }
@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos ) LPHKEY retkey, LPDWORD dispos )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct create_key_request *req = get_req_buffer(); UNICODE_STRING nameW, classW;
ANSI_STRING nameA, classA;
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved, NTSTATUS status;
debugstr_a(class), options, access, sa, retkey, dispos );
if (reserved) return ERROR_INVALID_PARAMETER; if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey; attr.Length = sizeof(attr);
req->access = access; attr.RootDirectory = hkey;
req->options = options; attr.ObjectName = &nameW;
req->modif = time(NULL); attr.Attributes = 0;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; attr.SecurityDescriptor = NULL;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; attr.SecurityQualityOfService = NULL;
lstrcpynAtoW( req->class, class ? class : "", RtlInitAnsiString( &nameA, name );
server_remaining(req->class) / sizeof(WCHAR) ); RtlInitAnsiString( &classA, class );
if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
/* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
{ {
*retkey = req->hkey; if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; {
status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos );
RtlFreeUnicodeString( &classW );
} }
return ret; RtlFreeUnicodeString( &nameW );
}
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 WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct open_key_request *req = get_req_buffer(); UNICODE_STRING nameW;
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey ); attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
if (!retkey) return ERROR_INVALID_PARAMETER; attr.ObjectName = &nameW;
*retkey = 0; attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
req->parent = hkey; attr.SecurityQualityOfService = NULL;
req->access = access; RtlInitUnicodeString( &nameW, name );
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
} }
@ -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 WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{ {
DWORD ret; OBJECT_ATTRIBUTES attr;
struct open_key_request *req = get_req_buffer(); 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; RtlInitAnsiString( &nameA, name );
*retkey = 0; /* FIXME: should use Unicode buffer in TEB */
if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
req->parent = hkey; {
req->access = access; status = NtOpenKey( retkey, access, &attr );
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; RtlFreeUnicodeString( &nameW );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; }
if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; return RtlNtStatusToDosError( status );
return ret;
} }
@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
*/ */
DWORD WINAPI RegCloseKey( HKEY hkey ) DWORD WINAPI RegCloseKey( HKEY hkey )
{ {
struct close_key_request *req = get_req_buffer(); if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS;
TRACE( "(0x%x)\n", hkey ); return RtlNtStatusToDosError( NtClose( hkey ) );
req->hkey = hkey;
return reg_server_call( REQ_CLOSE_KEY );
} }
@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey )
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
{ {
DWORD ret; DWORD ret;
struct delete_key_request *req = get_req_buffer(); HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp )))
req->hkey = hkey; {
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; RegCloseKey( tmp );
return reg_server_call( REQ_DELETE_KEY ); }
return ret;
} }
@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
{ {
DWORD ret; DWORD ret;
struct delete_key_request *req = get_req_buffer(); HKEY tmp;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); if (!name || !*name) return NtDeleteKey( hkey );
if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
req->hkey = hkey; {
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; RegCloseKey( tmp );
return reg_server_call( REQ_DELETE_KEY ); }
return ret;
} }
@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count ) DWORD type, CONST BYTE *data, DWORD count )
{ {
DWORD ret; UNICODE_STRING nameW;
struct set_key_value_request *req = get_req_buffer();
unsigned int max, pos;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count ); if (count && is_string(type))
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{ {
LPCWSTR str = (LPCWSTR)data; LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */ /* 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); count += sizeof(WCHAR);
} }
req->hkey = hkey; RtlInitUnicodeString( &nameW, name );
req->type = type; return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
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;
} }
@ -611,44 +583,36 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
CONST BYTE *data, DWORD count ) CONST BYTE *data, DWORD count )
{ {
DWORD ret; UNICODE_STRING nameW;
struct set_key_value_request *req = get_req_buffer(); ANSI_STRING nameA;
unsigned int max, pos; WCHAR *dataW = NULL;
NTSTATUS status;
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count ); if (count && is_string(type))
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{ {
/* if user forgot to count terminating null, add it (yes NT does this) */ /* if user forgot to count terminating null, add it (yes NT does this) */
if (data[count-1] && !data[count]) count++; if (data[count-1] && !data[count]) count++;
} }
if (is_string( type )) /* need to convert to Unicode */ 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; DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 );
if (len > max) len = max; if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) )))
req->offset = pos; return ERROR_OUTOFMEMORY;
req->len = len; MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW );
count = lenW * sizeof(WCHAR);
if (is_string( type )) data = (BYTE *)dataW;
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;
} }
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 );
} }
@ -722,45 +686,60 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count ) LPBYTE data, LPDWORD count )
{ {
DWORD ret; NTSTATUS status;
struct get_key_value_request *req = get_req_buffer(); 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", TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 ); hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey; RtlInitUnicodeString( &name_str, name );
req->offset = 0;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; if (data) total_size = min( sizeof(buffer), *count + info_size );
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; 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 (data)
{ {
if (*count < req->len) ret = ERROR_MORE_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 else
{ status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
/* copy the data */ buf_ptr, total_size, &total_size );
unsigned int max = server_remaining( req->data );
unsigned int pos = 0;
while (pos < req->len)
{
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;
}
} }
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated /* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */ * and there is enough space in the buffer NT appends a \0 */
if (req->len && is_string(req->type) && if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0; {
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
} }
if (type) *type = req->type; }
if (count) *count = req->len; if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
return ret; }
if (type) *type = info->Type;
if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
} }
@ -773,51 +752,84 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count ) LPBYTE data, LPDWORD count )
{ {
DWORD ret, total_len; NTSTATUS status;
struct get_key_value_request *req = get_req_buffer(); 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", TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey; RtlInitAnsiString( &nameA, name );
req->offset = 0; /* FIXME: should use Unicode buffer in TEB */
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
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; 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 );
}
if (!status)
{
if (is_string(info->Type))
{
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 else
{ {
/* copy the data */ WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
unsigned int max = server_remaining( req->data ); (total_size - info_size) /sizeof(WCHAR),
unsigned int pos = 0; data, len, NULL, NULL );
while (pos < req->len)
{
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;
}
}
/* if the type is REG_SZ and data is not 0-terminated /* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */ * 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]) if (len < *count && data[len-1]) data[len] = 0;
data[total_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 (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
} }
if (count) *count = total_len; if (type) *type = info->Type;
if (type) *type = req->type; if (count) *count = total_size - info_size;
return ret; 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 WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{ {
DWORD ret; UNICODE_STRING nameW;
struct delete_key_value_request *req = get_req_buffer(); RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
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 );
} }
@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
*/ */
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
{ {
DWORD ret; UNICODE_STRING nameW;
struct delete_key_value_request *req = get_req_buffer(); STRING nameA;
NTSTATUS status;
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); RtlInitAnsiString( &nameA, name );
/* FIXME: should use Unicode buffer in TEB */
req->hkey = hkey; if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; {
return reg_server_call( REQ_DELETE_KEY_VALUE ); 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 */ /* duplicate a key path from the request buffer */
/* returns a pointer to a static buffer, so only useable once per request */ /* 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]; static WCHAR buffer[MAX_PATH+1];
WCHAR *p = buffer;
while (p < buffer + sizeof(buffer) - 1) if (!(*p++ = *path++)) break; if (len > sizeof(buffer)-sizeof(buffer[0]))
*p = 0; {
set_error( STATUS_BUFFER_OVERFLOW );
return NULL;
}
memcpy( buffer, path, len );
buffer[len / sizeof(WCHAR)] = 0;
return buffer; 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 */ /* return the next token in a given path */
/* returns a pointer to a static buffer, so only useable once per request */ /* 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 WCHAR *path;
static const WCHAR *end; WCHAR *ret;
static WCHAR buffer[MAX_PATH+1];
WCHAR *p = buffer;
if (initpath) if (initpath)
{ {
path = initpath; /* path cannot start with a backslash */
end = path + maxlen / sizeof(WCHAR); if (*initpath == '\\')
}
while ((path < end) && (*path == '\\')) path++;
while ((path < end) && (p < buffer + sizeof(buffer) - 1))
{ {
WCHAR ch = *path; set_error( STATUS_OBJECT_PATH_INVALID );
if (!ch || (ch == '\\')) break; return NULL;
*p++ = ch;
path++;
} }
*p = 0; path = initpath;
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 */ /* 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; WCHAR *name;
size_t len = get_req_strlenW( req, str ); if ((name = mem_alloc( len + sizeof(WCHAR) )) != NULL)
if ((name = mem_alloc( (len + 1) * sizeof(WCHAR) )) != NULL)
{ {
memcpy( name, str, len * sizeof(WCHAR) ); memcpy( name, str, len );
name[len] = 0; name[len / sizeof(WCHAR)] = 0;
} }
return name; return name;
} }
@ -466,12 +481,13 @@ static struct key *find_subkey( struct key *key, const WCHAR *name, int *index )
} }
/* open a subkey */ /* 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; int index;
WCHAR *path; WCHAR *path;
path = get_path_token( name, maxlen ); if (!(path = get_path_token( name ))) return NULL;
while (*path) while (*path)
{ {
if (!(key = find_subkey( key, path, &index ))) 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 ); set_error( STATUS_OBJECT_NAME_NOT_FOUND );
break; break;
} }
path = get_path_token( NULL, 0 ); path = get_path_token( NULL );
} }
if (debug_level > 1) dump_operation( key, NULL, "Open" ); 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 */ /* 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 ) unsigned int options, time_t modif, int *created )
{ {
struct key *base; 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); if (!modif) modif = time(NULL);
path = get_path_token( name, maxlen ); if (!(path = get_path_token( name ))) return NULL;
*created = 0; *created = 0;
while (*path) while (*path)
{ {
struct key *subkey; struct key *subkey;
if (!(subkey = find_subkey( key, path, &index ))) break; if (!(subkey = find_subkey( key, path, &index ))) break;
key = subkey; key = subkey;
path = get_path_token( NULL, 0 ); path = get_path_token( NULL );
} }
/* create the remaining part */ /* create the remaining part */
@ -528,7 +545,7 @@ static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen
while (key) while (key)
{ {
key->flags |= flags; key->flags |= flags;
path = get_path_token( NULL, 0 ); path = get_path_token( NULL );
if (!*path) goto done; if (!*path) goto done;
/* we know the index is always 0 in a new key */ /* we know the index is always 0 in a new key */
key = alloc_subkey( key, path, 0, modif ); key = alloc_subkey( key, path, 0, modif );
@ -597,16 +614,12 @@ static void query_key( struct key *key, struct query_key_info_request *req )
} }
/* delete a key and its values */ /* 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; int index;
struct key *parent; struct key *parent;
WCHAR *path;
path = get_path_token( name, maxlen ); /* must find parent and index */
if (!*path)
{
/* deleting this key, must find parent and index */
if (key->flags & KEY_ROOT) if (key->flags & KEY_ROOT)
{ {
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
@ -620,17 +633,6 @@ static void delete_key( struct key *key, const WCHAR *name, size_t maxlen )
for (index = 0; index <= parent->last_subkey; index++) for (index = 0; index <= parent->last_subkey; index++)
if (parent->subkeys[index] == key) break; if (parent->subkeys[index] == key) break;
assert( index <= parent->last_subkey ); assert( index <= parent->last_subkey );
}
else while (*path)
{
parent = key;
if (!(key = find_subkey( parent, path, &index )))
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return;
}
path = get_path_token( NULL, 0 );
}
/* we can only delete a key that has no subkeys (FIXME) */ /* we can only delete a key that has no subkeys (FIXME) */
if ((key->flags & KEY_ROOT) || (key->last_subkey >= 0)) 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 */ /* set a key value */
static void set_value( struct key *key, WCHAR *name, int type, unsigned int total_len, 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; struct key_value *value;
void *ptr = NULL; 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 */ /* get a key value */
static void get_value( struct key *key, WCHAR *name, unsigned int offset, static size_t get_value( struct key *key, WCHAR *name, unsigned int offset,
unsigned int maxlen, int *type, int *len, void *data ) unsigned int maxlen, int *type, int *len, void *data )
{ {
struct key_value *value; struct key_value *value;
int index; int index;
size_t ret = 0;
if ((value = find_value( key, name, &index ))) 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; if (maxlen > value->len - offset) maxlen = value->len - offset;
memcpy( data, (char *)value->data + offset, maxlen ); memcpy( data, (char *)value->data + offset, maxlen );
ret = maxlen;
} }
if (debug_level > 1) dump_operation( key, value, "Get" ); 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; *type = -1;
set_error( STATUS_OBJECT_NAME_NOT_FOUND ); set_error( STATUS_OBJECT_NAME_NOT_FOUND );
} }
return ret;
} }
/* enumerate a key value */ /* enumerate a key value */
@ -871,7 +876,7 @@ static struct key *create_root_key( int hkey )
} }
keyname[i++] = 0; 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; special_root_keys[hkey - HKEY_SPECIAL_ROOT_FIRST] = key;
key->flags |= KEY_ROOT; 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, static struct key *load_key( struct key *base, const char *buffer, unsigned int options,
int prefix_len, struct file_load_info *info ) int prefix_len, struct file_load_info *info )
{ {
WCHAR *p; WCHAR *p, *name;
int res, len, modif; int res, len, modif;
len = strlen(buffer) * sizeof(WCHAR); 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 */ /* empty key name, return base key */
return (struct key *)grab_object( base ); 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 */ /* parse a comma-separated list of hex digits */
@ -1325,7 +1335,7 @@ void init_registry(void)
int dummy; int dummy;
/* create the config key */ /* 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 ))) NULL, 0, time(NULL), &dummy )))
fatal_error( "could not create config key\n" ); fatal_error( "could not create config key\n" );
key->flags |= KEY_VOLATILE; key->flags |= KEY_VOLATILE;
@ -1520,23 +1530,37 @@ void close_registry(void)
/* create a registry key */ /* create a registry key */
DECL_HANDLER(create_key) DECL_HANDLER(create_key)
{ {
struct key *key, *parent; struct key *key = NULL, *parent;
WCHAR *class;
unsigned int access = req->access; unsigned int access = req->access;
WCHAR *name, *class;
size_t len;
if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */ if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */
req->hkey = -1; req->hkey = -1;
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ ))) 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, if (len == get_req_data_size(req)) /* no class specified */
req->modif, &req->created ))) {
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 ); req->hkey = alloc_handle( current->process, key, access, 0 );
release_object( key ); release_object( key );
} }
free( class );
} }
release_object( parent ); release_object( parent );
} }
@ -1552,7 +1576,8 @@ DECL_HANDLER(open_key)
req->hkey = -1; req->hkey = -1;
if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ ))) 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 ); req->hkey = alloc_handle( current->process, key, access, 0 );
release_object( key ); release_object( key );
@ -1568,19 +1593,11 @@ DECL_HANDLER(delete_key)
if ((key = get_hkey_obj( req->hkey, 0 /*FIXME*/ ))) if ((key = get_hkey_obj( req->hkey, 0 /*FIXME*/ )))
{ {
delete_key( key, req->name, sizeof(req->name) ); delete_key( key );
release_object( 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 */ /* enumerate registry subkeys */
DECL_HANDLER(enum_key) DECL_HANDLER(enum_key)
{ {
@ -1611,14 +1628,18 @@ DECL_HANDLER(query_key_info)
DECL_HANDLER(set_key_value) DECL_HANDLER(set_key_value)
{ {
struct key *key; struct key *key;
unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) ); WCHAR *name;
unsigned int datalen = req->len; size_t len;
if (datalen > max) datalen = max;
if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE ))) if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
{ {
set_value( key, copy_path( req->name ), req->type, req->total, if ((name = copy_req_path( req, &len )))
req->offset, datalen, req->data ); {
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 ); release_object( key );
} }
} }
@ -1627,13 +1648,18 @@ DECL_HANDLER(set_key_value)
DECL_HANDLER(get_key_value) DECL_HANDLER(get_key_value)
{ {
struct key *key; struct key *key;
unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) ); WCHAR *name;
size_t len;
req->len = 0; req->len = 0;
if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE ))) if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
{ {
get_value( key, copy_path( req->name ), req->offset, max, if ((name = copy_req_path( req, &len )))
&req->type, &req->len, req->data ); {
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 ); release_object( key );
} }
} }
@ -1662,7 +1688,7 @@ DECL_HANDLER(delete_key_value)
if ((key = get_hkey_obj( req->hkey, KEY_SET_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 ); delete_value( key, name );
free( name ); free( name );

View File

@ -175,7 +175,6 @@ DECL_HANDLER(write_process_memory);
DECL_HANDLER(create_key); DECL_HANDLER(create_key);
DECL_HANDLER(open_key); DECL_HANDLER(open_key);
DECL_HANDLER(delete_key); DECL_HANDLER(delete_key);
DECL_HANDLER(close_key);
DECL_HANDLER(enum_key); DECL_HANDLER(enum_key);
DECL_HANDLER(query_key_info); DECL_HANDLER(query_key_info);
DECL_HANDLER(set_key_value); 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_create_key,
(req_handler)req_open_key, (req_handler)req_open_key,
(req_handler)req_delete_key, (req_handler)req_delete_key,
(req_handler)req_close_key,
(req_handler)req_enum_key, (req_handler)req_enum_key,
(req_handler)req_query_key_info, (req_handler)req_query_key_info,
(req_handler)req_set_key_value, (req_handler)req_set_key_value,

View File

@ -15,9 +15,20 @@
#include "request.h" #include "request.h"
#include "unicode.h" #include "unicode.h"
static int cur_pos;
/* utility functions */ /* 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 ) static void dump_uints( const int *ptr, int len )
{ {
fputc( '{', stderr ); fputc( '{', stderr );
@ -59,63 +70,8 @@ static void dump_path_t( const void *req, const path_t *path )
dump_unicode_string( req, *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__ #ifdef __i386__
fprintf( stderr, "{flags=%08lx,eax=%08lx,ebx=%08lx,ecx=%08lx,edx=%08lx,esi=%08lx,edi=%08lx," 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," "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 #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=" ); int i;
dump_varargs_context( ptr, sizeof(CONTEXT) ); fprintf( stderr, "{code=%lx,flags=%lx,rec=%p,addr=%p,params={",
fprintf( stderr, ",rec=" ); rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionRecord,
dump_exc_record( (EXCEPTION_RECORD *)((CONTEXT *)ptr + 1) ); rec->ExceptionAddress );
for (i = 0; i < rec->NumberParameters; i++)
{
if (i) fputc( ',', stderr );
fprintf( stderr, "%lx", rec->ExceptionInformation[i] );
}
fputc( '}', stderr ); 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, "{}" ); fprintf( stderr, "{}" );
return; return 0;
} }
switch(event->code) 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 ); fprintf( stderr, "{code=??? (%d)}", event->code );
break; 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; const INPUT_RECORD *rec = get_data(req);
len /= sizeof(*rec); size_t len = get_size(req) / sizeof(*rec);
fputc( '{', stderr ); fputc( '{', stderr );
while (len > 0) while (len > 0)
@ -217,6 +266,7 @@ static void dump_varargs_input_records( const void *ptr, size_t len )
if (--len) fputc( ',', stderr ); if (--len) fputc( ',', stderr );
} }
fputc( '}', stderr ); fputc( '}', stderr );
return get_size(req);
} }
/* dumping for functions for requests that have a variable part */ /* 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) ); 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 ) 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 )); 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, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " alloc_fd=%d,", req->alloc_fd ); fprintf( stderr, " alloc_fd=%d,", req->alloc_fd );
fprintf( stderr, " filename=" ); 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 ) 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, " hstderr=%d,", req->hstderr );
fprintf( stderr, " cmd_show=%d,", req->cmd_show ); fprintf( stderr, " cmd_show=%d,", req->cmd_show );
fprintf( stderr, " filename=" ); 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 ) 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, " func=%p,", req->func );
fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " type=%d,", req->type );
fprintf( stderr, " args=" ); 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 ) 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, " flags=%d,", req->flags );
fprintf( stderr, " timeout=%d,", req->timeout ); fprintf( stderr, " timeout=%d,", req->timeout );
fprintf( stderr, " handles=" ); 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 ) 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, " initial_state=%d,", req->initial_state );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " owned=%d,", req->owned );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " max=%08x,", req->max );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " create=%d,", req->create );
fprintf( stderr, " attrs=%08x,", req->attrs ); fprintf( stderr, " attrs=%08x,", req->attrs );
fprintf( stderr, " filename=" ); 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 ) 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, " pmask=%08x,", req->pmask );
fprintf( stderr, " state=%08x,", req->state ); fprintf( stderr, " state=%08x,", req->state );
fprintf( stderr, " errors=" ); 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 ) 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_size=%d,", req->cursor_size );
fprintf( stderr, " cursor_visible=%d,", req->cursor_visible ); fprintf( stderr, " cursor_visible=%d,", req->cursor_visible );
fprintf( stderr, " title=" ); 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 ) 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, " cursor_visible=%d,", req->cursor_visible );
fprintf( stderr, " pid=%d,", req->pid ); fprintf( stderr, " pid=%d,", req->pid );
fprintf( stderr, " title=" ); 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 ) static void dump_write_console_input_request( const struct write_console_input_request *req )
{ {
fprintf( stderr, " handle=%d,", req->handle ); fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " rec=" ); 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 ) 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, " read=%d,", req->read );
fprintf( stderr, " rec=" ); 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 ) 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, " inherit=%d,", req->inherit );
fprintf( stderr, " file_handle=%d,", req->file_handle ); fprintf( stderr, " file_handle=%d,", req->file_handle );
fprintf( stderr, " name=" ); 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 ) 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, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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, " pid=%p,", req->pid );
fprintf( stderr, " tid=%p,", req->tid ); fprintf( stderr, " tid=%p,", req->tid );
fprintf( stderr, " event=" ); 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 ) static void dump_exception_event_request( const struct exception_event_request *req )
{ {
fprintf( stderr, " first=%d,", req->first ); fprintf( stderr, " first=%d,", req->first );
fprintf( stderr, " record=" ); 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 ) static void dump_exception_event_reply( const struct exception_event_request *req )
{ {
fprintf( stderr, " status=%d,", req->status ); fprintf( stderr, " status=%d,", req->status );
fprintf( stderr, " context=" ); 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 ) 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, " options=%08x,", req->options );
fprintf( stderr, " modif=%ld,", req->modif ); fprintf( stderr, " modif=%ld,", req->modif );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_path_t( req, &req->name ); cur_pos += dump_varargs_unicode_len_str( req );
fprintf( stderr, "," ); fputc( ',', stderr );
fprintf( stderr, " class=" ); 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 ) 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, " parent=%d,", req->parent );
fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " name=" ); 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 ) 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 ) 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 ); 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, " type=%d,", req->type );
fprintf( stderr, " total=%08x,", req->total ); fprintf( stderr, " total=%08x,", req->total );
fprintf( stderr, " offset=%08x,", req->offset ); fprintf( stderr, " offset=%08x,", req->offset );
fprintf( stderr, " len=%08x,", req->len );
fprintf( stderr, " name=" ); fprintf( stderr, " name=" );
dump_path_t( req, &req->name ); cur_pos += dump_varargs_unicode_len_str( req );
fprintf( stderr, "," ); fputc( ',', stderr );
fprintf( stderr, " data=" ); 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 ) 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, " hkey=%d,", req->hkey );
fprintf( stderr, " offset=%08x,", req->offset ); fprintf( stderr, " offset=%08x,", req->offset );
fprintf( stderr, " name=" ); 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 ) 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, " type=%d,", req->type );
fprintf( stderr, " len=%d,", req->len ); fprintf( stderr, " len=%d,", req->len );
fprintf( stderr, " data=" ); 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 ) 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, " hkey=%d,", req->hkey );
fprintf( stderr, " name=" ); 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 ) 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, " inherit=%d,", req->inherit );
fprintf( stderr, " manual=%d,", req->manual ); fprintf( stderr, " manual=%d,", req->manual );
fprintf( stderr, " name=" ); 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 ) 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, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " name=" ); 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 ) 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 ) static void dump_get_thread_context_reply( const struct get_thread_context_request *req )
{ {
fprintf( stderr, " context=" ); 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 ) 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, " handle=%d,", req->handle );
fprintf( stderr, " flags=%08x,", req->flags ); fprintf( stderr, " flags=%08x,", req->flags );
fprintf( stderr, " context=" ); 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 ) 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, " local=%d,", req->local );
fprintf( stderr, " name=" ); 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 ) 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, " local=%d,", req->local );
fprintf( stderr, " name=" ); 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 ) 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, " count=%d,", req->count );
fprintf( stderr, " name=" ); 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 ) 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_create_key_request,
(dump_func)dump_open_key_request, (dump_func)dump_open_key_request,
(dump_func)dump_delete_key_request, (dump_func)dump_delete_key_request,
(dump_func)dump_close_key_request,
(dump_func)dump_enum_key_request, (dump_func)dump_enum_key_request,
(dump_func)dump_query_key_info_request, (dump_func)dump_query_key_info_request,
(dump_func)dump_set_key_value_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_create_key_reply,
(dump_func)dump_open_key_reply, (dump_func)dump_open_key_reply,
(dump_func)0, (dump_func)0,
(dump_func)0,
(dump_func)dump_enum_key_reply, (dump_func)dump_enum_key_reply,
(dump_func)dump_query_key_info_reply, (dump_func)dump_query_key_info_reply,
(dump_func)0, (dump_func)0,
@ -1769,7 +1797,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"create_key", "create_key",
"open_key", "open_key",
"delete_key", "delete_key",
"close_key",
"enum_key", "enum_key",
"query_key_info", "query_key_info",
"set_key_value", "set_key_value",
@ -1805,10 +1832,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
void trace_request( enum request req ) void trace_request( enum request req )
{ {
cur_pos = 0;
current->last_req = req; current->last_req = req;
if (req < REQ_NB_REQUESTS) if (req < REQ_NB_REQUESTS)
{ {
fprintf( stderr, "%08x: %s(", (unsigned int)current, req_names[req] ); fprintf( stderr, "%08x: %s(", (unsigned int)current, req_names[req] );
cur_pos = 0;
req_dumpers[req]( current->buffer ); req_dumpers[req]( current->buffer );
} }
else else
@ -1824,6 +1853,7 @@ void trace_reply( struct thread *thread )
if (reply_dumpers[thread->last_req]) if (reply_dumpers[thread->last_req])
{ {
fprintf( stderr, " {" ); fprintf( stderr, " {" );
cur_pos = 0;
reply_dumpers[thread->last_req]( thread->buffer ); reply_dumpers[thread->last_req]( thread->buffer );
fprintf( stderr, " }" ); fprintf( stderr, " }" );
} }

View File

@ -179,7 +179,8 @@ sub DO_DUMP_FUNC
{ {
my $func = $1; my $func = $1;
push @trace_lines, " fprintf( stderr, \" $var=\" );\n"; 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 else
{ {