Converted some of the registry server requests to the new request

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

View File

@ -29,14 +29,6 @@
DEFAULT_DEBUG_CHANNEL(reg); 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 );
}
RtlFreeUnicodeString( &nameW );
} }
return ret; return RtlNtStatusToDosError( status );
} }
@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
*/ */
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) DWORD 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;
} }
@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
* RegSetValueExA [ADVAPI32.169] * RegSetValueExA [ADVAPI32.169]
*/ */
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 );
} }
@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
* buffer is left untouched. The MS-documentation is wrong (js) !!! * buffer is left untouched. The MS-documentation is wrong (js) !!!
*/ */
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;
else /* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
{ {
/* copy the data */ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
unsigned int max = server_remaining( req->data ); if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
unsigned int pos = 0; status = STATUS_NO_MEMORY;
while (pos < req->len) else
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{ {
unsigned int len = min( req->len - pos, max ); WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
memcpy( data + pos, req->data, len ); if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
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 the type is REG_SZ and data is not 0-terminated if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
* and there is enough space in the buffer NT appends a \0 */
if (req->len && is_string(req->type) &&
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
} }
if (type) *type = req->type;
if (count) *count = req->len; if (type) *type = info->Type;
return ret; if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
} }
@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
* the documentation is wrong: if the buffer is to small it remains untouched * the documentation is wrong: if the buffer is to small it remains untouched
*/ */
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;
else /* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW)
{ {
/* copy the data */ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
unsigned int max = server_remaining( req->data ); if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
unsigned int pos = 0; status = STATUS_NO_MEMORY;
while (pos < req->len) else
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (!status)
{
if (is_string(info->Type))
{ {
unsigned int len = min( req->len - pos, max ); DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
if (is_string( req->type )) (total_size - info_size) /sizeof(WCHAR),
memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) ); NULL, 0, NULL, NULL );
else if (data && len)
memcpy( data + pos, req->data, len ); {
if ((pos += len) >= req->len) break; if (len > *count) status = STATUS_BUFFER_OVERFLOW;
req->offset = pos; else
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; {
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
data, len, NULL, NULL );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (len < *count && data[len-1]) data[len] = 0;
}
}
total_size = len + info_size;
}
else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
} }
} }
/* if the type is REG_SZ and data is not 0-terminated if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
* and there is enough space in the buffer NT appends a \0 */
if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
data[total_len] = 0;
} }
if (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 (!retkey) return STATUS_INVALID_PARAMETER; if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
len += sizeof(WCHAR); /* for storing name length */
req->parent = attr->RootDirectory;
req->access = access;
req->options = options;
req->modif = 0;
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
req->class[0] = 0;
if (class) if (class)
{ {
if ((ret = copy_nameU( req->class, class, server_remaining(req->class) ))) return ret; len += class->Length;
if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
} }
if (!retkey) return STATUS_INVALID_PARAMETER;
if (!(ret = server_call_noerr( REQ_CREATE_KEY ))) SERVER_START_REQ
{ {
*retkey = req->hkey; struct create_key_request *req = server_alloc_req( sizeof(*req), len );
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; WCHAR *data = server_data_ptr(req);
req->parent = attr->RootDirectory;
req->access = access;
req->options = options;
req->modif = 0;
*data++ = attr->ObjectName->Length;
memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
} }
SERVER_END_REQ;
return ret; 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;
req->parent = attr->RootDirectory; SERVER_START_REQ
req->access = access; {
struct open_key_request *req = server_alloc_req( sizeof(*req), len );
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret; req->parent = attr->RootDirectory;
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey; req->access = access;
memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
}
SERVER_END_REQ;
return ret; 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 );
req->hkey = hkey;
req->name[0] = 0; SERVER_START_REQ
return server_call_noerr( REQ_DELETE_KEY ); {
struct delete_key_request *req = server_alloc_req( sizeof(*req), 0 );
req->hkey = hkey;
ret = server_call_noerr( REQ_DELETE_KEY );
}
SERVER_END_REQ;
return ret;
} }
@ -139,13 +150,19 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name ) NTSTATUS 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;
req->hkey = hkey; SERVER_START_REQ
if (!(ret = copy_nameU( req->name, name, MAX_PATH ))) {
struct delete_key_value_request *req = server_alloc_req( sizeof(*req), name->Length );
req->hkey = hkey;
memcpy( server_data_ptr(req), name->Buffer, name->Length );
ret = server_call_noerr( REQ_DELETE_KEY_VALUE ); ret = server_call_noerr( REQ_DELETE_KEY_VALUE );
}
SERVER_END_REQ;
return ret; return ret;
} }
@ -468,70 +485,113 @@ 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;
TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n",
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
req->hkey = KeyHandle; NTSTATUS ret;
if (copy_nameU(req->name, ValueName, MAX_PATH) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW; char *data_ptr;
if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret; int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
switch(KeyValueInformationClass) TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
{
case KeyValueBasicInformation:
{
PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation;
kbi->Type = req->type;
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR); if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
kbi->NameLength = 0;
}
break;
case KeyValueFullInformation:
{
PKEY_VALUE_FULL_INFORMATION kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation;
ULONG DataOffset;
kfi->Type = req->type;
DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR); /* compute the length we want to retrieve */
*ResultLength = DataOffset + req->len; switch(info_class)
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; {
case KeyValueBasicInformation:
fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR);
data_ptr = NULL;
break;
case KeyValueFullInformation:
fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR);
data_ptr = (char *)info + fixed_size;
break;
case KeyValuePartialInformation:
fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR);
data_ptr = (char *)info + fixed_size;
break;
default:
FIXME( "Information class %d not implemented\n", info_class );
return STATUS_INVALID_PARAMETER;
}
if (data_ptr && length > fixed_size) data_len = length - fixed_size;
kfi->NameLength = 0; do
kfi->DataOffset = DataOffset; {
kfi->DataLength = req->len; size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len); reqlen = max( reqlen, name->Length );
}
break;
case KeyValuePartialInformation:
{
PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
kpi->Type = req->type;
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len; SERVER_START_REQ
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; {
struct get_key_value_request *req = server_alloc_req( sizeof(*req), reqlen );
WCHAR *nameptr = server_data_ptr(req);
kpi->DataLength = req->len; req->hkey = handle;
memcpy(kpi->Data, req->data, req->len); req->offset = offset;
} *nameptr++ = name->Length;
break; memcpy( nameptr, name->Buffer, name->Length );
default:
FIXME("KeyValueInformationClass not implemented\n"); if (!(ret = server_call_noerr( REQ_GET_KEY_VALUE )))
return STATUS_UNSUCCESSFUL; {
size_t size = min( server_data_size(req), data_len );
} type = req->type;
return ret; total_len = req->len;
if (size)
{
memcpy( data_ptr + offset, server_data_ptr(req), size );
offset += size;
data_len -= size;
}
}
}
SERVER_END_REQ;
if (ret) return ret;
} while (data_len && offset < total_len);
*result_len = total_len + fixed_size;
if (!data_len) ret = STATUS_BUFFER_OVERFLOW;
if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
switch(info_class)
{
case KeyValueBasicInformation:
{
KEY_VALUE_BASIC_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.NameLength = 0;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
case KeyValueFullInformation:
{
KEY_VALUE_FULL_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.DataOffset = fixed_size;
keyinfo.DataLength = total_len;
keyinfo.NameLength = 0;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
case KeyValuePartialInformation:
{
KEY_VALUE_PARTIAL_INFORMATION keyinfo;
keyinfo.TitleIndex = 0;
keyinfo.Type = type;
keyinfo.DataLength = total_len;
memcpy( info, &keyinfo, min(fixed_size,length) );
break;
}
default:
break;
}
return ret;
} }
/****************************************************************************** /******************************************************************************
@ -587,22 +647,52 @@ NTSTATUS WINAPI NtSetInformationKey(
KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength); 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 );
}
RtlFreeUnicodeString( &nameW );
} }
return ret; return RtlNtStatusToDosError( status );
} }
@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
*/ */
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) DWORD 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;
} }
@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
* RegSetValueExA [ADVAPI32.169] * RegSetValueExA [ADVAPI32.169]
*/ */
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 );
} }
@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR
* buffer is left untouched. The MS-documentation is wrong (js) !!! * buffer is left untouched. The MS-documentation is wrong (js) !!!
*/ */
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;
else /* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
{ {
/* copy the data */ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
unsigned int max = server_remaining( req->data ); if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
unsigned int pos = 0; status = STATUS_NO_MEMORY;
while (pos < req->len) else
status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (!status)
{
memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{ {
unsigned int len = min( req->len - pos, max ); WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
memcpy( data + pos, req->data, len ); if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
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 the type is REG_SZ and data is not 0-terminated if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
* and there is enough space in the buffer NT appends a \0 */
if (req->len && is_string(req->type) &&
(req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
} }
if (type) *type = req->type;
if (count) *count = req->len; if (type) *type = info->Type;
return ret; if (count) *count = total_size - info_size;
done:
return RtlNtStatusToDosError(status);
} }
@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
* the documentation is wrong: if the buffer is to small it remains untouched * the documentation is wrong: if the buffer is to small it remains untouched
*/ */
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;
else /* retry with a dynamically allocated buffer */
while (status == STATUS_BUFFER_OVERFLOW)
{ {
/* copy the data */ if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
unsigned int max = server_remaining( req->data ); if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
unsigned int pos = 0; status = STATUS_NO_MEMORY;
while (pos < req->len) else
status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
buf_ptr, total_size, &total_size );
}
if (!status)
{
if (is_string(info->Type))
{ {
unsigned int len = min( req->len - pos, max ); DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
if (is_string( req->type )) (total_size - info_size) /sizeof(WCHAR),
memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) ); NULL, 0, NULL, NULL );
else if (data && len)
memcpy( data + pos, req->data, len ); {
if ((pos += len) >= req->len) break; if (len > *count) status = STATUS_BUFFER_OVERFLOW;
req->offset = pos; else
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; {
if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
(total_size - info_size) /sizeof(WCHAR),
data, len, NULL, NULL );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (len < *count && data[len-1]) data[len] = 0;
}
}
total_size = len + info_size;
}
else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size );
/* if the type is REG_SZ and data is not 0-terminated
* and there is enough space in the buffer NT appends a \0 */
if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
{
WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
} }
} }
/* if the type is REG_SZ and data is not 0-terminated if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
* and there is enough space in the buffer NT appends a \0 */
if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
data[total_len] = 0;
} }
if (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 cannot start with a backslash */
if (*initpath == '\\')
{
set_error( STATUS_OBJECT_PATH_INVALID );
return NULL;
}
path = initpath; path = initpath;
end = path + maxlen / sizeof(WCHAR);
} }
while ((path < end) && (*path == '\\')) path++; else while (*path == '\\') path++;
while ((path < end) && (p < buffer + sizeof(buffer) - 1))
{ ret = path;
WCHAR ch = *path; while (*path && *path != '\\') path++;
if (!ch || (ch == '\\')) break; if (*path) *path++ = 0;
*p++ = ch; return ret;
path++;
}
*p = 0;
return buffer;
} }
/* 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,40 +614,25 @@ 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) if (key->flags & KEY_ROOT)
{ {
/* deleting this key, must find parent and index */ set_error( STATUS_ACCESS_DENIED );
if (key->flags & KEY_ROOT) return;
{
set_error( STATUS_ACCESS_DENIED );
return;
}
if (!(parent = key->parent) || (key->flags & KEY_DELETED))
{
set_error( STATUS_KEY_DELETED );
return;
}
for (index = 0; index <= parent->last_subkey; index++)
if (parent->subkeys[index] == key) break;
assert( index <= parent->last_subkey );
} }
else while (*path) if (!(parent = key->parent) || (key->flags & KEY_DELETED))
{ {
parent = key; set_error( STATUS_KEY_DELETED );
if (!(key = find_subkey( parent, path, &index ))) return;
{
set_error( STATUS_OBJECT_NAME_NOT_FOUND );
return;
}
path = get_path_token( NULL, 0 );
} }
for (index = 0; index <= parent->last_subkey; index++)
if (parent->subkeys[index] == key) break;
assert( index <= parent->last_subkey );
/* we can only delete a key that has no subkeys (FIXME) */ /* 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,8 +1853,9 @@ 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, " }" );
} }
if (thread->pass_fd != -1) fprintf( stderr, " fd=%d\n", thread->pass_fd ); if (thread->pass_fd != -1) fprintf( stderr, " fd=%d\n", thread->pass_fd );
else fprintf( stderr, "\n" ); else fprintf( stderr, "\n" );

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
{ {