Converted some of the registry server requests to the new request
mechanism.
This commit is contained in:
parent
d76f9f9637
commit
bcf393a5e5
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
306
dlls/ntdll/reg.c
306
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;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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,
|
||||
|
|
290
server/trace.c
290
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" );
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue