[1/2] ntdll: Fix NtQueryValueKey ret. value for insufficient buffer

Nikolay Sivov bunglehead at gmail.com
Thu Jan 15 12:59:05 CST 2009


Changelog:
   - Fix NtQueryValueKey ret. value for insufficient buffer
   - Added some tests for NULL arguments and a fix for them

>From 89c908d7c575882b3a447c1738a2fbf9dd4f41e7 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Thu, 15 Jan 2009 21:25:44 +0300
Subject:   Fix ret. value for NtQueryValueKey. Added some tests for NULL arguments.

---
 dlls/ntdll/reg.c       |    5 ++++-
 dlls/ntdll/tests/reg.c |   31 ++++++++++++++++++++++++++++++-
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c
index 0d6a137..c1b81ec 100644
--- a/dlls/ntdll/reg.c
+++ b/dlls/ntdll/reg.c
@@ -470,6 +470,8 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
 
     TRACE( "(%p,%s,%d,%p,%d)\n", handle, debugstr_us(name), info_class, info, length );
 
+    if (!name || !result_len) return STATUS_ACCESS_VIOLATION;
+
     if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
 
     /* compute the length we want to retrieve */
@@ -518,7 +520,8 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
             copy_key_value_info( info_class, info, length, reply->type,
                                  name->Length, reply->total );
             *result_len = fixed_size + (info_class == KeyValueBasicInformation ? 0 : reply->total);
-            if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
+            if (length < *result_len)
+                ret = info ? STATUS_BUFFER_OVERFLOW: STATUS_BUFFER_TOO_SMALL;
         }
     }
     SERVER_END_REQ;
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index 0e25c06..2230be3 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -481,12 +481,41 @@ static void test_NtQueryValueKey(void)
     KEY_VALUE_PARTIAL_INFORMATION *partial_info;
     KEY_VALUE_FULL_INFORMATION *full_info;
     DWORD len;
+    USHORT namelength;
 
     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
+    namelength = ValName.Length;
 
     InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
     status = pNtOpenKey(&key, KEY_READ, &attr);
     ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
+ 
+    /* NULL arguments */
+    len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
+    basic_info = HeapAlloc(GetProcessHeap(), 0, len);
+    status = pNtQueryValueKey(key, NULL, KeyValueBasicInformation, NULL, 0, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    status = pNtQueryValueKey(key, NULL, KeyValueBasicInformation, NULL, len, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, NULL, len, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    status = pNtQueryValueKey(key, NULL, KeyValueBasicInformation, NULL, len, &len);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]), "NtQueryValueKey returned wrong len %d\n", len);
+    status = pNtQueryValueKey(key, NULL, KeyValueBasicInformation, basic_info, len, &len);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]), "NtQueryValueKey returned wrong len %d\n", len);
+    status = pNtQueryValueKey(key, NULL, KeyValueBasicInformation, basic_info, len, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]), "NtQueryValueKey returned wrong len %d\n", len);
+    status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, NULL);
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
+    HeapFree(GetProcessHeap(), 0, basic_info);
+    /* Test the order of argument checking */
+    ValName.Length = MAX_PATH*sizeof(WCHAR);
+    status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, NULL, len, NULL);
+    ValName.Length = namelength;
+    ok(status == STATUS_ACCESS_VIOLATION, "NtQueryValueKey should have returned STATUS_ACCESS_VIOLATION instead of 0x%08x\n", status);
 
     len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
     basic_info = HeapAlloc(GetProcessHeap(), 0, len);
@@ -554,7 +583,7 @@ static void test_NtQueryValueKey(void)
     pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest");
 
     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len);
-    todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status);
     partial_info = HeapAlloc(GetProcessHeap(), 0, len+1);
     memset((BYTE*)partial_info, 0xbd, len+1);
     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
-- 
1.5.6.5






More information about the wine-patches mailing list