diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index 2fe167860a1..fca82b169dd 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -29,14 +29,6 @@ DEFAULT_DEBUG_CHANNEL(reg); -/* Ansi->Unicode conversion without string delimiters */ -static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n ) -{ - LPWSTR p = dst; - while (n-- > 0) *p++ = (WCHAR)*src++; - return dst; -} - /* Unicode->Ansi conversion without string delimiters */ static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n ) { @@ -104,29 +96,23 @@ DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR cl DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, LPHKEY retkey, LPDWORD dispos ) { - DWORD ret; - struct create_key_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved, - debugstr_w(class), options, access, sa, retkey, dispos ); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW, classW; if (reserved) return ERROR_INVALID_PARAMETER; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; - req->parent = hkey; - req->access = access; - req->options = options; - req->modif = time(NULL); - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0", - server_remaining(req->class) / sizeof(WCHAR) ); - if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS) - { - *retkey = req->hkey; - if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; - } - return ret; + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, name ); + RtlInitUnicodeString( &classW, class ); + + return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0, + &classW, options, dispos ) ); } @@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, LPHKEY retkey, LPDWORD dispos ) { - DWORD ret; - struct create_key_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved, - debugstr_a(class), options, access, sa, retkey, dispos ); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW, classW; + ANSI_STRING nameA, classA; + NTSTATUS status; if (reserved) return ERROR_INVALID_PARAMETER; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; - req->parent = hkey; - req->access = access; - req->options = options; - req->modif = time(NULL); - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - lstrcpynAtoW( req->class, class ? class : "", - server_remaining(req->class) / sizeof(WCHAR) ); - if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS) + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitAnsiString( &nameA, name ); + RtlInitAnsiString( &classA, class ); + + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) { - *retkey = req->hkey; - if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; + if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) + { + status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos ); + RtlFreeUnicodeString( &classW ); + } + RtlFreeUnicodeString( &nameW ); } - return ret; + return RtlNtStatusToDosError( status ); } @@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey ) */ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) { - DWORD ret; - struct open_key_request *req = get_req_buffer(); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; - TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey ); - - if (!retkey) return ERROR_INVALID_PARAMETER; - *retkey = 0; - - req->parent = hkey; - req->access = access; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; - return ret; + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) ); } @@ -231,20 +219,26 @@ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM acce */ DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) { - DWORD ret; - struct open_key_request *req = get_req_buffer(); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + STRING nameA; + NTSTATUS status; - TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey ); + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; - if (!retkey) return ERROR_INVALID_PARAMETER; - *retkey = 0; - - req->parent = hkey; - req->access = access; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; - return ret; + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtOpenKey( retkey, access, &attr ); + RtlFreeUnicodeString( &nameW ); + } + return RtlNtStatusToDosError( status ); } @@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR */ DWORD WINAPI RegCloseKey( HKEY hkey ) { - struct close_key_request *req = get_req_buffer(); - TRACE( "(0x%x)\n", hkey ); - req->hkey = hkey; - return reg_server_call( REQ_CLOSE_KEY ); + if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS; + return RtlNtStatusToDosError( NtClose( hkey ) ); } @@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey ) DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) { DWORD ret; - struct delete_key_request *req = get_req_buffer(); + HKEY tmp; - TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); - - req->hkey = hkey; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - return reg_server_call( REQ_DELETE_KEY ); + if (!name || !*name) return NtDeleteKey( hkey ); + if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp ))) + { + ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); + RegCloseKey( tmp ); + } + return ret; } @@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) { DWORD ret; - struct delete_key_request *req = get_req_buffer(); + HKEY tmp; - TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); - - req->hkey = hkey; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - return reg_server_call( REQ_DELETE_KEY ); + if (!name || !*name) return NtDeleteKey( hkey ); + if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp ))) + { + ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); + RegCloseKey( tmp ); + } + return ret; } @@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, DWORD type, CONST BYTE *data, DWORD count ) { - DWORD ret; - struct set_key_value_request *req = get_req_buffer(); - unsigned int max, pos; + UNICODE_STRING nameW; - TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count ); - - if (reserved) return ERROR_INVALID_PARAMETER; - - if (count && type == REG_SZ) + if (count && is_string(type)) { LPCWSTR str = (LPCWSTR)data; /* if user forgot to count terminating null, add it (yes NT does this) */ @@ -584,24 +572,8 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, count += sizeof(WCHAR); } - req->hkey = hkey; - req->type = type; - req->total = count; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - - max = server_remaining( req->data ); - pos = 0; - while (pos < count) - { - unsigned int len = count - pos; - if (len > max) len = max; - req->offset = pos; - req->len = len; - memcpy( req->data, data + pos, len ); - if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break; - pos += len; - } - return ret; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) ); } @@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, * RegSetValueExA [ADVAPI32.169] */ DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, - CONST BYTE *data, DWORD count ) + CONST BYTE *data, DWORD count ) { - DWORD ret; - struct set_key_value_request *req = get_req_buffer(); - unsigned int max, pos; + UNICODE_STRING nameW; + ANSI_STRING nameA; + WCHAR *dataW = NULL; + NTSTATUS status; - TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count ); - - if (reserved) return ERROR_INVALID_PARAMETER; - - if (count && type == REG_SZ) + if (count && is_string(type)) { /* if user forgot to count terminating null, add it (yes NT does this) */ if (data[count-1] && !data[count]) count++; } + if (is_string( type )) /* need to convert to Unicode */ - count *= sizeof(WCHAR); - - req->hkey = hkey; - req->type = type; - req->total = count; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - - max = server_remaining( req->data ); - pos = 0; - while (pos < count) { - unsigned int len = count - pos; - if (len > max) len = max; - req->offset = pos; - req->len = len; - - if (is_string( type )) - memcpyAtoW( (LPWSTR)req->data, data + pos/sizeof(WCHAR), len/sizeof(WCHAR) ); - else - memcpy( req->data, data + pos, len ); - if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break; - pos += len; + DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 ); + if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) ))) + return ERROR_OUTOFMEMORY; + MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW ); + count = lenW * sizeof(WCHAR); + data = (BYTE *)dataW; } - return ret; + + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtSetValueKey( hkey, &nameW, 0, type, data, count ); + RtlFreeUnicodeString( &nameW ); + } + if (dataW) HeapFree( GetProcessHeap(), 0, dataW ); + return RtlNtStatusToDosError( status ); } @@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR * buffer is left untouched. The MS-documentation is wrong (js) !!! */ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, - LPBYTE data, LPDWORD count ) + LPBYTE data, LPDWORD count ) { - DWORD ret; - struct get_key_value_request *req = get_req_buffer(); + NTSTATUS status; + UNICODE_STRING name_str; + DWORD total_size; + char buffer[256]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + static const int info_size = sizeof(*info) - sizeof(info->Data); TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 ); if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; - req->hkey = hkey; - req->offset = 0; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + RtlInitUnicodeString( &name_str, name ); + + if (data) total_size = min( sizeof(buffer), *count + info_size ); + else total_size = info_size; + + status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, + buffer, total_size, &total_size ); + if (status && status != STATUS_BUFFER_OVERFLOW) goto done; if (data) { - if (*count < req->len) ret = ERROR_MORE_DATA; - else + char *buf_ptr = buffer; + /* retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count) { - /* copy the data */ - unsigned int max = server_remaining( req->data ); - unsigned int pos = 0; - while (pos < req->len) + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); + if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) + status = STATUS_NO_MEMORY; + else + status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, + buf_ptr, total_size, &total_size ); + } + + if (!status) + { + memcpy( data, buf_ptr + info_size, total_size - info_size ); + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) { - unsigned int len = min( req->len - pos, max ); - memcpy( data + pos, req->data, len ); - if ((pos += len) >= req->len) break; - req->offset = pos; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + WCHAR *ptr = (WCHAR *)(data + total_size - info_size); + if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; } } - /* if the type is REG_SZ and data is not 0-terminated - * and there is enough space in the buffer NT appends a \0 */ - if (req->len && is_string(req->type) && - (req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0; + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); } - if (type) *type = req->type; - if (count) *count = req->len; - return ret; + + if (type) *type = info->Type; + if (count) *count = total_size - info_size; + + done: + return RtlNtStatusToDosError(status); } @@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR * the documentation is wrong: if the buffer is to small it remains untouched */ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, - LPBYTE data, LPDWORD count ) + LPBYTE data, LPDWORD count ) { - DWORD ret, total_len; - struct get_key_value_request *req = get_req_buffer(); + NTSTATUS status; + ANSI_STRING nameA; + UNICODE_STRING nameW; + DWORD total_size; + char buffer[256]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + static const int info_size = sizeof(*info) - sizeof(info->Data); TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; - req->hkey = hkey; - req->offset = 0; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done; - total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len; + status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, + buffer, sizeof(buffer), &total_size ); + if (status && status != STATUS_BUFFER_OVERFLOW) goto done; - if (data) + /* we need to fetch the contents for a string type even if not requested, + * because we need to compute the length of the ASCII string. */ + if (data || is_string(info->Type)) { - if (*count < total_len) ret = ERROR_MORE_DATA; - else + char *buf_ptr = buffer; + /* retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW) { - /* copy the data */ - unsigned int max = server_remaining( req->data ); - unsigned int pos = 0; - while (pos < req->len) + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); + if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) + status = STATUS_NO_MEMORY; + else + status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, + buf_ptr, total_size, &total_size ); + } + + if (!status) + { + if (is_string(info->Type)) { - unsigned int len = min( req->len - pos, max ); - if (is_string( req->type )) - memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) ); - else - memcpy( data + pos, req->data, len ); - if ((pos += len) >= req->len) break; - req->offset = pos; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size), + (total_size - info_size) /sizeof(WCHAR), + NULL, 0, NULL, NULL ); + if (data && len) + { + if (len > *count) status = STATUS_BUFFER_OVERFLOW; + else + { + WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size), + (total_size - info_size) /sizeof(WCHAR), + data, len, NULL, NULL ); + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (len < *count && data[len-1]) data[len] = 0; + } + } + total_size = len + info_size; + } + else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size ); + + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) + { + WCHAR *ptr = (WCHAR *)(data + total_size - info_size); + if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; } } - /* if the type is REG_SZ and data is not 0-terminated - * and there is enough space in the buffer NT appends a \0 */ - if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1]) - data[total_len] = 0; + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); } - if (count) *count = total_len; - if (type) *type = req->type; - return ret; + if (type) *type = info->Type; + if (count) *count = total_size - info_size; + RtlFreeUnicodeString( &nameW ); + + done: + return RtlNtStatusToDosError(status); } @@ -1011,14 +1023,9 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou */ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) { - DWORD ret; - struct delete_key_value_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); - - req->hkey = hkey; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - return reg_server_call( REQ_DELETE_KEY_VALUE ); + UNICODE_STRING nameW; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) ); } @@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) */ DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) { - DWORD ret; - struct delete_key_value_request *req = get_req_buffer(); + UNICODE_STRING nameW; + STRING nameA; + NTSTATUS status; - TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); - - req->hkey = hkey; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - return reg_server_call( REQ_DELETE_KEY_VALUE ); + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtDeleteValueKey( hkey, &nameW ); + RtlFreeUnicodeString( &nameW ); + } + return RtlNtStatusToDosError( status ); } diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c index ce264051248..41b3005abbb 100644 --- a/dlls/ntdll/reg.c +++ b/dlls/ntdll/reg.c @@ -1,5 +1,8 @@ /* - * registry functions + * Registry functions + * + * Copyright (C) 1999 Juergen Schmied + * Copyright (C) 2000 Alexandre Julliard * * NOTES: * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE @@ -26,21 +29,8 @@ static const UNICODE_STRING root_path = (LPWSTR)root_name /* Buffer */ }; -/* copy a key name into the request buffer */ -static NTSTATUS copy_key_name( LPWSTR dest, const UNICODE_STRING *name ) -{ - int len = name->Length, pos = 0; - - if (len >= MAX_PATH) return STATUS_BUFFER_OVERFLOW; - if (RtlPrefixUnicodeString( &root_path, name, TRUE )) - { - pos += root_path.Length / sizeof(WCHAR); - len -= root_path.Length; - } - if (len) memcpy( dest, name->Buffer + pos, len ); - dest[len / sizeof(WCHAR)] = 0; - return STATUS_SUCCESS; -} +/* maximum length of a key/value name in bytes (without terminating null) */ +#define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR)) /* copy a key name into the request buffer */ @@ -61,31 +51,41 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, PULONG dispos ) { - struct create_key_request *req = get_req_buffer(); NTSTATUS ret; + DWORD len = attr->ObjectName->Length; TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), debugstr_us(class), options, access, retkey ); - if (!retkey) return STATUS_INVALID_PARAMETER; - - req->parent = attr->RootDirectory; - req->access = access; - req->options = options; - req->modif = 0; - - if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret; - req->class[0] = 0; + if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW; + len += sizeof(WCHAR); /* for storing name length */ if (class) { - if ((ret = copy_nameU( req->class, class, server_remaining(req->class) ))) return ret; + len += class->Length; + if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW; } + if (!retkey) return STATUS_INVALID_PARAMETER; - if (!(ret = server_call_noerr( REQ_CREATE_KEY ))) + SERVER_START_REQ { - *retkey = req->hkey; - if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; + struct create_key_request *req = server_alloc_req( sizeof(*req), len ); + WCHAR *data = server_data_ptr(req); + + req->parent = attr->RootDirectory; + req->access = access; + req->options = options; + req->modif = 0; + + *data++ = attr->ObjectName->Length; + memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length ); + if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length ); + if (!(ret = server_call_noerr( REQ_CREATE_KEY ))) + { + *retkey = req->hkey; + if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; + } } + SERVER_END_REQ; return ret; } @@ -99,20 +99,25 @@ NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_AT */ NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) { - struct open_key_request *req = get_req_buffer(); NTSTATUS ret; + DWORD len = attr->ObjectName->Length; TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), access, retkey ); + if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW; if (!retkey) return STATUS_INVALID_PARAMETER; *retkey = 0; - req->parent = attr->RootDirectory; - req->access = access; - - if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret; - if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey; + SERVER_START_REQ + { + struct open_key_request *req = server_alloc_req( sizeof(*req), len ); + req->parent = attr->RootDirectory; + req->access = access; + memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len ); + if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey; + } + SERVER_END_REQ; return ret; } @@ -123,12 +128,18 @@ NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTR */ NTSTATUS WINAPI NtDeleteKey( HANDLE hkey ) { - struct delete_key_request *req = get_req_buffer(); + NTSTATUS ret; TRACE( "(%x)\n", hkey ); - req->hkey = hkey; - req->name[0] = 0; - return server_call_noerr( REQ_DELETE_KEY ); + + SERVER_START_REQ + { + struct delete_key_request *req = server_alloc_req( sizeof(*req), 0 ); + req->hkey = hkey; + ret = server_call_noerr( REQ_DELETE_KEY ); + } + SERVER_END_REQ; + return ret; } @@ -139,13 +150,19 @@ NTSTATUS WINAPI NtDeleteKey( HANDLE hkey ) NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name ) { NTSTATUS ret; - struct delete_key_value_request *req = get_req_buffer(); TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) ); + if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW; - req->hkey = hkey; - if (!(ret = copy_nameU( req->name, name, MAX_PATH ))) + SERVER_START_REQ + { + struct delete_key_value_request *req = server_alloc_req( sizeof(*req), name->Length ); + + req->hkey = hkey; + memcpy( server_data_ptr(req), name->Buffer, name->Length ); ret = server_call_noerr( REQ_DELETE_KEY_VALUE ); + } + SERVER_END_REQ; return ret; } @@ -468,70 +485,113 @@ NTSTATUS WINAPI NtQueryMultipleValueKey( * NOTES * the name in the KeyValueInformation is never set */ -NTSTATUS WINAPI NtQueryValueKey( - IN HANDLE KeyHandle, - IN PUNICODE_STRING ValueName, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - OUT PVOID KeyValueInformation, - IN ULONG Length, - OUT PULONG ResultLength) +NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name, + KEY_VALUE_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) { - struct get_key_value_request *req = get_req_buffer(); - NTSTATUS ret; - TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n", - KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength); - req->hkey = KeyHandle; - if (copy_nameU(req->name, ValueName, MAX_PATH) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW; - if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret; + NTSTATUS ret; + char *data_ptr; + int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0; - switch(KeyValueInformationClass) - { - case KeyValueBasicInformation: - { - PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation; - kbi->Type = req->type; + TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length ); - *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR); - if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; - kbi->NameLength = 0; - } - break; - case KeyValueFullInformation: - { - PKEY_VALUE_FULL_INFORMATION kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation; - ULONG DataOffset; - kfi->Type = req->type; + if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW; - DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR); - *ResultLength = DataOffset + req->len; - if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; + /* compute the length we want to retrieve */ + switch(info_class) + { + case KeyValueBasicInformation: + fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR); + data_ptr = NULL; + break; + case KeyValueFullInformation: + fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR); + data_ptr = (char *)info + fixed_size; + break; + case KeyValuePartialInformation: + fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR); + data_ptr = (char *)info + fixed_size; + break; + default: + FIXME( "Information class %d not implemented\n", info_class ); + return STATUS_INVALID_PARAMETER; + } + if (data_ptr && length > fixed_size) data_len = length - fixed_size; - kfi->NameLength = 0; - kfi->DataOffset = DataOffset; - kfi->DataLength = req->len; - memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len); - } - break; - case KeyValuePartialInformation: - { - PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation; - kpi->Type = req->type; + do + { + size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE ); + reqlen = max( reqlen, name->Length ); - *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len; - if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW; + SERVER_START_REQ + { + struct get_key_value_request *req = server_alloc_req( sizeof(*req), reqlen ); + WCHAR *nameptr = server_data_ptr(req); - kpi->DataLength = req->len; - memcpy(kpi->Data, req->data, req->len); - } - break; - default: - FIXME("KeyValueInformationClass not implemented\n"); - return STATUS_UNSUCCESSFUL; - - } - return ret; + req->hkey = handle; + req->offset = offset; + *nameptr++ = name->Length; + memcpy( nameptr, name->Buffer, name->Length ); + + if (!(ret = server_call_noerr( REQ_GET_KEY_VALUE ))) + { + size_t size = min( server_data_size(req), data_len ); + type = req->type; + total_len = req->len; + if (size) + { + memcpy( data_ptr + offset, server_data_ptr(req), size ); + offset += size; + data_len -= size; + } + } + } + SERVER_END_REQ; + if (ret) return ret; + } while (data_len && offset < total_len); + + *result_len = total_len + fixed_size; + + if (!data_len) ret = STATUS_BUFFER_OVERFLOW; + if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW; + + switch(info_class) + { + case KeyValueBasicInformation: + { + KEY_VALUE_BASIC_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.NameLength = 0; + memcpy( info, &keyinfo, min(fixed_size,length) ); + break; + } + case KeyValueFullInformation: + { + KEY_VALUE_FULL_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.DataOffset = fixed_size; + keyinfo.DataLength = total_len; + keyinfo.NameLength = 0; + memcpy( info, &keyinfo, min(fixed_size,length) ); + break; + } + case KeyValuePartialInformation: + { + KEY_VALUE_PARTIAL_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.DataLength = total_len; + memcpy( info, &keyinfo, min(fixed_size,length) ); + break; + } + default: + break; + } + return ret; } /****************************************************************************** @@ -587,22 +647,52 @@ NTSTATUS WINAPI NtSetInformationKey( KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength); return STATUS_SUCCESS; } + + /****************************************************************************** * NtSetValueKey [NTDLL] * ZwSetValueKey + * + * NOTES + * win95 does not care about count for REG_SZ and finds out the len by itself (js) + * NT does definitely care (aj) */ -NTSTATUS WINAPI NtSetValueKey( - HANDLE KeyHandle, - PUNICODE_STRING ValueName, - ULONG TitleIndex, - ULONG Type, - PVOID Data, - ULONG DataSize) +NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex, + ULONG type, const void *data, ULONG count ) { - FIXME("(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n", - KeyHandle, ValueName,debugstr_us(ValueName), TitleIndex, Type, Data, DataSize); - return STATUS_SUCCESS; + NTSTATUS ret; + ULONG namelen, pos; + TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count ); + + if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW; + + namelen = name->Length + sizeof(WCHAR); /* for storing length */ + pos = 0; + + do + { + ULONG len = count - pos; + if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen; + + SERVER_START_REQ + { + struct set_key_value_request *req = server_alloc_req( sizeof(*req), namelen + len ); + WCHAR *name_ptr = server_data_ptr(req); + + req->hkey = hkey; + req->type = type; + req->total = count; + req->offset = pos; + *name_ptr++ = name->Length; + memcpy( name_ptr, name->Buffer, name->Length ); + memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len ); + pos += len; + ret = server_call_noerr( REQ_SET_KEY_VALUE ); + } + SERVER_END_REQ; + } while (!ret && pos < count); + return ret; } /****************************************************************************** diff --git a/include/server.h b/include/server.h index a9fbd62815c..f9255fe962c 100644 --- a/include/server.h +++ b/include/server.h @@ -1018,11 +1018,10 @@ struct create_key_request IN time_t modif; /* last modification time */ OUT int hkey; /* handle to the created key */ OUT int created; /* has it been newly created? */ - IN path_t name; /* key name */ - IN WCHAR class[1]; /* class name */ + IN VARARG(name,unicode_len_str); /* key name */ + IN VARARG(class,unicode_str); /* class name */ }; - /* Open a registry key */ struct open_key_request { @@ -1030,7 +1029,7 @@ struct open_key_request IN int parent; /* handle to the parent key */ IN unsigned int access; /* desired access rights */ OUT int hkey; /* handle to the open key */ - IN path_t name; /* key name */ + IN VARARG(name,unicode_str); /* key name */ }; @@ -1038,16 +1037,7 @@ struct open_key_request struct delete_key_request { REQUEST_HEADER; /* request header */ - IN int hkey; /* handle to the parent key */ - IN path_t name; /* key name */ -}; - - -/* Close a registry key */ -struct close_key_request -{ - REQUEST_HEADER; /* request header */ - IN int hkey; /* key to close */ + IN int hkey; /* handle to the key */ }; @@ -1088,9 +1078,8 @@ struct set_key_value_request IN int type; /* value type */ IN unsigned int total; /* total value len */ IN unsigned int offset; /* offset for setting data */ - IN unsigned int len; /* value data len */ - IN path_t name; /* value name */ - IN unsigned char data[1]; /* value data */ + IN VARARG(name,unicode_len_str); /* value name */ + IN VARARG(data,bytes); /* value data */ }; @@ -1102,8 +1091,8 @@ struct get_key_value_request IN unsigned int offset; /* offset for getting data */ OUT int type; /* value type */ OUT int len; /* value data len */ - IN WCHAR name[1]; /* value name */ - OUT unsigned char data[1]; /* value data */ + IN VARARG(name,unicode_len_str); /* value name */ + OUT VARARG(data,bytes); /* value data */ }; @@ -1126,7 +1115,7 @@ struct delete_key_value_request { REQUEST_HEADER; /* request header */ IN int hkey; /* handle to registry key */ - IN path_t name; /* value name */ + IN VARARG(name,unicode_str); /* value name */ }; @@ -1439,7 +1428,6 @@ enum request REQ_CREATE_KEY, REQ_OPEN_KEY, REQ_DELETE_KEY, - REQ_CLOSE_KEY, REQ_ENUM_KEY, REQ_QUERY_KEY_INFO, REQ_SET_KEY_VALUE, @@ -1556,7 +1544,6 @@ union generic_request struct create_key_request create_key; struct open_key_request open_key; struct delete_key_request delete_key; - struct close_key_request close_key; struct enum_key_request enum_key; struct query_key_info_request query_key_info; struct set_key_value_request set_key_value; @@ -1587,7 +1574,7 @@ union generic_request struct set_serial_info_request set_serial_info; }; -#define SERVER_PROTOCOL_VERSION 23 +#define SERVER_PROTOCOL_VERSION 24 /* ### make_requests end ### */ /* Everything above this line is generated automatically by tools/make_requests */ diff --git a/memory/registry.c b/memory/registry.c index 2fe167860a1..fca82b169dd 100644 --- a/memory/registry.c +++ b/memory/registry.c @@ -29,14 +29,6 @@ DEFAULT_DEBUG_CHANNEL(reg); -/* Ansi->Unicode conversion without string delimiters */ -static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n ) -{ - LPWSTR p = dst; - while (n-- > 0) *p++ = (WCHAR)*src++; - return dst; -} - /* Unicode->Ansi conversion without string delimiters */ static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n ) { @@ -104,29 +96,23 @@ DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR cl DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, LPHKEY retkey, LPDWORD dispos ) { - DWORD ret; - struct create_key_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved, - debugstr_w(class), options, access, sa, retkey, dispos ); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW, classW; if (reserved) return ERROR_INVALID_PARAMETER; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; - req->parent = hkey; - req->access = access; - req->options = options; - req->modif = time(NULL); - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0", - server_remaining(req->class) / sizeof(WCHAR) ); - if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS) - { - *retkey = req->hkey; - if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; - } - return ret; + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, name ); + RtlInitUnicodeString( &classW, class ); + + return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0, + &classW, options, dispos ) ); } @@ -137,29 +123,34 @@ DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR clas DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, LPHKEY retkey, LPDWORD dispos ) { - DWORD ret; - struct create_key_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved, - debugstr_a(class), options, access, sa, retkey, dispos ); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW, classW; + ANSI_STRING nameA, classA; + NTSTATUS status; if (reserved) return ERROR_INVALID_PARAMETER; if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED; - req->parent = hkey; - req->access = access; - req->options = options; - req->modif = time(NULL); - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - lstrcpynAtoW( req->class, class ? class : "", - server_remaining(req->class) / sizeof(WCHAR) ); - if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS) + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitAnsiString( &nameA, name ); + RtlInitAnsiString( &classA, class ); + + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) { - *retkey = req->hkey; - if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; + if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) + { + status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos ); + RtlFreeUnicodeString( &classW ); + } + RtlFreeUnicodeString( &nameW ); } - return ret; + return RtlNtStatusToDosError( status ); } @@ -209,20 +200,17 @@ DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey ) */ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) { - DWORD ret; - struct open_key_request *req = get_req_buffer(); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; - TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey ); - - if (!retkey) return ERROR_INVALID_PARAMETER; - *retkey = 0; - - req->parent = hkey; - req->access = access; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; - return ret; + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) ); } @@ -231,20 +219,26 @@ DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM acce */ DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey ) { - DWORD ret; - struct open_key_request *req = get_req_buffer(); + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + STRING nameA; + NTSTATUS status; - TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey ); + attr.Length = sizeof(attr); + attr.RootDirectory = hkey; + attr.ObjectName = &nameW; + attr.Attributes = 0; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; - if (!retkey) return ERROR_INVALID_PARAMETER; - *retkey = 0; - - req->parent = hkey; - req->access = access; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey; - return ret; + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtOpenKey( retkey, access, &attr ); + RtlFreeUnicodeString( &nameW ); + } + return RtlNtStatusToDosError( status ); } @@ -494,10 +488,8 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR */ DWORD WINAPI RegCloseKey( HKEY hkey ) { - struct close_key_request *req = get_req_buffer(); - TRACE( "(0x%x)\n", hkey ); - req->hkey = hkey; - return reg_server_call( REQ_CLOSE_KEY ); + if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS; + return RtlNtStatusToDosError( NtClose( hkey ) ); } @@ -515,14 +507,15 @@ DWORD WINAPI RegCloseKey( HKEY hkey ) DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) { DWORD ret; - struct delete_key_request *req = get_req_buffer(); + HKEY tmp; - TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); - - req->hkey = hkey; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - return reg_server_call( REQ_DELETE_KEY ); + if (!name || !*name) return NtDeleteKey( hkey ); + if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp ))) + { + ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); + RegCloseKey( tmp ); + } + return ret; } @@ -532,14 +525,15 @@ DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) { DWORD ret; - struct delete_key_request *req = get_req_buffer(); + HKEY tmp; - TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); - - req->hkey = hkey; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if (req->name[0] == '\\') return ERROR_BAD_PATHNAME; - return reg_server_call( REQ_DELETE_KEY ); + if (!name || !*name) return NtDeleteKey( hkey ); + if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp ))) + { + ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); + RegCloseKey( tmp ); + } + return ret; } @@ -568,15 +562,9 @@ DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, DWORD type, CONST BYTE *data, DWORD count ) { - DWORD ret; - struct set_key_value_request *req = get_req_buffer(); - unsigned int max, pos; + UNICODE_STRING nameW; - TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count ); - - if (reserved) return ERROR_INVALID_PARAMETER; - - if (count && type == REG_SZ) + if (count && is_string(type)) { LPCWSTR str = (LPCWSTR)data; /* if user forgot to count terminating null, add it (yes NT does this) */ @@ -584,24 +572,8 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, count += sizeof(WCHAR); } - req->hkey = hkey; - req->type = type; - req->total = count; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - - max = server_remaining( req->data ); - pos = 0; - while (pos < count) - { - unsigned int len = count - pos; - if (len > max) len = max; - req->offset = pos; - req->len = len; - memcpy( req->data, data + pos, len ); - if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break; - pos += len; - } - return ret; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) ); } @@ -609,46 +581,38 @@ DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, * RegSetValueExA [ADVAPI32.169] */ DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, - CONST BYTE *data, DWORD count ) + CONST BYTE *data, DWORD count ) { - DWORD ret; - struct set_key_value_request *req = get_req_buffer(); - unsigned int max, pos; + UNICODE_STRING nameW; + ANSI_STRING nameA; + WCHAR *dataW = NULL; + NTSTATUS status; - TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count ); - - if (reserved) return ERROR_INVALID_PARAMETER; - - if (count && type == REG_SZ) + if (count && is_string(type)) { /* if user forgot to count terminating null, add it (yes NT does this) */ if (data[count-1] && !data[count]) count++; } + if (is_string( type )) /* need to convert to Unicode */ - count *= sizeof(WCHAR); - - req->hkey = hkey; - req->type = type; - req->total = count; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - - max = server_remaining( req->data ); - pos = 0; - while (pos < count) { - unsigned int len = count - pos; - if (len > max) len = max; - req->offset = pos; - req->len = len; - - if (is_string( type )) - memcpyAtoW( (LPWSTR)req->data, data + pos/sizeof(WCHAR), len/sizeof(WCHAR) ); - else - memcpy( req->data, data + pos, len ); - if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break; - pos += len; + DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 ); + if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) ))) + return ERROR_OUTOFMEMORY; + MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW ); + count = lenW * sizeof(WCHAR); + data = (BYTE *)dataW; } - return ret; + + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtSetValueKey( hkey, &nameW, 0, type, data, count ); + RtlFreeUnicodeString( &nameW ); + } + if (dataW) HeapFree( GetProcessHeap(), 0, dataW ); + return RtlNtStatusToDosError( status ); } @@ -720,47 +684,62 @@ DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWOR * buffer is left untouched. The MS-documentation is wrong (js) !!! */ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, - LPBYTE data, LPDWORD count ) + LPBYTE data, LPDWORD count ) { - DWORD ret; - struct get_key_value_request *req = get_req_buffer(); + NTSTATUS status; + UNICODE_STRING name_str; + DWORD total_size; + char buffer[256]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + static const int info_size = sizeof(*info) - sizeof(info->Data); TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 ); if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; - req->hkey = hkey; - req->offset = 0; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + RtlInitUnicodeString( &name_str, name ); + + if (data) total_size = min( sizeof(buffer), *count + info_size ); + else total_size = info_size; + + status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, + buffer, total_size, &total_size ); + if (status && status != STATUS_BUFFER_OVERFLOW) goto done; if (data) { - if (*count < req->len) ret = ERROR_MORE_DATA; - else + char *buf_ptr = buffer; + /* retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count) { - /* copy the data */ - unsigned int max = server_remaining( req->data ); - unsigned int pos = 0; - while (pos < req->len) + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); + if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) + status = STATUS_NO_MEMORY; + else + status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, + buf_ptr, total_size, &total_size ); + } + + if (!status) + { + memcpy( data, buf_ptr + info_size, total_size - info_size ); + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) { - unsigned int len = min( req->len - pos, max ); - memcpy( data + pos, req->data, len ); - if ((pos += len) >= req->len) break; - req->offset = pos; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + WCHAR *ptr = (WCHAR *)(data + total_size - info_size); + if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; } } - /* if the type is REG_SZ and data is not 0-terminated - * and there is enough space in the buffer NT appends a \0 */ - if (req->len && is_string(req->type) && - (req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0; + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); } - if (type) *type = req->type; - if (count) *count = req->len; - return ret; + + if (type) *type = info->Type; + if (count) *count = total_size - info_size; + + done: + return RtlNtStatusToDosError(status); } @@ -771,53 +750,86 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR * the documentation is wrong: if the buffer is to small it remains untouched */ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, - LPBYTE data, LPDWORD count ) + LPBYTE data, LPDWORD count ) { - DWORD ret, total_len; - struct get_key_value_request *req = get_req_buffer(); + NTSTATUS status; + ANSI_STRING nameA; + UNICODE_STRING nameW; + DWORD total_size; + char buffer[256]; + KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; + static const int info_size = sizeof(*info) - sizeof(info->Data); TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; - req->hkey = hkey; - req->offset = 0; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done; - total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len; + status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, + buffer, sizeof(buffer), &total_size ); + if (status && status != STATUS_BUFFER_OVERFLOW) goto done; - if (data) + /* we need to fetch the contents for a string type even if not requested, + * because we need to compute the length of the ASCII string. */ + if (data || is_string(info->Type)) { - if (*count < total_len) ret = ERROR_MORE_DATA; - else + char *buf_ptr = buffer; + /* retry with a dynamically allocated buffer */ + while (status == STATUS_BUFFER_OVERFLOW) { - /* copy the data */ - unsigned int max = server_remaining( req->data ); - unsigned int pos = 0; - while (pos < req->len) + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); + if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) + status = STATUS_NO_MEMORY; + else + status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation, + buf_ptr, total_size, &total_size ); + } + + if (!status) + { + if (is_string(info->Type)) { - unsigned int len = min( req->len - pos, max ); - if (is_string( req->type )) - memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) ); - else - memcpy( data + pos, req->data, len ); - if ((pos += len) >= req->len) break; - req->offset = pos; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret; + DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size), + (total_size - info_size) /sizeof(WCHAR), + NULL, 0, NULL, NULL ); + if (data && len) + { + if (len > *count) status = STATUS_BUFFER_OVERFLOW; + else + { + WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size), + (total_size - info_size) /sizeof(WCHAR), + data, len, NULL, NULL ); + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (len < *count && data[len-1]) data[len] = 0; + } + } + total_size = len + info_size; + } + else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size ); + + /* if the type is REG_SZ and data is not 0-terminated + * and there is enough space in the buffer NT appends a \0 */ + if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) + { + WCHAR *ptr = (WCHAR *)(data + total_size - info_size); + if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; } } - /* if the type is REG_SZ and data is not 0-terminated - * and there is enough space in the buffer NT appends a \0 */ - if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1]) - data[total_len] = 0; + if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); } - if (count) *count = total_len; - if (type) *type = req->type; - return ret; + if (type) *type = info->Type; + if (count) *count = total_size - info_size; + RtlFreeUnicodeString( &nameW ); + + done: + return RtlNtStatusToDosError(status); } @@ -1011,14 +1023,9 @@ DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_cou */ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) { - DWORD ret; - struct delete_key_value_request *req = get_req_buffer(); - - TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) ); - - req->hkey = hkey; - if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret; - return reg_server_call( REQ_DELETE_KEY_VALUE ); + UNICODE_STRING nameW; + RtlInitUnicodeString( &nameW, name ); + return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) ); } @@ -1027,14 +1034,18 @@ DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) */ DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) { - DWORD ret; - struct delete_key_value_request *req = get_req_buffer(); + UNICODE_STRING nameW; + STRING nameA; + NTSTATUS status; - TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) ); - - req->hkey = hkey; - if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret; - return reg_server_call( REQ_DELETE_KEY_VALUE ); + RtlInitAnsiString( &nameA, name ); + /* FIXME: should use Unicode buffer in TEB */ + if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) + { + status = NtDeleteValueKey( hkey, &nameW ); + RtlFreeUnicodeString( &nameW ); + } + return RtlNtStatusToDosError( status ); } diff --git a/server/registry.c b/server/registry.c index 33b21c989c1..8d355c57fbc 100644 --- a/server/registry.c +++ b/server/registry.c @@ -286,51 +286,66 @@ static void key_destroy( struct object *obj ) /* duplicate a key path from the request buffer */ /* returns a pointer to a static buffer, so only useable once per request */ -static WCHAR *copy_path( const path_t path ) +static WCHAR *copy_path( const WCHAR *path, size_t len ) { static WCHAR buffer[MAX_PATH+1]; - WCHAR *p = buffer; - while (p < buffer + sizeof(buffer) - 1) if (!(*p++ = *path++)) break; - *p = 0; + if (len > sizeof(buffer)-sizeof(buffer[0])) + { + set_error( STATUS_BUFFER_OVERFLOW ); + return NULL; + } + memcpy( buffer, path, len ); + buffer[len / sizeof(WCHAR)] = 0; return buffer; } +/* copy a path from the request buffer, in cases where the length is stored in front of the path */ +static WCHAR *copy_req_path( void *req, size_t *len ) +{ + const WCHAR *name_ptr = get_req_data(req); + if ((*len = sizeof(WCHAR) + *name_ptr++) > get_req_data_size(req)) + { + fatal_protocol_error( current, "copy_req_path: invalid length %d/%d\n", + *len, get_req_data_size(req) ); + return NULL; + } + return copy_path( name_ptr, *len - sizeof(WCHAR) ); +} + /* return the next token in a given path */ /* returns a pointer to a static buffer, so only useable once per request */ -static WCHAR *get_path_token( const WCHAR *initpath, size_t maxlen ) +static WCHAR *get_path_token( WCHAR *initpath ) { - static const WCHAR *path; - static const WCHAR *end; - static WCHAR buffer[MAX_PATH+1]; - WCHAR *p = buffer; + static WCHAR *path; + WCHAR *ret; if (initpath) { + /* path cannot start with a backslash */ + if (*initpath == '\\') + { + set_error( STATUS_OBJECT_PATH_INVALID ); + return NULL; + } path = initpath; - end = path + maxlen / sizeof(WCHAR); } - while ((path < end) && (*path == '\\')) path++; - while ((path < end) && (p < buffer + sizeof(buffer) - 1)) - { - WCHAR ch = *path; - if (!ch || (ch == '\\')) break; - *p++ = ch; - path++; - } - *p = 0; - return buffer; + else while (*path == '\\') path++; + + ret = path; + while (*path && *path != '\\') path++; + if (*path) *path++ = 0; + return ret; } /* duplicate a Unicode string from the request buffer */ -static WCHAR *req_strdupW( const void *req, const WCHAR *str ) +static WCHAR *req_strdupW( const void *req, const WCHAR *str, size_t len ) { WCHAR *name; - size_t len = get_req_strlenW( req, str ); - if ((name = mem_alloc( (len + 1) * sizeof(WCHAR) )) != NULL) + if ((name = mem_alloc( len + sizeof(WCHAR) )) != NULL) { - memcpy( name, str, len * sizeof(WCHAR) ); - name[len] = 0; + memcpy( name, str, len ); + name[len / sizeof(WCHAR)] = 0; } return name; } @@ -466,12 +481,13 @@ static struct key *find_subkey( struct key *key, const WCHAR *name, int *index ) } /* open a subkey */ -static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen ) +/* warning: the key name must be writeable (use copy_path) */ +static struct key *open_key( struct key *key, WCHAR *name ) { int index; WCHAR *path; - path = get_path_token( name, maxlen ); + if (!(path = get_path_token( name ))) return NULL; while (*path) { if (!(key = find_subkey( key, path, &index ))) @@ -479,7 +495,7 @@ static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen ) set_error( STATUS_OBJECT_NAME_NOT_FOUND ); break; } - path = get_path_token( NULL, 0 ); + path = get_path_token( NULL ); } if (debug_level > 1) dump_operation( key, NULL, "Open" ); @@ -488,7 +504,8 @@ static struct key *open_key( struct key *key, const WCHAR *name, size_t maxlen ) } /* create a subkey */ -static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen, WCHAR *class, +/* warning: the key name must be writeable (use copy_path) */ +static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class, unsigned int options, time_t modif, int *created ) { struct key *base; @@ -508,14 +525,14 @@ static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen } if (!modif) modif = time(NULL); - path = get_path_token( name, maxlen ); + if (!(path = get_path_token( name ))) return NULL; *created = 0; while (*path) { struct key *subkey; if (!(subkey = find_subkey( key, path, &index ))) break; key = subkey; - path = get_path_token( NULL, 0 ); + path = get_path_token( NULL ); } /* create the remaining part */ @@ -528,7 +545,7 @@ static struct key *create_key( struct key *key, const WCHAR *name, size_t maxlen while (key) { key->flags |= flags; - path = get_path_token( NULL, 0 ); + path = get_path_token( NULL ); if (!*path) goto done; /* we know the index is always 0 in a new key */ key = alloc_subkey( key, path, 0, modif ); @@ -597,40 +614,25 @@ static void query_key( struct key *key, struct query_key_info_request *req ) } /* delete a key and its values */ -static void delete_key( struct key *key, const WCHAR *name, size_t maxlen ) +static void delete_key( struct key *key ) { int index; struct key *parent; - WCHAR *path; - path = get_path_token( name, maxlen ); - if (!*path) + /* must find parent and index */ + if (key->flags & KEY_ROOT) { - /* deleting this key, must find parent and index */ - if (key->flags & KEY_ROOT) - { - set_error( STATUS_ACCESS_DENIED ); - return; - } - if (!(parent = key->parent) || (key->flags & KEY_DELETED)) - { - set_error( STATUS_KEY_DELETED ); - return; - } - for (index = 0; index <= parent->last_subkey; index++) - if (parent->subkeys[index] == key) break; - assert( index <= parent->last_subkey ); + set_error( STATUS_ACCESS_DENIED ); + return; } - else while (*path) + if (!(parent = key->parent) || (key->flags & KEY_DELETED)) { - parent = key; - if (!(key = find_subkey( parent, path, &index ))) - { - set_error( STATUS_OBJECT_NAME_NOT_FOUND ); - return; - } - path = get_path_token( NULL, 0 ); + set_error( STATUS_KEY_DELETED ); + return; } + for (index = 0; index <= parent->last_subkey; index++) + if (parent->subkeys[index] == key) break; + assert( index <= parent->last_subkey ); /* we can only delete a key that has no subkeys (FIXME) */ if ((key->flags & KEY_ROOT) || (key->last_subkey >= 0)) @@ -716,7 +718,7 @@ static struct key_value *insert_value( struct key *key, const WCHAR *name ) /* set a key value */ static void set_value( struct key *key, WCHAR *name, int type, unsigned int total_len, - unsigned int offset, unsigned int data_len, void *data ) + unsigned int offset, unsigned int data_len, const void *data ) { struct key_value *value; void *ptr = NULL; @@ -767,11 +769,12 @@ static void set_value( struct key *key, WCHAR *name, int type, unsigned int tota } /* get a key value */ -static void get_value( struct key *key, WCHAR *name, unsigned int offset, - unsigned int maxlen, int *type, int *len, void *data ) +static size_t get_value( struct key *key, WCHAR *name, unsigned int offset, + unsigned int maxlen, int *type, int *len, void *data ) { struct key_value *value; int index; + size_t ret = 0; if ((value = find_value( key, name, &index ))) { @@ -781,6 +784,7 @@ static void get_value( struct key *key, WCHAR *name, unsigned int offset, { if (maxlen > value->len - offset) maxlen = value->len - offset; memcpy( data, (char *)value->data + offset, maxlen ); + ret = maxlen; } if (debug_level > 1) dump_operation( key, value, "Get" ); } @@ -789,6 +793,7 @@ static void get_value( struct key *key, WCHAR *name, unsigned int offset, *type = -1; set_error( STATUS_OBJECT_NAME_NOT_FOUND ); } + return ret; } /* enumerate a key value */ @@ -871,7 +876,7 @@ static struct key *create_root_key( int hkey ) } keyname[i++] = 0; - if ((key = create_key( root_key, keyname, i*sizeof(WCHAR), NULL, 0, time(NULL), &dummy ))) + if ((key = create_key( root_key, keyname, NULL, 0, time(NULL), &dummy ))) { special_root_keys[hkey - HKEY_SPECIAL_ROOT_FIRST] = key; key->flags |= KEY_ROOT; @@ -1047,7 +1052,7 @@ static int get_data_type( const char *buffer, int *type, int *parse_type ) static struct key *load_key( struct key *base, const char *buffer, unsigned int options, int prefix_len, struct file_load_info *info ) { - WCHAR *p; + WCHAR *p, *name; int res, len, modif; len = strlen(buffer) * sizeof(WCHAR); @@ -1073,7 +1078,12 @@ static struct key *load_key( struct key *base, const char *buffer, unsigned int /* empty key name, return base key */ return (struct key *)grab_object( base ); } - return create_key( base, p, len - ((char *)p - info->tmp), NULL, options, modif, &res ); + if (!(name = copy_path( p, len - ((char *)p - info->tmp) ))) + { + file_read_error( "Key is too long", info ); + return NULL; + } + return create_key( base, name, NULL, options, modif, &res ); } /* parse a comma-separated list of hex digits */ @@ -1325,7 +1335,7 @@ void init_registry(void) int dummy; /* create the config key */ - if (!(key = create_key( root_key, config_name, sizeof(config_name), + if (!(key = create_key( root_key, copy_path( config_name, sizeof(config_name) ), NULL, 0, time(NULL), &dummy ))) fatal_error( "could not create config key\n" ); key->flags |= KEY_VOLATILE; @@ -1520,23 +1530,37 @@ void close_registry(void) /* create a registry key */ DECL_HANDLER(create_key) { - struct key *key, *parent; - WCHAR *class; + struct key *key = NULL, *parent; unsigned int access = req->access; + WCHAR *name, *class; + size_t len; if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS; /* FIXME: needs general solution */ req->hkey = -1; if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ ))) { - if ((class = req_strdupW( req, req->class ))) + if ((name = copy_req_path( req, &len ))) { - if ((key = create_key( parent, req->name, sizeof(req->name), class, req->options, - req->modif, &req->created ))) + if (len == get_req_data_size(req)) /* no class specified */ + { + key = create_key( parent, name, NULL, req->options, req->modif, &req->created ); + } + else + { + const WCHAR *class_ptr = (WCHAR *)((char *)get_req_data(req) + len); + + if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len ))) + { + key = create_key( parent, name, class, req->options, + req->modif, &req->created ); + free( class ); + } + } + if (key) { req->hkey = alloc_handle( current->process, key, access, 0 ); release_object( key ); } - free( class ); } release_object( parent ); } @@ -1552,7 +1576,8 @@ DECL_HANDLER(open_key) req->hkey = -1; if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ ))) { - if ((key = open_key( parent, req->name, sizeof(req->name) ))) + WCHAR *name = copy_path( get_req_data(req), get_req_data_size(req) ); + if (name && (key = open_key( parent, name ))) { req->hkey = alloc_handle( current->process, key, access, 0 ); release_object( key ); @@ -1568,19 +1593,11 @@ DECL_HANDLER(delete_key) if ((key = get_hkey_obj( req->hkey, 0 /*FIXME*/ ))) { - delete_key( key, req->name, sizeof(req->name) ); + delete_key( key ); release_object( key ); } } -/* close a registry key */ -DECL_HANDLER(close_key) -{ - int hkey = req->hkey; - /* ignore attempts to close a root key */ - if (hkey && !IS_SPECIAL_ROOT_HKEY(hkey)) close_handle( current->process, hkey ); -} - /* enumerate registry subkeys */ DECL_HANDLER(enum_key) { @@ -1611,14 +1628,18 @@ DECL_HANDLER(query_key_info) DECL_HANDLER(set_key_value) { struct key *key; - unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) ); - unsigned int datalen = req->len; + WCHAR *name; + size_t len; - if (datalen > max) datalen = max; if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE ))) { - set_value( key, copy_path( req->name ), req->type, req->total, - req->offset, datalen, req->data ); + if ((name = copy_req_path( req, &len ))) + { + size_t datalen = get_req_data_size(req) - len; + const char *data = (char *)get_req_data(req) + len; + + set_value( key, name, req->type, req->total, req->offset, datalen, data ); + } release_object( key ); } } @@ -1627,13 +1648,18 @@ DECL_HANDLER(set_key_value) DECL_HANDLER(get_key_value) { struct key *key; - unsigned int max = get_req_size( req, req->data, sizeof(req->data[0]) ); + WCHAR *name; + size_t len; req->len = 0; if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE ))) { - get_value( key, copy_path( req->name ), req->offset, max, - &req->type, &req->len, req->data ); + if ((name = copy_req_path( req, &len ))) + { + len = get_value( key, name, req->offset, get_req_data_size(req), + &req->type, &req->len, get_req_data(req) ); + set_req_data_size( req, len ); + } release_object( key ); } } @@ -1662,7 +1688,7 @@ DECL_HANDLER(delete_key_value) if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE ))) { - if ((name = req_strdupW( req, req->name ))) + if ((name = req_strdupW( req, get_req_data(req), get_req_data_size(req) ))) { delete_value( key, name ); free( name ); diff --git a/server/request.h b/server/request.h index 975330ce466..738b4d070cb 100644 --- a/server/request.h +++ b/server/request.h @@ -175,7 +175,6 @@ DECL_HANDLER(write_process_memory); DECL_HANDLER(create_key); DECL_HANDLER(open_key); DECL_HANDLER(delete_key); -DECL_HANDLER(close_key); DECL_HANDLER(enum_key); DECL_HANDLER(query_key_info); DECL_HANDLER(set_key_value); @@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_create_key, (req_handler)req_open_key, (req_handler)req_delete_key, - (req_handler)req_close_key, (req_handler)req_enum_key, (req_handler)req_query_key_info, (req_handler)req_set_key_value, diff --git a/server/trace.c b/server/trace.c index 9bbd3387d03..bc3e4ff4914 100644 --- a/server/trace.c +++ b/server/trace.c @@ -15,9 +15,20 @@ #include "request.h" #include "unicode.h" +static int cur_pos; /* utility functions */ +static const void *get_data( const void *req ) +{ + return (char *)get_req_data(req) + cur_pos; +} + +static size_t get_size( const void *req ) +{ + return get_req_data_size(req) - cur_pos; +} + static void dump_uints( const int *ptr, int len ) { fputc( '{', stderr ); @@ -59,63 +70,8 @@ static void dump_path_t( const void *req, const path_t *path ) dump_unicode_string( req, *path ); } -static void dump_exc_record( const EXCEPTION_RECORD *rec ) +static void dump_context( const CONTEXT *context ) { - int i; - fprintf( stderr, "{code=%lx,flags=%lx,rec=%p,addr=%p,params={", - rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionRecord, - rec->ExceptionAddress ); - for (i = 0; i < rec->NumberParameters; i++) - { - if (i) fputc( ',', stderr ); - fprintf( stderr, "%lx", rec->ExceptionInformation[i] ); - } - fputc( '}', stderr ); -} - -static void dump_varargs_ints( const void *ptr, size_t len ) -{ - const int *data = ptr; - len /= sizeof(*data); - - fputc( '{', stderr ); - while (len > 0) - { - fprintf( stderr, "%d", *data++ ); - if (--len) fputc( ',', stderr ); - } - fputc( '}', stderr ); -} - -static void dump_varargs_ptrs( const void *ptr, size_t len ) -{ - void * const *data = ptr; - len /= sizeof(*data); - - fputc( '{', stderr ); - while (len > 0) - { - fprintf( stderr, "%p", *data++ ); - if (--len) fputc( ',', stderr ); - } - fputc( '}', stderr ); -} - -static void dump_varargs_string( const void *ptr, size_t len ) -{ - fprintf( stderr, "\"%.*s\"", (int)len, (char *)ptr ); -} - -static void dump_varargs_unicode_str( const void *ptr, size_t len ) -{ - fprintf( stderr, "L\"" ); - dump_strW( ptr, len / sizeof(WCHAR), stderr, "\"\"" ); - fputc( '\"', stderr ); -} - -static void dump_varargs_context( const void *ptr, size_t len ) -{ - const CONTEXT *context = ptr; #ifdef __i386__ fprintf( stderr, "{flags=%08lx,eax=%08lx,ebx=%08lx,ecx=%08lx,edx=%08lx,esi=%08lx,edi=%08lx," "ebp=%08lx,eip=%08lx,esp=%08lx,eflags=%08lx,cs=%04lx,ds=%04lx,es=%04lx," @@ -132,23 +88,115 @@ static void dump_varargs_context( const void *ptr, size_t len ) #endif } -static void dump_varargs_exc_event( const void *ptr, size_t len ) +static void dump_exc_record( const EXCEPTION_RECORD *rec ) { - fprintf( stderr, "{context=" ); - dump_varargs_context( ptr, sizeof(CONTEXT) ); - fprintf( stderr, ",rec=" ); - dump_exc_record( (EXCEPTION_RECORD *)((CONTEXT *)ptr + 1) ); + int i; + fprintf( stderr, "{code=%lx,flags=%lx,rec=%p,addr=%p,params={", + rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionRecord, + rec->ExceptionAddress ); + for (i = 0; i < rec->NumberParameters; i++) + { + if (i) fputc( ',', stderr ); + fprintf( stderr, "%lx", rec->ExceptionInformation[i] ); + } fputc( '}', stderr ); } -static void dump_varargs_debug_event( const void *ptr, size_t len ) +static size_t dump_varargs_ints( const void *req ) { - const debug_event_t *event = ptr; + const int *data = get_data(req); + size_t len = get_size(req) / sizeof(*data); - if (!len) + fputc( '{', stderr ); + while (len > 0) + { + fprintf( stderr, "%d", *data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + return get_size(req); +} + +static size_t dump_varargs_ptrs( const void *req ) +{ + void * const *data = get_data(req); + size_t len = get_size(req) / sizeof(*data); + + fputc( '{', stderr ); + while (len > 0) + { + fprintf( stderr, "%p", *data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + return get_size(req); +} + +static size_t dump_varargs_bytes( const void *req ) +{ + const unsigned char *data = get_data(req); + size_t len = get_size(req); + + fputc( '{', stderr ); + while (len > 0) + { + fprintf( stderr, "%02x", *data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + return get_size(req); +} + +static size_t dump_varargs_string( const void *req ) +{ + fprintf( stderr, "\"%.*s\"", (int)get_size(req), (char *)get_data(req) ); + return get_size(req); +} + +static size_t dump_varargs_unicode_len_str( const void *req ) +{ + const WCHAR *str = get_data(req); + WCHAR len = *str++; + len = min( len, get_size(req) ); + fprintf( stderr, "L\"" ); + dump_strW( str, len / sizeof(WCHAR), stderr, "\"\"" ); + fputc( '\"', stderr ); + return len + sizeof(WCHAR); +} + +static size_t dump_varargs_unicode_str( const void *req ) +{ + fprintf( stderr, "L\"" ); + dump_strW( get_data(req), get_size(req) / sizeof(WCHAR), stderr, "\"\"" ); + fputc( '\"', stderr ); + return get_size(req); +} + +static size_t dump_varargs_context( const void *req ) +{ + dump_context( get_data(req) ); + return get_size(req); +} + +static size_t dump_varargs_exc_event( const void *req ) +{ + const CONTEXT *ptr = get_data(req); + fprintf( stderr, "{context=" ); + dump_context( ptr ); + fprintf( stderr, ",rec=" ); + dump_exc_record( (EXCEPTION_RECORD *)(ptr + 1) ); + fputc( '}', stderr ); + return get_size(req); +} + +static size_t dump_varargs_debug_event( const void *req ) +{ + const debug_event_t *event = get_data(req); + + if (!get_size(req)) { fprintf( stderr, "{}" ); - return; + return 0; } switch(event->code) { @@ -202,12 +250,13 @@ static void dump_varargs_debug_event( const void *ptr, size_t len ) fprintf( stderr, "{code=??? (%d)}", event->code ); break; } + return get_size(req); } -static void dump_varargs_input_records( const void *ptr, size_t len ) +static size_t dump_varargs_input_records( const void *req ) { - const INPUT_RECORD *rec = ptr; - len /= sizeof(*rec); + const INPUT_RECORD *rec = get_data(req); + size_t len = get_size(req) / sizeof(*rec); fputc( '{', stderr ); while (len > 0) @@ -217,6 +266,7 @@ static void dump_varargs_input_records( const void *ptr, size_t len ) if (--len) fputc( ',', stderr ); } fputc( '}', stderr ); + return get_size(req); } /* dumping for functions for requests that have a variable part */ @@ -233,18 +283,6 @@ static void dump_varargs_write_process_memory_request( const struct write_proces dump_bytes( (unsigned char *)req->data, count * sizeof(int) ); } -static void dump_varargs_set_key_value_request( const struct set_key_value_request *req ) -{ - int count = min( req->len, get_req_size( req, req->data, 1 )); - dump_bytes( req->data, count ); -} - -static void dump_varargs_get_key_value_reply( const struct get_key_value_request *req ) -{ - int count = min( req->len - req->offset, get_req_size( req, req->data, 1 )); - dump_bytes( req->data, count ); -} - static void dump_varargs_enum_key_value_reply( const struct enum_key_value_request *req ) { int count = min( req->len - req->offset, get_req_size( req, req->data, 1 )); @@ -268,7 +306,7 @@ static void dump_new_process_request( const struct new_process_request *req ) fprintf( stderr, " cmd_show=%d,", req->cmd_show ); fprintf( stderr, " alloc_fd=%d,", req->alloc_fd ); fprintf( stderr, " filename=" ); - dump_varargs_string( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_string( req ); } static void dump_wait_process_request( const struct wait_process_request *req ) @@ -322,7 +360,7 @@ static void dump_init_process_reply( const struct init_process_request *req ) fprintf( stderr, " hstderr=%d,", req->hstderr ); fprintf( stderr, " cmd_show=%d,", req->cmd_show ); fprintf( stderr, " filename=" ); - dump_varargs_string( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_string( req ); } static void dump_init_process_done_request( const struct init_process_done_request *req ) @@ -475,7 +513,7 @@ static void dump_get_apc_reply( const struct get_apc_request *req ) fprintf( stderr, " func=%p,", req->func ); fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " args=" ); - dump_varargs_ptrs( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_ptrs( req ); } static void dump_close_handle_request( const struct close_handle_request *req ) @@ -532,7 +570,7 @@ static void dump_select_request( const struct select_request *req ) fprintf( stderr, " flags=%d,", req->flags ); fprintf( stderr, " timeout=%d,", req->timeout ); fprintf( stderr, " handles=" ); - dump_varargs_ints( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_ints( req ); } static void dump_select_reply( const struct select_request *req ) @@ -546,7 +584,7 @@ static void dump_create_event_request( const struct create_event_request *req ) fprintf( stderr, " initial_state=%d,", req->initial_state ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_event_reply( const struct create_event_request *req ) @@ -565,7 +603,7 @@ static void dump_open_event_request( const struct open_event_request *req ) fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_event_reply( const struct open_event_request *req ) @@ -578,7 +616,7 @@ static void dump_create_mutex_request( const struct create_mutex_request *req ) fprintf( stderr, " owned=%d,", req->owned ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_mutex_reply( const struct create_mutex_request *req ) @@ -596,7 +634,7 @@ static void dump_open_mutex_request( const struct open_mutex_request *req ) fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_mutex_reply( const struct open_mutex_request *req ) @@ -610,7 +648,7 @@ static void dump_create_semaphore_request( const struct create_semaphore_request fprintf( stderr, " max=%08x,", req->max ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_semaphore_reply( const struct create_semaphore_request *req ) @@ -634,7 +672,7 @@ static void dump_open_semaphore_request( const struct open_semaphore_request *re fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_semaphore_reply( const struct open_semaphore_request *req ) @@ -650,7 +688,7 @@ static void dump_create_file_request( const struct create_file_request *req ) fprintf( stderr, " create=%d,", req->create ); fprintf( stderr, " attrs=%08x,", req->attrs ); fprintf( stderr, " filename=" ); - dump_varargs_string( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_string( req ); } static void dump_create_file_reply( const struct create_file_request *req ) @@ -804,7 +842,7 @@ static void dump_get_socket_event_reply( const struct get_socket_event_request * fprintf( stderr, " pmask=%08x,", req->pmask ); fprintf( stderr, " state=%08x,", req->state ); fprintf( stderr, " errors=" ); - dump_varargs_ints( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_ints( req ); } static void dump_enable_socket_event_request( const struct enable_socket_event_request *req ) @@ -873,7 +911,7 @@ static void dump_set_console_info_request( const struct set_console_info_request fprintf( stderr, " cursor_size=%d,", req->cursor_size ); fprintf( stderr, " cursor_visible=%d,", req->cursor_visible ); fprintf( stderr, " title=" ); - dump_varargs_string( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_string( req ); } static void dump_get_console_info_request( const struct get_console_info_request *req ) @@ -887,14 +925,14 @@ static void dump_get_console_info_reply( const struct get_console_info_request * fprintf( stderr, " cursor_visible=%d,", req->cursor_visible ); fprintf( stderr, " pid=%d,", req->pid ); fprintf( stderr, " title=" ); - dump_varargs_string( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_string( req ); } static void dump_write_console_input_request( const struct write_console_input_request *req ) { fprintf( stderr, " handle=%d,", req->handle ); fprintf( stderr, " rec=" ); - dump_varargs_input_records( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_input_records( req ); } static void dump_write_console_input_reply( const struct write_console_input_request *req ) @@ -912,7 +950,7 @@ static void dump_read_console_input_reply( const struct read_console_input_reque { fprintf( stderr, " read=%d,", req->read ); fprintf( stderr, " rec=" ); - dump_varargs_input_records( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_input_records( req ); } static void dump_create_change_notification_request( const struct create_change_notification_request *req ) @@ -934,7 +972,7 @@ static void dump_create_mapping_request( const struct create_mapping_request *re fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " file_handle=%d,", req->file_handle ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_mapping_reply( const struct create_mapping_request *req ) @@ -947,7 +985,7 @@ static void dump_open_mapping_request( const struct open_mapping_request *req ) fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_mapping_reply( const struct open_mapping_request *req ) @@ -1046,21 +1084,21 @@ static void dump_wait_debug_event_reply( const struct wait_debug_event_request * fprintf( stderr, " pid=%p,", req->pid ); fprintf( stderr, " tid=%p,", req->tid ); fprintf( stderr, " event=" ); - dump_varargs_debug_event( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_debug_event( req ); } static void dump_exception_event_request( const struct exception_event_request *req ) { fprintf( stderr, " first=%d,", req->first ); fprintf( stderr, " record=" ); - dump_varargs_exc_event( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_exc_event( req ); } static void dump_exception_event_reply( const struct exception_event_request *req ) { fprintf( stderr, " status=%d,", req->status ); fprintf( stderr, " context=" ); - dump_varargs_context( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_context( req ); } static void dump_output_debug_string_request( const struct output_debug_string_request *req ) @@ -1113,10 +1151,10 @@ static void dump_create_key_request( const struct create_key_request *req ) fprintf( stderr, " options=%08x,", req->options ); fprintf( stderr, " modif=%ld,", req->modif ); fprintf( stderr, " name=" ); - dump_path_t( req, &req->name ); - fprintf( stderr, "," ); + cur_pos += dump_varargs_unicode_len_str( req ); + fputc( ',', stderr ); fprintf( stderr, " class=" ); - dump_unicode_string( req, req->class ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_key_reply( const struct create_key_request *req ) @@ -1130,7 +1168,7 @@ static void dump_open_key_request( const struct open_key_request *req ) fprintf( stderr, " parent=%d,", req->parent ); fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " name=" ); - dump_path_t( req, &req->name ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_key_reply( const struct open_key_request *req ) @@ -1139,13 +1177,6 @@ static void dump_open_key_reply( const struct open_key_request *req ) } static void dump_delete_key_request( const struct delete_key_request *req ) -{ - fprintf( stderr, " hkey=%d,", req->hkey ); - fprintf( stderr, " name=" ); - dump_path_t( req, &req->name ); -} - -static void dump_close_key_request( const struct close_key_request *req ) { fprintf( stderr, " hkey=%d", req->hkey ); } @@ -1193,12 +1224,11 @@ static void dump_set_key_value_request( const struct set_key_value_request *req fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " total=%08x,", req->total ); fprintf( stderr, " offset=%08x,", req->offset ); - fprintf( stderr, " len=%08x,", req->len ); fprintf( stderr, " name=" ); - dump_path_t( req, &req->name ); - fprintf( stderr, "," ); + cur_pos += dump_varargs_unicode_len_str( req ); + fputc( ',', stderr ); fprintf( stderr, " data=" ); - dump_varargs_set_key_value_request( req ); + cur_pos += dump_varargs_bytes( req ); } static void dump_get_key_value_request( const struct get_key_value_request *req ) @@ -1206,7 +1236,7 @@ static void dump_get_key_value_request( const struct get_key_value_request *req fprintf( stderr, " hkey=%d,", req->hkey ); fprintf( stderr, " offset=%08x,", req->offset ); fprintf( stderr, " name=" ); - dump_unicode_string( req, req->name ); + cur_pos += dump_varargs_unicode_len_str( req ); } static void dump_get_key_value_reply( const struct get_key_value_request *req ) @@ -1214,7 +1244,7 @@ static void dump_get_key_value_reply( const struct get_key_value_request *req ) fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " len=%d,", req->len ); fprintf( stderr, " data=" ); - dump_varargs_get_key_value_reply( req ); + cur_pos += dump_varargs_bytes( req ); } static void dump_enum_key_value_request( const struct enum_key_value_request *req ) @@ -1239,7 +1269,7 @@ static void dump_delete_key_value_request( const struct delete_key_value_request { fprintf( stderr, " hkey=%d,", req->hkey ); fprintf( stderr, " name=" ); - dump_path_t( req, &req->name ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_load_registry_request( const struct load_registry_request *req ) @@ -1275,7 +1305,7 @@ static void dump_create_timer_request( const struct create_timer_request *req ) fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " manual=%d,", req->manual ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_create_timer_reply( const struct create_timer_request *req ) @@ -1288,7 +1318,7 @@ static void dump_open_timer_request( const struct open_timer_request *req ) fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_open_timer_reply( const struct open_timer_request *req ) @@ -1320,7 +1350,7 @@ static void dump_get_thread_context_request( const struct get_thread_context_req static void dump_get_thread_context_reply( const struct get_thread_context_request *req ) { fprintf( stderr, " context=" ); - dump_varargs_context( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_context( req ); } static void dump_set_thread_context_request( const struct set_thread_context_request *req ) @@ -1328,7 +1358,7 @@ static void dump_set_thread_context_request( const struct set_thread_context_req fprintf( stderr, " handle=%d,", req->handle ); fprintf( stderr, " flags=%08x,", req->flags ); fprintf( stderr, " context=" ); - dump_varargs_context( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_context( req ); } static void dump_get_selector_entry_request( const struct get_selector_entry_request *req ) @@ -1348,7 +1378,7 @@ static void dump_add_atom_request( const struct add_atom_request *req ) { fprintf( stderr, " local=%d,", req->local ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_add_atom_reply( const struct add_atom_request *req ) @@ -1366,7 +1396,7 @@ static void dump_find_atom_request( const struct find_atom_request *req ) { fprintf( stderr, " local=%d,", req->local ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_find_atom_reply( const struct find_atom_request *req ) @@ -1384,7 +1414,7 @@ static void dump_get_atom_name_reply( const struct get_atom_name_request *req ) { fprintf( stderr, " count=%d,", req->count ); fprintf( stderr, " name=" ); - dump_varargs_unicode_str( get_req_data(req), get_req_data_size(req) ); + cur_pos += dump_varargs_unicode_str( req ); } static void dump_init_atom_table_request( const struct init_atom_table_request *req ) @@ -1543,7 +1573,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_key_request, (dump_func)dump_open_key_request, (dump_func)dump_delete_key_request, - (dump_func)dump_close_key_request, (dump_func)dump_enum_key_request, (dump_func)dump_query_key_info_request, (dump_func)dump_set_key_value_request, @@ -1656,7 +1685,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_key_reply, (dump_func)dump_open_key_reply, (dump_func)0, - (dump_func)0, (dump_func)dump_enum_key_reply, (dump_func)dump_query_key_info_reply, (dump_func)0, @@ -1769,7 +1797,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "create_key", "open_key", "delete_key", - "close_key", "enum_key", "query_key_info", "set_key_value", @@ -1805,10 +1832,12 @@ static const char * const req_names[REQ_NB_REQUESTS] = { void trace_request( enum request req ) { + cur_pos = 0; current->last_req = req; if (req < REQ_NB_REQUESTS) { fprintf( stderr, "%08x: %s(", (unsigned int)current, req_names[req] ); + cur_pos = 0; req_dumpers[req]( current->buffer ); } else @@ -1824,8 +1853,9 @@ void trace_reply( struct thread *thread ) if (reply_dumpers[thread->last_req]) { fprintf( stderr, " {" ); + cur_pos = 0; reply_dumpers[thread->last_req]( thread->buffer ); - fprintf( stderr, " }" ); + fprintf( stderr, " }" ); } if (thread->pass_fd != -1) fprintf( stderr, " fd=%d\n", thread->pass_fd ); else fprintf( stderr, "\n" ); diff --git a/tools/make_requests b/tools/make_requests index a0f07b14981..56b4ddd54e9 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -179,7 +179,8 @@ sub DO_DUMP_FUNC { my $func = $1; push @trace_lines, " fprintf( stderr, \" $var=\" );\n"; - push @trace_lines, " $func( get_req_data(req), get_req_data_size(req) );\n"; + push @trace_lines, " cur_pos += $func( req );\n"; + push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0); } else {