Author: tfaber
Date: Mon May  2 13:19:44 2016
New Revision: 71232

URL: http://svn.reactos.org/svn/reactos?rev=71232&view=rev
Log:
[NTOS:CM]
- Correctly handle NULL Data with nonzero DataSize in NtSetValueKey
ROSTESTS-200 #resolve

Added:
    trunk/rostests/apitests/ntdll/NtSetValueKey.c   (with props)
Modified:
    trunk/reactos/ntoskrnl/config/ntapi.c
    trunk/rostests/apitests/ntdll/CMakeLists.txt
    trunk/rostests/apitests/ntdll/testlist.c

Modified: trunk/reactos/ntoskrnl/config/ntapi.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/ntapi.c?rev=71232&r1=71231&r2=71232&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/config/ntapi.c       [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/ntapi.c       [iso-8859-1] Mon May  2 
13:19:44 2016
@@ -630,11 +630,11 @@
         Data = NULL;
 
     /* Probe and copy the data */
-    if ((PreviousMode != KernelMode) && Data)
+    if ((PreviousMode != KernelMode) && (DataSize != 0))
     {
         PVOID DataCopy = ExAllocatePoolWithTag(PagedPool, DataSize, TAG_CM);
         if (!DataCopy)
-            return STATUS_NO_MEMORY;
+            return STATUS_INSUFFICIENT_RESOURCES;
         _SEH2_TRY
         {
             ProbeForRead(Data, DataSize, 1);

Modified: trunk/rostests/apitests/ntdll/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/CMakeLists.txt?rev=71232&r1=71231&r2=71232&view=diff
==============================================================================
--- trunk/rostests/apitests/ntdll/CMakeLists.txt        [iso-8859-1] (original)
+++ trunk/rostests/apitests/ntdll/CMakeLists.txt        [iso-8859-1] Mon May  2 
13:19:44 2016
@@ -18,6 +18,7 @@
     NtQuerySystemEnvironmentValue.c
     NtQueryVolumeInformationFile.c
     NtSaveKey.c
+    NtSetValueKey.c
     RtlAllocateHeap.c
     RtlBitmap.c
     RtlCopyMappedMemory.c

Added: trunk/rostests/apitests/ntdll/NtSetValueKey.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/NtSetValueKey.c?rev=71232
==============================================================================
--- trunk/rostests/apitests/ntdll/NtSetValueKey.c       (added)
+++ trunk/rostests/apitests/ntdll/NtSetValueKey.c       [iso-8859-1] Mon May  2 
13:19:44 2016
@@ -0,0 +1,209 @@
+/*
+ * PROJECT:         ReactOS API tests
+ * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
+ * PURPOSE:         Test for NtSetValueKey
+ * PROGRAMMER:      Thomas Faber <[email protected]>
+ */
+
+#include <apitest.h>
+
+#include <winreg.h>
+#define WIN32_NO_STATUS
+#include <ndk/cmfuncs.h>
+#include <ndk/obfuncs.h>
+#include <ndk/rtlfuncs.h>
+#include <strsafe.h>
+
+START_TEST(NtSetValueKey)
+{
+    NTSTATUS Status;
+    HANDLE ParentKeyHandle;
+    HANDLE KeyHandle;
+    UNICODE_STRING KeyName = 
RTL_CONSTANT_STRING(L"SOFTWARE\\ntdll-apitest-NtSetValueKey");
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING ValueName;
+    WCHAR Default[] = L"Default";
+    WCHAR Hello[] = L"Hello";
+    WCHAR Empty[] = L"";
+    NTSTATUS QueryStatus;
+    PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
+    ULONG PartialInfoLength;
+    ULONG ResultLength;
+    const struct
+    {
+        ULONG Type;
+        PVOID Data;
+        ULONG DataSize;
+        NTSTATUS StatusExisting;
+        NTSTATUS StatusNew;
+        NTSTATUS StatusExisting2;
+        NTSTATUS StatusNew2;
+    } Tests[] =
+    {
+        { REG_NONE,   NULL,                 0,             STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Empty REG_NONE value */
+        { REG_SZ,     Hello,                sizeof(Hello), STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Regular string */
+        { REG_SZ,     Empty,                sizeof(Empty), STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Empty string */
+        { REG_SZ,     NULL,                 0,             STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Zero length */
+        { REG_SZ,     Hello,                0,             STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Zero length, non-null data */
+        { REG_SZ,     (PVOID)(LONG_PTR)-4,  0,             STATUS_SUCCESS,     
           STATUS_SUCCESS                }, /* Zero length, kernel data */
+        { REG_SZ,     NULL,                 1,             
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION       }, /* Non-zero 
length (odd), null data */
+        { REG_SZ,     NULL,                 2,             
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION       }, /* Non-zero 
length (even), null data */
+        { REG_SZ,     NULL,                 4,             
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION       }, /* 
CM_KEY_VALUE_SMALL, null data */
+        { REG_SZ,     NULL,                 5,             
STATUS_INVALID_PARAMETER,      STATUS_ACCESS_VIOLATION,         /* 
CM_KEY_VALUE_SMALL+1, null data */
+                                                           
STATUS_ACCESS_VIOLATION,       STATUS_INSUFFICIENT_RESOURCES },        /* win7 
*/
+        { REG_SZ,     NULL,                 6,             
STATUS_INVALID_PARAMETER,      STATUS_ACCESS_VIOLATION,         /* 
CM_KEY_VALUE_SMALL+2, null data */
+                                                           
STATUS_ACCESS_VIOLATION,       STATUS_INSUFFICIENT_RESOURCES },        /* win7 
*/
+        { REG_SZ,     NULL,                 0x7fff0000,    
STATUS_INVALID_PARAMETER,      STATUS_INSUFFICIENT_RESOURCES,   /* 
MI_USER_PROBE_ADDRESS, null data */
+                                                           
STATUS_INSUFFICIENT_RESOURCES, STATUS_INSUFFICIENT_RESOURCES },        /* win7 
*/
+        { REG_SZ,     NULL,                 0x7fff0001,    
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION,         /* 
MI_USER_PROBE_ADDRESS+1, null data */
+                                                           
STATUS_INSUFFICIENT_RESOURCES, STATUS_INSUFFICIENT_RESOURCES },        /* win7 
*/
+        { REG_SZ,     NULL,                 0x7fffffff,    
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION,         /* <2GB, null 
data */
+                                                           
STATUS_INVALID_PARAMETER,      STATUS_INVALID_PARAMETER      },        /* win7 
*/
+        { REG_SZ,     NULL,                 0x80000000,    
STATUS_ACCESS_VIOLATION,       STATUS_ACCESS_VIOLATION,         /* 2GB, null 
data */
+                                                           
STATUS_INVALID_PARAMETER,      STATUS_INVALID_PARAMETER      },        /* win7 
*/
+        { REG_BINARY, NULL,                 5,             
STATUS_INVALID_PARAMETER,      STATUS_ACCESS_VIOLATION,         /* ROSTESTS-200 
*/
+                                                           
STATUS_ACCESS_VIOLATION,       STATUS_INSUFFICIENT_RESOURCES },        /* win7 
*/
+    };
+    ULONG i;
+
+    Status = RtlOpenCurrentUser(READ_CONTROL, &ParentKeyHandle);
+    ok(Status == STATUS_SUCCESS, "RtlOpenCurrentUser returned %lx\n", Status);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("No user key handle\n");
+        return;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               ParentKeyHandle,
+                               NULL);
+    Status = NtCreateKey(&KeyHandle,
+                         KEY_QUERY_VALUE | KEY_SET_VALUE | DELETE,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE,
+                         NULL);
+    ok(Status == STATUS_SUCCESS, "NtCreateKey returned %lx\n", Status);
+    if (!NT_SUCCESS(Status))
+    {
+        NtClose(ParentKeyHandle);
+        skip("No key handle\n");
+        return;
+    }
+
+    PartialInfoLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[128]);
+    PartialInfo = HeapAlloc(GetProcessHeap(), 0, PartialInfoLength);
+    if (PartialInfo == NULL)
+    {
+        NtDeleteKey(KeyHandle);
+        NtClose(KeyHandle);
+        NtClose(ParentKeyHandle);
+        skip("No key handle\n");
+        return;
+    }
+
+    for (i = 0; i < RTL_NUMBER_OF(Tests); i++)
+    {
+        /*
+         * Existing value
+         */
+        /* Make sure it exists */
+        RtlInitUnicodeString(&ValueName, L"ExistingValue");
+        Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, Default, 
sizeof(Default));
+        ok(Status == STATUS_SUCCESS, "[%lu] NtSetValueKey failed with %lx", i, 
Status);
+
+        /* Set it */
+        Status = NtSetValueKey(KeyHandle, &ValueName, 0, Tests[i].Type, 
Tests[i].Data, Tests[i].DataSize);
+        if (Status == Tests[i].StatusExisting2)
+            ok(Status == Tests[i].StatusExisting || Status == 
Tests[i].StatusExisting2, "[%lu, %p, %lu] NtSetValueKey returned %lx, expected 
%lx or %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, Status, 
Tests[i].StatusExisting, Tests[i].StatusExisting2);
+        else
+            ok(Status == Tests[i].StatusExisting, "[%lu, %p, %lu] 
NtSetValueKey returned %lx, expected %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, Status, 
Tests[i].StatusExisting);
+
+        /* Check it */
+        RtlZeroMemory(PartialInfo, PartialInfoLength);
+        QueryStatus = NtQueryValueKey(KeyHandle, &ValueName, 
KeyValuePartialInformation, PartialInfo, PartialInfoLength, &ResultLength);
+        ok(QueryStatus == STATUS_SUCCESS, "[%lu, %p, %lu] NtQueryValueKey 
failed with %lx\n",
+           Tests[i].Type, Tests[i].Data, Tests[i].DataSize, QueryStatus);
+        if (NT_SUCCESS(QueryStatus))
+        {
+            if (NT_SUCCESS(Status))
+            {
+                ok(PartialInfo->TitleIndex == 0, "[%lu, %p, %lu] TitleIndex = 
%lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->TitleIndex);
+                ok(PartialInfo->Type == Tests[i].Type, "[%lu, %p, %lu] Type = 
%lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->Type);
+                ok(PartialInfo->DataLength == Tests[i].DataSize, "[%lu, %p, 
%lu] DataLength = %lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->DataLength);
+                ok(!memcmp(PartialInfo->Data, Tests[i].Data, 
Tests[i].DataSize), "[%lu, %p, %lu] Data does not match set value\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize);
+            }
+            else
+            {
+                ok(PartialInfo->TitleIndex == 0, "[%lu, %p, %lu] TitleIndex = 
%lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->TitleIndex);
+                ok(PartialInfo->Type == REG_SZ, "[%lu, %p, %lu] Type = %lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->Type);
+                ok(PartialInfo->DataLength == sizeof(Default), "[%lu, %p, %lu] 
DataLength = %lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->DataLength);
+                ok(!memcmp(PartialInfo->Data, Default, sizeof(Default)), 
"[%lu, %p, %lu] Data does not match default\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize);
+            }
+        }
+
+        /*
+         * New value
+         */
+        /* Make sure it doesn't exist */
+        RtlInitUnicodeString(&ValueName, L"NewValue");
+        Status = NtDeleteValueKey(KeyHandle, &ValueName);
+        ok(Status == STATUS_SUCCESS || Status == STATUS_OBJECT_NAME_NOT_FOUND,
+           "[%lu] NtDeleteValueKey failed with %lx", i, Status);
+
+        /* Set it */
+        Status = NtSetValueKey(KeyHandle, &ValueName, 0, Tests[i].Type, 
Tests[i].Data, Tests[i].DataSize);
+        if (Tests[i].StatusNew2)
+            ok(Status == Tests[i].StatusNew || Status == Tests[i].StatusNew2, 
"[%lu, %p, %lu] NtSetValueKey returned %lx, expected %lx or %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, Status, 
Tests[i].StatusNew, Tests[i].StatusNew2);
+        else
+            ok(Status == Tests[i].StatusNew, "[%lu, %p, %lu] NtSetValueKey 
returned %lx, expected %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, Status, 
Tests[i].StatusNew);
+
+        /* Check it */
+        RtlZeroMemory(PartialInfo, PartialInfoLength);
+        QueryStatus = NtQueryValueKey(KeyHandle, &ValueName, 
KeyValuePartialInformation, PartialInfo, PartialInfoLength, &ResultLength);
+        if (NT_SUCCESS(Status))
+        {
+            ok(QueryStatus == STATUS_SUCCESS, "[%lu, %p, %lu] NtQueryValueKey 
failed with %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, QueryStatus);
+            if (NT_SUCCESS(QueryStatus))
+            {
+                ok(PartialInfo->TitleIndex == 0, "[%lu, %p, %lu] TitleIndex = 
%lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->TitleIndex);
+                ok(PartialInfo->Type == Tests[i].Type, "[%lu, %p, %lu] Type = 
%lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->Type);
+                ok(PartialInfo->DataLength == Tests[i].DataSize, "[%lu, %p, 
%lu] DataLength = %lu\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize, 
PartialInfo->DataLength);
+                ok(!memcmp(PartialInfo->Data, Tests[i].Data, 
Tests[i].DataSize), "[%lu, %p, %lu] Data does not match set value\n",
+                   Tests[i].Type, Tests[i].Data, Tests[i].DataSize);
+            }
+        }
+        else
+        {
+            ok(QueryStatus == STATUS_OBJECT_NAME_NOT_FOUND, "[%lu, %p, %lu] 
QueryStatus = %lx\n",
+               Tests[i].Type, Tests[i].Data, Tests[i].DataSize, QueryStatus);
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, PartialInfo);
+    Status = NtDeleteKey(KeyHandle);
+    ok(Status == STATUS_SUCCESS, "NtDeleteKey returned %lx\n", Status);
+    Status = NtClose(KeyHandle);
+    ok(Status == STATUS_SUCCESS, "NtClose returned %lx\n", Status);
+    Status = NtClose(ParentKeyHandle);
+    ok(Status == STATUS_SUCCESS, "NtClose returned %lx\n", Status);
+}

Propchange: trunk/rostests/apitests/ntdll/NtSetValueKey.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/rostests/apitests/ntdll/testlist.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/ntdll/testlist.c?rev=71232&r1=71231&r2=71232&view=diff
==============================================================================
--- trunk/rostests/apitests/ntdll/testlist.c    [iso-8859-1] (original)
+++ trunk/rostests/apitests/ntdll/testlist.c    [iso-8859-1] Mon May  2 
13:19:44 2016
@@ -21,6 +21,7 @@
 extern void func_NtQuerySystemEnvironmentValue(void);
 extern void func_NtQueryVolumeInformationFile(void);
 extern void func_NtSaveKey(void);
+extern void func_NtSetValueKey(void);
 extern void func_NtSystemInformation(void);
 extern void func_RtlAllocateHeap(void);
 extern void func_RtlBitmap(void);
@@ -63,6 +64,7 @@
     { "NtQuerySystemEnvironmentValue",  func_NtQuerySystemEnvironmentValue },
     { "NtQueryVolumeInformationFile",   func_NtQueryVolumeInformationFile },
     { "NtSaveKey",                      func_NtSaveKey},
+    { "NtSetValueKey",                  func_NtSetValueKey},
     { "NtSystemInformation",            func_NtSystemInformation },
     { "RtlAllocateHeap",                func_RtlAllocateHeap },
     { "RtlBitmapApi",                   func_RtlBitmap },


Reply via email to