diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
index fca82b169dda4a2d73835694354f35c75c7cc364..26aa450971eecabacefd584ec556366d7596d51f 100644
--- a/dlls/advapi32/registry.c
+++ b/dlls/advapi32/registry.c
@@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
 DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
                             LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
 {
-    DWORD ret, len, cls_len;
-    struct enum_key_request *req = get_req_buffer();
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
            name_len ? *name_len : -1, reserved, class, class_len, ft );
 
     if (reserved) return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    req->index = index;
-    if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+    status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                             buffer, sizeof(buffer), &total_size );
 
-    len = strlenW( req->name ) + 1;
-    cls_len = strlenW( req->class ) + 1;
-    if (len > *name_len) return ERROR_MORE_DATA;
-    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+    while (status == STATUS_BUFFER_OVERFLOW)
+    {
+        /* retry with a dynamically allocated buffer */
+        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            return ERROR_NOT_ENOUGH_MEMORY;
+        info = (KEY_NODE_INFORMATION *)buf_ptr;
+        status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                                 buf_ptr, total_size, &total_size );
+    }
 
-    memcpy( name, req->name, len * sizeof(WCHAR) );
-    *name_len = len - 1;
-    if (class_len)
+    if (!status)
     {
-        if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
-        *class_len = cls_len - 1;
+        DWORD len = info->NameLength / sizeof(WCHAR);
+        DWORD cls_len = info->ClassLength / sizeof(WCHAR);
+
+        if (ft) *ft = info->LastWriteTime;
+
+        if (len >= *name_len || (class_len && (cls_len >= *class_len)))
+            status = STATUS_BUFFER_OVERFLOW;
+        else
+        {
+            *name_len = len;
+            memcpy( name, info->Name, info->NameLength );
+            name[len] = 0;
+            if (class_len)
+            {
+                *class_len = cls_len;
+                if (class)
+                {
+                    memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
+                    class[cls_len] = 0;
+                }
+            }
+        }
     }
-    if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
-    return ERROR_SUCCESS;
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
 DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
                             LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
 {
-    DWORD ret, len, cls_len;
-    struct enum_key_request *req = get_req_buffer();
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
            name_len ? *name_len : -1, reserved, class, class_len, ft );
 
     if (reserved) return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    req->index = index;
-    if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+    status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                             buffer, sizeof(buffer), &total_size );
 
-    len = strlenW( req->name ) + 1;
-    cls_len = strlenW( req->class ) + 1;
-    if (len > *name_len) return ERROR_MORE_DATA;
-    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+    while (status == STATUS_BUFFER_OVERFLOW)
+    {
+        /* retry with a dynamically allocated buffer */
+        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            return ERROR_NOT_ENOUGH_MEMORY;
+        info = (KEY_NODE_INFORMATION *)buf_ptr;
+        status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                                 buf_ptr, total_size, &total_size );
+    }
 
-    memcpyWtoA( name, req->name, len );
-    *name_len = len - 1;
-    if (class_len)
+    if (!status)
     {
-        if (class) memcpyWtoA( class, req->class, cls_len );
-        *class_len = cls_len - 1;
+        DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
+                                         NULL, 0, NULL, NULL );
+        DWORD cls_len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
+                                             info->ClassLength / sizeof(WCHAR),
+                                             NULL, 0, NULL, NULL );
+
+        if (ft) *ft = info->LastWriteTime;
+
+        if (len >= *name_len || (class_len && (cls_len >= *class_len)))
+            status = STATUS_BUFFER_OVERFLOW;
+        else
+        {
+            *name_len = len;
+            WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
+                                 name, len, NULL, NULL );
+            name[len] = 0;
+            if (class_len)
+            {
+                *class_len = cls_len;
+                if (class)
+                {
+                    WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
+                                         info->ClassLength / sizeof(WCHAR),
+                                         class, cls_len, NULL, NULL );
+                    class[cls_len] = 0;
+                }
+            }
+        }
     }
-    if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
-    return ERROR_SUCCESS;
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
                                LPDWORD values, LPDWORD max_value, LPDWORD max_data,
                                LPDWORD security, FILETIME *modif )
 {
-    DWORD ret;
-    struct query_key_info_request *req = get_req_buffer();
-
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
            reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
@@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
     if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
         return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+    status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
 
     if (class)
     {
-        if (class_len && (strlenW(req->class) + 1 > *class_len))
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
         {
-            *class_len = strlenW(req->class);
-            return ERROR_MORE_DATA;
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_FULL_INFORMATION *)buf_ptr;
+            status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
+        }
+
+        if (!status)
+        {
+            if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+            }
+            else
+            {
+                memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
+                class[info->ClassLength/sizeof(WCHAR)] = 0;
+            }
         }
-        strcpyW( class, req->class );
     }
-    if (class_len) *class_len = strlenW( req->class );
-    if (subkeys) *subkeys = req->subkeys;
-    if (max_subkey) *max_subkey = req->max_subkey;
-    if (max_class) *max_class = req->max_class;
-    if (values) *values = req->values;
-    if (max_value) *max_value = req->max_value;
-    if (max_data) *max_data = req->max_data;
-    if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
-    return ERROR_SUCCESS;
+
+    if (!status || status == STATUS_BUFFER_OVERFLOW)
+    {
+        if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
+        if (subkeys) *subkeys = info->SubKeys;
+        if (max_subkey) *max_subkey = info->MaxNameLen;
+        if (max_class) *max_class = info->MaxClassLen;
+        if (values) *values = info->Values;
+        if (max_value) *max_value = info->MaxValueNameLen;
+        if (max_data) *max_data = info->MaxValueDataLen;
+        if (modif) *modif = info->LastWriteTime;
+    }
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
                                LPDWORD values, LPDWORD max_value, LPDWORD max_data,
                                LPDWORD security, FILETIME *modif )
 {
-    DWORD ret;
-    struct query_key_info_request *req = get_req_buffer();
-
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
            reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
@@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
     if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
         return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+    status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
 
-    if (class)
+    if (class || class_len)
     {
-        if (class_len && (strlenW(req->class) + 1 > *class_len))
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
         {
-            *class_len = strlenW(req->class);
-            return ERROR_MORE_DATA;
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_FULL_INFORMATION *)buf_ptr;
+            status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
+        }
+
+        if (!status)
+        {
+            DWORD len = WideCharToMultiByte( CP_ACP, 0,
+                                             (WCHAR *)(buf_ptr + info->ClassOffset),
+                                             info->ClassLength/sizeof(WCHAR),
+                                             NULL, 0, NULL, NULL );
+            if (class_len)
+            {
+                if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
+                *class_len = len;
+            }
+            if (class && !status)
+            {
+                WideCharToMultiByte( CP_ACP, 0,
+                                     (WCHAR *)(buf_ptr + info->ClassOffset),
+                                     info->ClassLength/sizeof(WCHAR),
+                                     class, len, NULL, NULL );
+                class[len] = 0;
+            }
         }
-        lstrcpyWtoA( class, req->class );
     }
-    if (class_len) *class_len = strlenW( req->class );
-    if (subkeys) *subkeys = req->subkeys;
-    if (max_subkey) *max_subkey = req->max_subkey;
-    if (max_class) *max_class = req->max_class;
-    if (values) *values = req->values;
-    if (max_value) *max_value = req->max_value;
-    if (max_data) *max_data = req->max_data;
-    if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
-    return ERROR_SUCCESS;
+
+    if (!status || status == STATUS_BUFFER_OVERFLOW)
+    {
+        if (subkeys) *subkeys = info->SubKeys;
+        if (max_subkey) *max_subkey = info->MaxNameLen;
+        if (max_class) *max_class = info->MaxClassLen;
+        if (values) *values = info->Values;
+        if (max_value) *max_value = info->MaxValueNameLen;
+        if (max_data) *max_data = info->MaxValueDataLen;
+        if (modif) *modif = info->LastWriteTime;
+    }
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
     NTSTATUS status;
     UNICODE_STRING name_str;
     DWORD total_size;
-    char buffer[256];
+    char buffer[256], *buf_ptr = buffer;
     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
     static const int info_size = sizeof(*info) - sizeof(info->Data);
 
@@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
 
     if (data)
     {
-        char *buf_ptr = buffer;
         /* retry with a dynamically allocated buffer */
         while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
-                status = STATUS_NO_MEMORY;
-            else
-                status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
-                                          buf_ptr, total_size, &total_size );
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+            status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
+                                      buf_ptr, total_size, &total_size );
         }
 
         if (!status)
@@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
                 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
             }
         }
-        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        else if (status != STATUS_BUFFER_OVERFLOW) goto done;
     }
 
     if (type) *type = info->Type;
     if (count) *count = total_size - info_size;
 
  done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
     return RtlNtStatusToDosError(status);
 }
 
@@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
     ANSI_STRING nameA;
     UNICODE_STRING nameW;
     DWORD total_size;
-    char buffer[256];
+    char buffer[256], *buf_ptr = buffer;
     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
     static const int info_size = sizeof(*info) - sizeof(info->Data);
 
@@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
 
     RtlInitAnsiString( &nameA, name );
     /* FIXME: should use Unicode buffer in TEB */
-    if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
+    if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
+        return RtlNtStatusToDosError(status);
 
     status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
                               buffer, sizeof(buffer), &total_size );
@@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
      * because we need to compute the length of the ASCII string. */
     if (data || is_string(info->Type))
     {
-        char *buf_ptr = buffer;
         /* retry with a dynamically allocated buffer */
         while (status == STATUS_BUFFER_OVERFLOW)
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            {
                 status = STATUS_NO_MEMORY;
-            else
-                status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
-                                          buf_ptr, total_size, &total_size );
+                goto done;
+            }
+            info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+            status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
+                                      buf_ptr, total_size, &total_size );
         }
 
         if (!status)
@@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
                 total_size = len + info_size;
             }
             else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size );
-
-            /* if the type is REG_SZ and data is not 0-terminated
-             * and there is enough space in the buffer NT appends a \0 */
-            if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
-            {
-                WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
-                if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
-            }
         }
-        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        else if (status != STATUS_BUFFER_OVERFLOW) goto done;
     }
 
     if (type) *type = info->Type;
     if (count) *count = total_size - info_size;
-    RtlFreeUnicodeString( &nameW );
 
  done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    RtlFreeUnicodeString( &nameW );
     return RtlNtStatusToDosError(status);
 }
 
diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c
index 41b3005abbb2f0c674fb8e432c02fb699cddda02..c1d43eaba3fca40190dd257867092f77afe6ce55 100644
--- a/dlls/ntdll/reg.c
+++ b/dlls/ntdll/reg.c
@@ -167,6 +167,95 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
 }
 
 
+/******************************************************************************
+ *     fill_key_info
+ *
+ * Helper function for NtQueryKey and NtEnumerateKey
+ */
+static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
+                               DWORD *result_len, const struct enum_key_request *req )
+{
+    WCHAR *name_ptr = server_data_ptr(req);
+    int name_size = *name_ptr++;
+    WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
+    int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
+    int fixed_size;
+    FILETIME modif;
+
+    RtlSecondsSince1970ToTime( req->modif, &modif );
+
+    switch(info_class)
+    {
+    case KeyBasicInformation:
+        {
+            KEY_BASIC_INFORMATION keyinfo;
+            fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
+            keyinfo.LastWriteTime = modif;
+            keyinfo.TitleIndex = 0;
+            keyinfo.NameLength = name_size;
+            memcpy( info, &keyinfo, min( length, fixed_size ) );
+            class_size = 0;
+        }
+        break;
+    case KeyFullInformation:
+        {
+            KEY_FULL_INFORMATION keyinfo;
+            fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Class);
+            keyinfo.LastWriteTime = modif;
+            keyinfo.TitleIndex = 0;
+            keyinfo.ClassLength = class_size;
+            keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
+            keyinfo.SubKeys = req->subkeys;
+            keyinfo.MaxNameLen = req->max_subkey;
+            keyinfo.MaxClassLen = req->max_class;
+            keyinfo.Values = req->values;
+            keyinfo.MaxValueNameLen = req->max_value;
+            keyinfo.MaxValueDataLen = req->max_data;
+            memcpy( info, &keyinfo, min( length, fixed_size ) );
+            name_size = 0;
+        }
+        break;
+    case KeyNodeInformation:
+        {
+            KEY_NODE_INFORMATION keyinfo;
+            fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
+            keyinfo.LastWriteTime = modif;
+            keyinfo.TitleIndex = 0;
+            keyinfo.ClassLength = class_size;
+            keyinfo.ClassOffset = fixed_size + name_size;
+            if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
+            keyinfo.NameLength = name_size;
+            memcpy( info, &keyinfo, min( length, fixed_size ) );
+        }
+        break;
+    default:
+        FIXME("Information class not implemented\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    *result_len = fixed_size + name_size + class_size;
+    if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
+    length -= fixed_size;
+
+    /* copy the name */
+    if (name_size)
+    {
+        memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
+        if (length < name_size) return STATUS_BUFFER_OVERFLOW;
+        length -= name_size;
+    }
+
+    /* copy the class */
+    if (class_size)
+    {
+        memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
+        if (length < class_size) return STATUS_BUFFER_OVERFLOW;
+    }
+    return STATUS_SUCCESS;
+}
+
+
+
 /******************************************************************************
  * NtEnumerateKey [NTDLL]
  * ZwEnumerateKey
@@ -174,164 +263,52 @@ NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
  * NOTES
  *  the name copied into the buffer is NOT 0-terminated 
  */
-NTSTATUS WINAPI NtEnumerateKey(
-	HANDLE KeyHandle,
-	ULONG Index,
-	KEY_INFORMATION_CLASS KeyInformationClass,
-	PVOID KeyInformation,
-	ULONG Length,
-	PULONG ResultLength)
+NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
+                                void *info, DWORD length, DWORD *result_len )
 {
-	struct enum_key_request *req = get_req_buffer();
-	NTSTATUS ret;
+    NTSTATUS ret;
 
-	TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
-	KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
+    /* -1 means query key, so avoid it here */
+    if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
 
-	req->hkey = KeyHandle;
-	req->index = Index;
-	if ((ret = server_call_noerr(REQ_ENUM_KEY)) != STATUS_SUCCESS) return ret;
-
-	switch (KeyInformationClass)
-	{
-	  case KeyBasicInformation:
-	    {
-	      PKEY_BASIC_INFORMATION kbi = KeyInformation;
-	      UINT NameLength = strlenW(req->name) * sizeof(WCHAR);
-	      *ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
-
-	      RtlSecondsSince1970ToTime(req->modif, &kbi->LastWriteTime);
-	      kbi->TitleIndex = 0;
-	      kbi->NameLength = NameLength;
-	      memcpy (kbi->Name, req->name, NameLength);
-	    }
-	    break;
-	  case KeyFullInformation:
-	    {
-	      PKEY_FULL_INFORMATION kfi = KeyInformation;
-	      kfi->ClassLength = strlenW(req->class) * sizeof(WCHAR);
-	      kfi->ClassOffset = (kfi->ClassLength) ?
-	        sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
-	      *ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
-
-	      RtlSecondsSince1970ToTime(req->modif, &kfi->LastWriteTime);
-	      kfi->TitleIndex = 0;
-/*	      kfi->SubKeys = req->subkeys;
-	      kfi->MaxNameLength = req->max_subkey;
-	      kfi->MaxClassLength = req->max_class;
-	      kfi->Values = req->values;
-	      kfi->MaxValueNameLen = req->max_value;
-	      kfi->MaxValueDataLen = req->max_data;
-*/
-	      FIXME("incomplete\n");
-	      if (kfi->ClassLength) memcpy (kfi->Class, req->class, kfi->ClassLength);
-	    }
-	    break;
-	  case KeyNodeInformation:
-	    {
-	      PKEY_NODE_INFORMATION kni = KeyInformation;
-	      kni->ClassLength = strlenW(req->class) * sizeof(WCHAR);
-	      kni->NameLength = strlenW(req->name) * sizeof(WCHAR);
-	      kni->ClassOffset = (kni->ClassLength) ?
-	        sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
-
-	      *ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
-
-	      RtlSecondsSince1970ToTime(req->modif, &kni->LastWriteTime);
-	      kni->TitleIndex = 0;
-	      memcpy (kni->Name, req->name, kni->NameLength);
-	      if (kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
-	    }
-	    break;
-	  default:
-	    FIXME("KeyInformationClass not implemented\n");
-	    return STATUS_UNSUCCESSFUL;
-	}
-	TRACE("buf=%lu len=%lu\n", Length, *ResultLength);
-	return ret;
+    SERVER_START_REQ
+    {
+        struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
+        req->hkey  = handle;
+        req->index = index;
+        req->full  = (info_class == KeyFullInformation);
+        if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
+        {
+            ret = fill_key_info( info_class, info, length, result_len, req );
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
 }
 
+
 /******************************************************************************
  * NtQueryKey [NTDLL]
  * ZwQueryKey
  */
-NTSTATUS WINAPI NtQueryKey(
-	HANDLE KeyHandle,
-	KEY_INFORMATION_CLASS KeyInformationClass,
-	PVOID KeyInformation,
-	ULONG Length,
-	PULONG ResultLength)
+NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
+                            void *info, DWORD length, DWORD *result_len )
 {
-	struct query_key_info_request *req = get_req_buffer();
-	NTSTATUS ret;
-	
-	TRACE("(0x%08x,0x%08x,%p,0x%08lx,%p) stub\n",
-	KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
-	
-	req->hkey = KeyHandle;
-	if ((ret = server_call_noerr(REQ_QUERY_KEY_INFO)) != STATUS_SUCCESS) return ret;
-	
-	switch (KeyInformationClass)
-	{
-	  case KeyBasicInformation:
-	    {
-	      PKEY_BASIC_INFORMATION kbi = KeyInformation;
-	      UINT NameLength = strlenW(req->name) * sizeof(WCHAR);
-	      *ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
+    NTSTATUS ret;
 
-	      RtlSecondsSince1970ToTime(req->modif, &kbi->LastWriteTime);
-	      kbi->TitleIndex = 0;
-	      kbi->NameLength = NameLength;
-	      memcpy (kbi->Name, req->name, NameLength);
-	    }
-	    break;
-	  case KeyFullInformation:
-	    {
-	      PKEY_FULL_INFORMATION kfi = KeyInformation;
-	      kfi->ClassLength = strlenW(req->class) * sizeof(WCHAR);
-	      kfi->ClassOffset = (kfi->ClassLength) ?
-	        sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
-
-	      *ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
-
-	      RtlSecondsSince1970ToTime(req->modif, &kfi->LastWriteTime);
-	      kfi->TitleIndex = 0;
-	      kfi->SubKeys = req->subkeys;
-	      kfi->MaxNameLen = req->max_subkey;
-	      kfi->MaxClassLen = req->max_class;
-	      kfi->Values = req->values;
-	      kfi->MaxValueNameLen = req->max_value;
-	      kfi->MaxValueDataLen = req->max_data;
-	      if(kfi->ClassLength) memcpy ((char *) KeyInformation + kfi->ClassOffset, req->class, kfi->ClassLength);
-	    }
-	    break;
-	  case KeyNodeInformation:
-	    {
-	      PKEY_NODE_INFORMATION kni = KeyInformation;
-	      kni->ClassLength = strlenW(req->class) * sizeof(WCHAR);
-	      kni->NameLength = strlenW(req->name) * sizeof(WCHAR);
-	      kni->ClassOffset = (kni->ClassLength) ?
-	        sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
-
-	      *ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
-	      if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
-
-	      RtlSecondsSince1970ToTime(req->modif, &kni->LastWriteTime);
-	      kni->TitleIndex = 0;
-	      memcpy (kni->Name, req->name, kni->NameLength);
-	      if(kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
-	    }
-	    break;
-	  default:
-	    FIXME("KeyInformationClass not implemented\n");
-	    return STATUS_UNSUCCESSFUL;
-	}
-	return ret;
+    SERVER_START_REQ
+    {
+        struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
+        req->hkey  = handle;
+        req->index = -1;
+        req->full  = (info_class == KeyFullInformation);
+        if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
+        {
+            ret = fill_key_info( info_class, info, length, result_len, req );
+        }
+    }
+    SERVER_END_REQ;
+    return ret;
 }
 
 /******************************************************************************
@@ -489,8 +466,6 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
                                  KEY_VALUE_INFORMATION_CLASS info_class,
                                  void *info, DWORD length, DWORD *result_len )
 {
-
-
     NTSTATUS ret;
     char *data_ptr;
     int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
@@ -523,7 +498,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
     do
     {
         size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
-        reqlen = max( reqlen, name->Length );
+        reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
 
         SERVER_START_REQ
         {
@@ -554,7 +529,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
 
     *result_len = total_len + fixed_size;
 
-    if (!data_len) ret = STATUS_BUFFER_OVERFLOW;
+    if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
     if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
 
     switch(info_class)
diff --git a/include/ntddk.h b/include/ntddk.h
index 8aef5cb11bca40dcc8ea5189f59e286f023d6f51..aefc99e66bee233675ab002a3e2a4cd33b444987 100644
--- a/include/ntddk.h
+++ b/include/ntddk.h
@@ -821,17 +821,11 @@ NTSTATUS    WINAPI NtDeleteKey(HANDLE);
 NTSTATUS    WINAPI NtDeleteValueKey(HANDLE,const UNICODE_STRING*);
 NTSTATUS    WINAPI NtOpenKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*);
 NTSTATUS    WINAPI NtSetValueKey(HANDLE,const UNICODE_STRING*,ULONG,ULONG,const void*,ULONG);
+NTSTATUS    WINAPI NtEnumerateKey(HANDLE,ULONG,KEY_INFORMATION_CLASS,void*,DWORD,DWORD*);
 NTSTATUS    WINAPI NtQueryValueKey(HANDLE,const UNICODE_STRING*,KEY_VALUE_INFORMATION_CLASS,
                                    void*,DWORD,DWORD*);
 
 
-NTSTATUS WINAPI NtEnumerateKey(
-	HANDLE KeyHandle,
-	ULONG Index,
-	KEY_INFORMATION_CLASS KeyInformationClass,
-	PVOID KeyInformation,
-	ULONG Length,
-	PULONG ResultLength);
 
 NTSTATUS WINAPI NtQueryKey(
 	HANDLE KeyHandle,
diff --git a/include/server.h b/include/server.h
index f9255fe962c725b4abd9545250805fa184e59b7f..443c547700561cc6defb8b4a480e94a3d32fb361 100644
--- a/include/server.h
+++ b/include/server.h
@@ -1046,18 +1046,8 @@ struct enum_key_request
 {
     REQUEST_HEADER;                /* request header */
     IN  int          hkey;         /* handle to registry key */
-    IN  int          index;        /* index of subkey */
-    OUT time_t       modif;        /* last modification time */
-    OUT path_t       name;         /* subkey name */
-    OUT WCHAR        class[1];     /* class name */
-};
-
-
-/* Query information about a registry key */
-struct query_key_info_request
-{
-    REQUEST_HEADER;                /* request header */
-    IN  int          hkey;         /* handle to registry key */
+    IN  int          index;        /* index of subkey (or -1 for current key) */
+    IN  int          full;         /* return the full info? */
     OUT int          subkeys;      /* number of subkeys */
     OUT int          max_subkey;   /* longest subkey name */
     OUT int          max_class;    /* longest class name */
@@ -1065,8 +1055,8 @@ struct query_key_info_request
     OUT int          max_value;    /* longest value name */
     OUT int          max_data;     /* longest value data */
     OUT time_t       modif;        /* last modification time */
-    OUT path_t       name;         /* key name */
-    OUT WCHAR        class[1];     /* class name */
+    OUT VARARG(name,unicode_len_str);  /* key name */
+    OUT VARARG(class,unicode_str);     /* class name */
 };
 
 
@@ -1429,7 +1419,6 @@ enum request
     REQ_OPEN_KEY,
     REQ_DELETE_KEY,
     REQ_ENUM_KEY,
-    REQ_QUERY_KEY_INFO,
     REQ_SET_KEY_VALUE,
     REQ_GET_KEY_VALUE,
     REQ_ENUM_KEY_VALUE,
@@ -1545,7 +1534,6 @@ union generic_request
     struct open_key_request open_key;
     struct delete_key_request delete_key;
     struct enum_key_request enum_key;
-    struct query_key_info_request query_key_info;
     struct set_key_value_request set_key_value;
     struct get_key_value_request get_key_value;
     struct enum_key_value_request enum_key_value;
@@ -1574,7 +1562,7 @@ union generic_request
     struct set_serial_info_request set_serial_info;
 };
 
-#define SERVER_PROTOCOL_VERSION 24
+#define SERVER_PROTOCOL_VERSION 25
 
 /* ### make_requests end ### */
 /* Everything above this line is generated automatically by tools/make_requests */
@@ -1648,13 +1636,13 @@ static inline void server_strcpyAtoW( WCHAR *dst, const char *src )
 }
 
 /* get a pointer to the variable part of the request */
-inline static void *server_data_ptr( void *req )
+inline static void *server_data_ptr( const void *req )
 {
     return (union generic_request *)req + 1;
 }
 
 /* get the size of the variable part of the request */
-inline static size_t server_data_size( void *req )
+inline static size_t server_data_size( const void *req )
 {
     return ((struct request_header *)req)->var_size;
 }
diff --git a/memory/registry.c b/memory/registry.c
index fca82b169dda4a2d73835694354f35c75c7cc364..26aa450971eecabacefd584ec556366d7596d51f 100644
--- a/memory/registry.c
+++ b/memory/registry.c
@@ -289,32 +289,58 @@ DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
 DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
                             LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
 {
-    DWORD ret, len, cls_len;
-    struct enum_key_request *req = get_req_buffer();
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
            name_len ? *name_len : -1, reserved, class, class_len, ft );
 
     if (reserved) return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    req->index = index;
-    if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+    status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                             buffer, sizeof(buffer), &total_size );
 
-    len = strlenW( req->name ) + 1;
-    cls_len = strlenW( req->class ) + 1;
-    if (len > *name_len) return ERROR_MORE_DATA;
-    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+    while (status == STATUS_BUFFER_OVERFLOW)
+    {
+        /* retry with a dynamically allocated buffer */
+        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            return ERROR_NOT_ENOUGH_MEMORY;
+        info = (KEY_NODE_INFORMATION *)buf_ptr;
+        status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                                 buf_ptr, total_size, &total_size );
+    }
 
-    memcpy( name, req->name, len * sizeof(WCHAR) );
-    *name_len = len - 1;
-    if (class_len)
+    if (!status)
     {
-        if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
-        *class_len = cls_len - 1;
+        DWORD len = info->NameLength / sizeof(WCHAR);
+        DWORD cls_len = info->ClassLength / sizeof(WCHAR);
+
+        if (ft) *ft = info->LastWriteTime;
+
+        if (len >= *name_len || (class_len && (cls_len >= *class_len)))
+            status = STATUS_BUFFER_OVERFLOW;
+        else
+        {
+            *name_len = len;
+            memcpy( name, info->Name, info->NameLength );
+            name[len] = 0;
+            if (class_len)
+            {
+                *class_len = cls_len;
+                if (class)
+                {
+                    memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
+                    class[cls_len] = 0;
+                }
+            }
+        }
     }
-    if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
-    return ERROR_SUCCESS;
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -324,32 +350,64 @@ DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_le
 DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
                             LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
 {
-    DWORD ret, len, cls_len;
-    struct enum_key_request *req = get_req_buffer();
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
            name_len ? *name_len : -1, reserved, class, class_len, ft );
 
     if (reserved) return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    req->index = index;
-    if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+    status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                             buffer, sizeof(buffer), &total_size );
 
-    len = strlenW( req->name ) + 1;
-    cls_len = strlenW( req->class ) + 1;
-    if (len > *name_len) return ERROR_MORE_DATA;
-    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+    while (status == STATUS_BUFFER_OVERFLOW)
+    {
+        /* retry with a dynamically allocated buffer */
+        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            return ERROR_NOT_ENOUGH_MEMORY;
+        info = (KEY_NODE_INFORMATION *)buf_ptr;
+        status = NtEnumerateKey( hkey, index, KeyNodeInformation,
+                                 buf_ptr, total_size, &total_size );
+    }
 
-    memcpyWtoA( name, req->name, len );
-    *name_len = len - 1;
-    if (class_len)
+    if (!status)
     {
-        if (class) memcpyWtoA( class, req->class, cls_len );
-        *class_len = cls_len - 1;
+        DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
+                                         NULL, 0, NULL, NULL );
+        DWORD cls_len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
+                                             info->ClassLength / sizeof(WCHAR),
+                                             NULL, 0, NULL, NULL );
+
+        if (ft) *ft = info->LastWriteTime;
+
+        if (len >= *name_len || (class_len && (cls_len >= *class_len)))
+            status = STATUS_BUFFER_OVERFLOW;
+        else
+        {
+            *name_len = len;
+            WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
+                                 name, len, NULL, NULL );
+            name[len] = 0;
+            if (class_len)
+            {
+                *class_len = cls_len;
+                if (class)
+                {
+                    WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
+                                         info->ClassLength / sizeof(WCHAR),
+                                         class, cls_len, NULL, NULL );
+                    class[cls_len] = 0;
+                }
+            }
+        }
     }
-    if (ft) RtlSecondsSince1970ToTime( req->modif, ft );
-    return ERROR_SUCCESS;
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -398,9 +456,10 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
                                LPDWORD values, LPDWORD max_value, LPDWORD max_data,
                                LPDWORD security, FILETIME *modif )
 {
-    DWORD ret;
-    struct query_key_info_request *req = get_req_buffer();
-
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
            reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
@@ -408,27 +467,48 @@ DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWO
     if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
         return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+    status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
 
     if (class)
     {
-        if (class_len && (strlenW(req->class) + 1 > *class_len))
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
         {
-            *class_len = strlenW(req->class);
-            return ERROR_MORE_DATA;
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_FULL_INFORMATION *)buf_ptr;
+            status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
+        }
+
+        if (!status)
+        {
+            if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+            }
+            else
+            {
+                memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
+                class[info->ClassLength/sizeof(WCHAR)] = 0;
+            }
         }
-        strcpyW( class, req->class );
     }
-    if (class_len) *class_len = strlenW( req->class );
-    if (subkeys) *subkeys = req->subkeys;
-    if (max_subkey) *max_subkey = req->max_subkey;
-    if (max_class) *max_class = req->max_class;
-    if (values) *values = req->values;
-    if (max_value) *max_value = req->max_value;
-    if (max_data) *max_data = req->max_data;
-    if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
-    return ERROR_SUCCESS;
+
+    if (!status || status == STATUS_BUFFER_OVERFLOW)
+    {
+        if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
+        if (subkeys) *subkeys = info->SubKeys;
+        if (max_subkey) *max_subkey = info->MaxNameLen;
+        if (max_class) *max_class = info->MaxClassLen;
+        if (values) *values = info->Values;
+        if (max_value) *max_value = info->MaxValueNameLen;
+        if (max_data) *max_data = info->MaxValueDataLen;
+        if (modif) *modif = info->LastWriteTime;
+    }
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -440,9 +520,10 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
                                LPDWORD values, LPDWORD max_value, LPDWORD max_data,
                                LPDWORD security, FILETIME *modif )
 {
-    DWORD ret;
-    struct query_key_info_request *req = get_req_buffer();
-
+    NTSTATUS status;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
+    DWORD total_size;
 
     TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
            reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
@@ -450,27 +531,55 @@ DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWOR
     if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
         return ERROR_INVALID_PARAMETER;
 
-    req->hkey = hkey;
-    if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+    status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
 
-    if (class)
+    if (class || class_len)
     {
-        if (class_len && (strlenW(req->class) + 1 > *class_len))
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
         {
-            *class_len = strlenW(req->class);
-            return ERROR_MORE_DATA;
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_FULL_INFORMATION *)buf_ptr;
+            status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
+        }
+
+        if (!status)
+        {
+            DWORD len = WideCharToMultiByte( CP_ACP, 0,
+                                             (WCHAR *)(buf_ptr + info->ClassOffset),
+                                             info->ClassLength/sizeof(WCHAR),
+                                             NULL, 0, NULL, NULL );
+            if (class_len)
+            {
+                if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
+                *class_len = len;
+            }
+            if (class && !status)
+            {
+                WideCharToMultiByte( CP_ACP, 0,
+                                     (WCHAR *)(buf_ptr + info->ClassOffset),
+                                     info->ClassLength/sizeof(WCHAR),
+                                     class, len, NULL, NULL );
+                class[len] = 0;
+            }
         }
-        lstrcpyWtoA( class, req->class );
     }
-    if (class_len) *class_len = strlenW( req->class );
-    if (subkeys) *subkeys = req->subkeys;
-    if (max_subkey) *max_subkey = req->max_subkey;
-    if (max_class) *max_class = req->max_class;
-    if (values) *values = req->values;
-    if (max_value) *max_value = req->max_value;
-    if (max_data) *max_data = req->max_data;
-    if (modif) RtlSecondsSince1970ToTime( req->modif, modif );
-    return ERROR_SUCCESS;
+
+    if (!status || status == STATUS_BUFFER_OVERFLOW)
+    {
+        if (subkeys) *subkeys = info->SubKeys;
+        if (max_subkey) *max_subkey = info->MaxNameLen;
+        if (max_class) *max_class = info->MaxClassLen;
+        if (values) *values = info->Values;
+        if (max_value) *max_value = info->MaxValueNameLen;
+        if (max_data) *max_data = info->MaxValueDataLen;
+        if (modif) *modif = info->LastWriteTime;
+    }
+
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError( status );
 }
 
 
@@ -689,7 +798,7 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
     NTSTATUS status;
     UNICODE_STRING name_str;
     DWORD total_size;
-    char buffer[256];
+    char buffer[256], *buf_ptr = buffer;
     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
     static const int info_size = sizeof(*info) - sizeof(info->Data);
 
@@ -709,16 +818,15 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
 
     if (data)
     {
-        char *buf_ptr = buffer;
         /* retry with a dynamically allocated buffer */
         while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
-                status = STATUS_NO_MEMORY;
-            else
-                status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
-                                          buf_ptr, total_size, &total_size );
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+            status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
+                                      buf_ptr, total_size, &total_size );
         }
 
         if (!status)
@@ -732,13 +840,14 @@ DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWOR
                 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
             }
         }
-        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        else if (status != STATUS_BUFFER_OVERFLOW) goto done;
     }
 
     if (type) *type = info->Type;
     if (count) *count = total_size - info_size;
 
  done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
     return RtlNtStatusToDosError(status);
 }
 
@@ -756,7 +865,7 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
     ANSI_STRING nameA;
     UNICODE_STRING nameW;
     DWORD total_size;
-    char buffer[256];
+    char buffer[256], *buf_ptr = buffer;
     KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
     static const int info_size = sizeof(*info) - sizeof(info->Data);
 
@@ -767,7 +876,8 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
 
     RtlInitAnsiString( &nameA, name );
     /* FIXME: should use Unicode buffer in TEB */
-    if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE ))) goto done;
+    if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
+        return RtlNtStatusToDosError(status);
 
     status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
                               buffer, sizeof(buffer), &total_size );
@@ -777,16 +887,18 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
      * because we need to compute the length of the ASCII string. */
     if (data || is_string(info->Type))
     {
-        char *buf_ptr = buffer;
         /* retry with a dynamically allocated buffer */
         while (status == STATUS_BUFFER_OVERFLOW)
         {
             if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
             if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+            {
                 status = STATUS_NO_MEMORY;
-            else
-                status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
-                                          buf_ptr, total_size, &total_size );
+                goto done;
+            }
+            info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
+            status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
+                                      buf_ptr, total_size, &total_size );
         }
 
         if (!status)
@@ -812,23 +924,16 @@ DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD
                 total_size = len + info_size;
             }
             else if (data) memcpy( data, buf_ptr + info_size, total_size - info_size );
-
-            /* if the type is REG_SZ and data is not 0-terminated
-             * and there is enough space in the buffer NT appends a \0 */
-            if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
-            {
-                WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
-                if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
-            }
         }
-        if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+        else if (status != STATUS_BUFFER_OVERFLOW) goto done;
     }
 
     if (type) *type = info->Type;
     if (count) *count = total_size - info_size;
-    RtlFreeUnicodeString( &nameW );
 
  done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    RtlFreeUnicodeString( &nameW );
     return RtlNtStatusToDosError(status);
 }
 
diff --git a/server/registry.c b/server/registry.c
index 8d355c57fbc10aefc5fc3ad92e8567cf34dcadda..944d7312e1fd102374ec0507d046791c64089c7d 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -560,57 +560,80 @@ static struct key *create_key( struct key *key, WCHAR *name, WCHAR *class,
     return key;
 }
 
-/* find a subkey of a given key by its index */
-static void enum_key( struct key *parent, int index, WCHAR *name, WCHAR *class, time_t *modif )
+/* query information about a key or a subkey */
+static size_t enum_key( struct key *key, int index, struct enum_key_request *req )
 {
-    struct key *key;
+    int i;
+    size_t len, namelen, classlen;
+    int max_subkey = 0, max_class = 0;
+    int max_value = 0, max_data = 0;
+    WCHAR *data = get_req_data(req);
 
-    if ((index < 0) || (index > parent->last_subkey)) set_error( STATUS_NO_MORE_ENTRIES );
+    if (index != -1)  /* -1 means use the specified key directly */
+    {
+        if ((index < 0) || (index > key->last_subkey))
+        {
+            set_error( STATUS_NO_MORE_ENTRIES );
+            return 0;
+        }
+        key = key->subkeys[index];
+    }
+
+    if (req->full)
+    {
+        for (i = 0; i <= key->last_subkey; i++)
+        {
+            struct key *subkey = key->subkeys[i];
+            len = strlenW( subkey->name );
+            if (len > max_subkey) max_subkey = len;
+            if (!subkey->class) continue;
+            len = strlenW( subkey->class );
+            if (len > max_class) max_class = len;
+        }
+        for (i = 0; i <= key->last_value; i++)
+        {
+            len = strlenW( key->values[i].name );
+            if (len > max_value) max_value = len;
+            len = key->values[i].len;
+            if (len > max_data) max_data = len;
+        }
+        req->max_subkey = max_subkey;
+        req->max_class  = max_class;
+        req->max_value  = max_value;
+        req->max_data   = max_data;
+    }
     else
     {
-        key = parent->subkeys[index];
-        *modif = key->modif;
-        strcpyW( name, key->name );
-        if (key->class) strcpyW( class, key->class );  /* FIXME: length */
-        else *class = 0;
-        if (debug_level > 1) dump_operation( key, NULL, "Enum" );
+        req->max_subkey = 0;
+        req->max_class  = 0;
+        req->max_value  = 0;
+        req->max_data   = 0;
     }
-}
+    req->subkeys = key->last_subkey + 1;
+    req->values  = key->last_value + 1;
+    req->modif   = key->modif;
 
-/* query information about a key */
-static void query_key( struct key *key, struct query_key_info_request *req )
-{
-    int i, len;
-    int max_subkey = 0, max_class = 0;
-    int max_value = 0, max_data = 0;
+    namelen = strlenW(key->name) * sizeof(WCHAR);
+    classlen = key->class ? strlenW(key->class) * sizeof(WCHAR) : 0;
 
-    for (i = 0; i <= key->last_subkey; i++)
+    len = namelen + classlen + sizeof(WCHAR);
+    if (len > get_req_data_size(req))
     {
-        struct key *subkey = key->subkeys[i];
-        len = strlenW( subkey->name );
-        if (len > max_subkey) max_subkey = len;
-        if (!subkey->class) continue;
-        len = strlenW( subkey->class );
-        if (len > max_class) max_class = len;
+        len = get_req_data_size(req);
+        if (len < sizeof(WCHAR)) return 0;
     }
-    for (i = 0; i <= key->last_value; i++)
+
+    *data++ = namelen;
+    len -= sizeof(WCHAR);
+    if (len > namelen)
     {
-        len = strlenW( key->values[i].name );
-        if (len > max_value) max_value = len;
-        len = key->values[i].len;
-        if (len > max_data) max_data = len;
-    }
-    req->subkeys    = key->last_subkey + 1;
-    req->max_subkey = max_subkey;
-    req->max_class  = max_class;
-    req->values     = key->last_value + 1;
-    req->max_value  = max_value;
-    req->max_data   = max_data;
-    req->modif      = key->modif;
-    strcpyW( req->name, key->name);
-    if (key->class) strcpyW( req->class, key->class );  /* FIXME: length */
-    else req->class[0] = 0;
-    if (debug_level > 1) dump_operation( key, NULL, "Query" );
+        memcpy( data, key->name, namelen );
+        memcpy( (char *)data + namelen, key->class, min(classlen,len-namelen) );
+    }
+    else memcpy( data, key->name, len );
+
+    if (debug_level > 1) dump_operation( key, NULL, "Enum" );
+    return len + sizeof(WCHAR);
 }
 
 /* delete a key and its values */
@@ -1537,31 +1560,29 @@ DECL_HANDLER(create_key)
 
     if (access & MAXIMUM_ALLOWED) access = KEY_ALL_ACCESS;  /* FIXME: needs general solution */
     req->hkey = -1;
+    if (!(name = copy_req_path( req, &len ))) return;
     if ((parent = get_hkey_obj( req->parent, 0 /*FIXME*/ )))
     {
-        if ((name = copy_req_path( req, &len )))
+        if (len == get_req_data_size(req))  /* no class specified */
         {
-            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);
+            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)
+            if ((class = req_strdupW( req, class_ptr, get_req_data_size(req) - len )))
             {
-                req->hkey = alloc_handle( current->process, key, access, 0 );
-                release_object( key );
+                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 );
+        }
         release_object( parent );
     }
 }
@@ -1602,26 +1623,15 @@ DECL_HANDLER(delete_key)
 DECL_HANDLER(enum_key)
 {
     struct key *key;
+    size_t len = 0;
 
-    req->name[0] = req->class[0] = 0;
-    if ((key = get_hkey_obj( req->hkey, KEY_ENUMERATE_SUB_KEYS )))
-    {
-        enum_key( key, req->index, req->name, req->class, &req->modif );
-        release_object( key );
-    }
-}
-
-/* query information about a registry key */
-DECL_HANDLER(query_key_info)
-{
-    struct key *key;
-
-    req->name[0] = req->class[0] = 0;
-    if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
+    if ((key = get_hkey_obj( req->hkey,
+                             req->index == -1 ? KEY_QUERY_VALUE : KEY_ENUMERATE_SUB_KEYS )))
     {
-        query_key( key, req );
+        len = enum_key( key, req->index, req );
         release_object( key );
     }
+    set_req_data_size( req, len );
 }
 
 /* set a value of a registry key */
@@ -1631,15 +1641,13 @@ DECL_HANDLER(set_key_value)
     WCHAR *name;
     size_t len;
 
+    if (!(name = copy_req_path( req, &len ))) return;
     if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE )))
     {
-        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;
+        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 );
-        }
+        set_value( key, name, req->type, req->total, req->offset, datalen, data );
         release_object( key );
     }
 }
@@ -1649,19 +1657,17 @@ DECL_HANDLER(get_key_value)
 {
     struct key *key;
     WCHAR *name;
-    size_t len;
+    size_t len = 0, tmp;
 
     req->len = 0;
+    if (!(name = copy_req_path( req, &tmp ))) return;
     if ((key = get_hkey_obj( req->hkey, KEY_QUERY_VALUE )))
     {
-        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 );
-        }
+        len = get_value( key, name, req->offset, get_req_data_size(req),
+                         &req->type, &req->len, get_req_data(req) );
         release_object( key );
     }
+    set_req_data_size( req, len );
 }
 
 /* enumerate the value of a registry key */
diff --git a/server/request.h b/server/request.h
index 738b4d070cb8ab22f6d9ac10b8a4f7a789809de0..ac80b7bbcc77c9833bebe7009f611f0d17d22146 100644
--- a/server/request.h
+++ b/server/request.h
@@ -176,7 +176,6 @@ DECL_HANDLER(create_key);
 DECL_HANDLER(open_key);
 DECL_HANDLER(delete_key);
 DECL_HANDLER(enum_key);
-DECL_HANDLER(query_key_info);
 DECL_HANDLER(set_key_value);
 DECL_HANDLER(get_key_value);
 DECL_HANDLER(enum_key_value);
@@ -291,7 +290,6 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
     (req_handler)req_open_key,
     (req_handler)req_delete_key,
     (req_handler)req_enum_key,
-    (req_handler)req_query_key_info,
     (req_handler)req_set_key_value,
     (req_handler)req_get_key_value,
     (req_handler)req_enum_key_value,
diff --git a/server/trace.c b/server/trace.c
index bc3e4ff49146d145f5e21d5c1f6df97edb184a63..b9e02a8135c976cc3859831e5858002c7bdb6c1a 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -94,7 +94,7 @@ static void dump_exc_record( const EXCEPTION_RECORD *rec )
     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++)
+    for (i = 0; i < min(rec->NumberParameters,EXCEPTION_MAXIMUM_PARAMETERS); i++)
     {
         if (i) fputc( ',', stderr );
         fprintf( stderr, "%lx", rec->ExceptionInformation[i] );
@@ -156,12 +156,12 @@ static size_t dump_varargs_string( const void *req )
 static size_t dump_varargs_unicode_len_str( const void *req )
 {
     const WCHAR *str = get_data(req);
-    WCHAR len = *str++;
+    int len = *str++ + sizeof(WCHAR);
     len = min( len, get_size(req) );
     fprintf( stderr, "L\"" );
-    dump_strW( str, len / sizeof(WCHAR), stderr, "\"\"" );
+    if (len >= sizeof(WCHAR)) dump_strW( str, (len / sizeof(WCHAR)) - 1, stderr, "\"\"" );
     fputc( '\"', stderr );
-    return len + sizeof(WCHAR);
+    return len;
 }
 
 static size_t dump_varargs_unicode_str( const void *req )
@@ -1184,25 +1184,11 @@ static void dump_delete_key_request( const struct delete_key_request *req )
 static void dump_enum_key_request( const struct enum_key_request *req )
 {
     fprintf( stderr, " hkey=%d,", req->hkey );
-    fprintf( stderr, " index=%d", req->index );
+    fprintf( stderr, " index=%d,", req->index );
+    fprintf( stderr, " full=%d", req->full );
 }
 
 static void dump_enum_key_reply( const struct enum_key_request *req )
-{
-    fprintf( stderr, " modif=%ld,", req->modif );
-    fprintf( stderr, " name=" );
-    dump_path_t( req, &req->name );
-    fprintf( stderr, "," );
-    fprintf( stderr, " class=" );
-    dump_unicode_string( req, req->class );
-}
-
-static void dump_query_key_info_request( const struct query_key_info_request *req )
-{
-    fprintf( stderr, " hkey=%d", req->hkey );
-}
-
-static void dump_query_key_info_reply( const struct query_key_info_request *req )
 {
     fprintf( stderr, " subkeys=%d,", req->subkeys );
     fprintf( stderr, " max_subkey=%d,", req->max_subkey );
@@ -1212,10 +1198,10 @@ static void dump_query_key_info_reply( const struct query_key_info_request *req
     fprintf( stderr, " max_data=%d,", req->max_data );
     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_set_key_value_request( const struct set_key_value_request *req )
@@ -1574,7 +1560,6 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_open_key_request,
     (dump_func)dump_delete_key_request,
     (dump_func)dump_enum_key_request,
-    (dump_func)dump_query_key_info_request,
     (dump_func)dump_set_key_value_request,
     (dump_func)dump_get_key_value_request,
     (dump_func)dump_enum_key_value_request,
@@ -1686,7 +1671,6 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_open_key_reply,
     (dump_func)0,
     (dump_func)dump_enum_key_reply,
-    (dump_func)dump_query_key_info_reply,
     (dump_func)0,
     (dump_func)dump_get_key_value_reply,
     (dump_func)dump_enum_key_value_reply,
@@ -1798,7 +1782,6 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
     "open_key",
     "delete_key",
     "enum_key",
-    "query_key_info",
     "set_key_value",
     "get_key_value",
     "enum_key_value",