Alexandre Julliard : ntdll: Fix the return status of NtQueryValueKey for a too small buffer.

Alexandre Julliard julliard at winehq.org
Tue Feb 16 11:44:41 CST 2010


Module: wine
Branch: master
Commit: 2530304f1c0b3ca0855ef2eb9b0fdff1886c7db8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2530304f1c0b3ca0855ef2eb9b0fdff1886c7db8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Feb 16 14:28:41 2010 +0100

ntdll: Fix the return status of NtQueryValueKey for a too small buffer.

---

 dlls/kernel32/except.c |    2 +-
 dlls/kernel32/path.c   |    2 +-
 dlls/ntdll/reg.c       |   27 ++++++++++++---------------
 dlls/ntdll/tests/reg.c |   19 +++++++++++++++++--
 4 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/dlls/kernel32/except.c b/dlls/kernel32/except.c
index 6ed88ad..de07442 100644
--- a/dlls/kernel32/except.c
+++ b/dlls/kernel32/except.c
@@ -220,7 +220,7 @@ static BOOL	start_debugger(PEXCEPTION_POINTERS epointers, HANDLE hEvent)
 
         RtlInitUnicodeString( &nameW, DebuggerW );
         if (NtQueryValueKey( hDbgConf, &nameW, KeyValuePartialInformation,
-                             NULL, 0, &format_size ) == STATUS_BUFFER_OVERFLOW)
+                             NULL, 0, &format_size ) == STATUS_BUFFER_TOO_SMALL)
         {
             char *data = HeapAlloc(GetProcessHeap(), 0, format_size);
             NtQueryValueKey( hDbgConf, &nameW, KeyValuePartialInformation,
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c
index d77ecc1..2b69e8c 100644
--- a/dlls/kernel32/path.c
+++ b/dlls/kernel32/path.c
@@ -182,7 +182,7 @@ static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
 
     /* First we check if the key exists and if so how many bytes it already contains. */
     if (NtQueryValueKey( Reboot, &nameW, KeyValuePartialInformation,
-                         NULL, 0, &DataSize ) == STATUS_BUFFER_OVERFLOW)
+                         NULL, 0, &DataSize ) == STATUS_BUFFER_TOO_SMALL)
     {
         if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
             goto Quit;
diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c
index 50ec081..9b3aae5 100644
--- a/dlls/ntdll/reg.c
+++ b/dlls/ntdll/reg.c
@@ -477,7 +477,7 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
 {
     NTSTATUS ret;
     UCHAR *data_ptr;
-    unsigned int fixed_size = 0;
+    unsigned int fixed_size = 0, min_size = 0;
 
     TRACE( "(%p,%s,%d,%p,%d)\n", handle, debugstr_us(name), info_class, info, length );
 
@@ -489,30 +489,26 @@ NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
     case KeyValueBasicInformation:
     {
         KEY_VALUE_BASIC_INFORMATION *basic_info = info;
-        if (FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) < length)
-        {
-            memcpy(basic_info->Name, name->Buffer,
-                   min(length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name), name->Length));
-        }
-        fixed_size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name) + name->Length;
+        min_size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name);
+        fixed_size = min_size + name->Length;
+        if (min_size < length)
+            memcpy(basic_info->Name, name->Buffer, min(length - min_size, name->Length));
         data_ptr = NULL;
         break;
     }
     case KeyValueFullInformation:
     {
         KEY_VALUE_FULL_INFORMATION *full_info = info;
-        if (FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) < length)
-        {
-            memcpy(full_info->Name, name->Buffer,
-                   min(length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name), name->Length));
-        }
+        min_size = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
+        fixed_size = min_size + name->Length;
+        if (min_size < length)
+            memcpy(full_info->Name, name->Buffer, min(length - min_size, name->Length));
         data_ptr = (UCHAR *)full_info->Name + name->Length;
-        fixed_size = (char *)data_ptr - (char *)info;
         break;
     }
     case KeyValuePartialInformation:
+        min_size = fixed_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
         data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
-        fixed_size = (char *)data_ptr - (char *)info;
         break;
     default:
         FIXME( "Information class %d not implemented\n", info_class );
@@ -529,7 +525,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 < min_size) ret = STATUS_BUFFER_TOO_SMALL;
+            else if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
         }
     }
     SERVER_END_REQ;
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index 3521065..67bd125 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -480,7 +480,7 @@ static void test_NtQueryValueKey(void)
     KEY_VALUE_BASIC_INFORMATION *basic_info;
     KEY_VALUE_PARTIAL_INFORMATION *partial_info;
     KEY_VALUE_FULL_INFORMATION *full_info;
-    DWORD len;
+    DWORD len, expected;
 
     pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
 
@@ -554,7 +554,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(partial_info, 0xbd, len+1);
     status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len);
@@ -564,6 +564,21 @@ static void test_NtQueryValueKey(void)
     ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength);
     ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n");
     ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE));
+
+    expected = len;
+    status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 0, &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
+    ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
+    status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 1, &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
+    ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
+    status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) - 1, &len);
+    ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status);
+    ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
+    status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data), &len);
+    ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey wrong status 0x%08x\n", status);
+    ok(len == expected, "NtQueryValueKey wrong len %u\n", len);
+
     HeapFree(GetProcessHeap(), 0, partial_info);
 
     pRtlFreeUnicodeString(&ValName);




More information about the wine-cvs mailing list