[WINSPOOL]
authorColin Finck <colin@reactos.org>
Wed, 6 Jan 2016 04:31:53 +0000 (04:31 +0000)
committerColin Finck <colin@reactos.org>
Wed, 6 Jan 2016 04:31:53 +0000 (04:31 +0000)
Add and fully implement IsValidDevmodeA and IsValidDevmodeW.

[WINSPOOL_APITEST]
Add tests for IsValidDevmodeA and IsValidDevmodeW covering the entire functions.

svn path=/branches/colins-printing-for-freedom/; revision=70503

reactos/win32ss/printing/base/winspool/CMakeLists.txt
reactos/win32ss/printing/base/winspool/devmode.c [new file with mode: 0644]
reactos/win32ss/printing/base/winspool/winspool.spec
rostests/apitests/winspool/CMakeLists.txt
rostests/apitests/winspool/IsValidDevmode.c [new file with mode: 0644]
rostests/apitests/winspool/testlist.c

index a922bae..b1ff3b1 100644 (file)
@@ -4,6 +4,7 @@ add_rpc_files(client ${REACTOS_SOURCE_DIR}/include/reactos/idl/winspool.idl)
 spec2def(winspool.drv winspool.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
+    devmode.c
     jobs.c
     main.c
     monitors.c
diff --git a/reactos/win32ss/printing/base/winspool/devmode.c b/reactos/win32ss/printing/base/winspool/devmode.c
new file mode 100644 (file)
index 0000000..d035f86
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * PROJECT:     ReactOS Spooler API
+ * LICENSE:     GNU LGPL v2.1 or any later version as published by the Free Software Foundation
+ * PURPOSE:     Functions giving information about DEVMODE structures
+ * COPYRIGHT:   Copyright 2016 Colin Finck <colin@reactos.org>
+ */
+
+#include "precomp.h"
+
+BOOL WINAPI
+IsValidDevmodeA(PDEVMODEA pDevmode, size_t DevmodeSize)
+{
+    // Check if a Devmode was given, its dmSize member is at least as big as the DEVMODEA structure
+    // and DevmodeSize is large enough for the public and private members of the structure.
+    if (!pDevmode ||
+        pDevmode->dmSize < sizeof(DEVMODEA) ||
+        DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra)
+    {
+        SetLastError(ERROR_INVALID_DATA);
+        return FALSE;
+    }
+
+    // Return success without setting the error code.
+    return TRUE;
+}
+
+BOOL WINAPI
+IsValidDevmodeW(PDEVMODEW pDevmode, size_t DevmodeSize)
+{
+    // Check if a Devmode was given, its dmSize member is at least as big as the DEVMODEW structure
+    // and DevmodeSize is large enough for the public and private members of the structure.
+    if (!pDevmode ||
+        pDevmode->dmSize < sizeof(DEVMODEW) ||
+        DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra)
+    {
+        SetLastError(ERROR_INVALID_DATA);
+        return FALSE;
+    }
+
+    // Return success without setting the error code.
+    return TRUE;
+}
index cccf966..03c1d1e 100644 (file)
 256 stdcall GetPrinterDriverW(long wstr long ptr long ptr)
 257 stdcall GetPrinterW(long long ptr long ptr)
 258 stub GetSpoolFileHandle
-259 stub IsValidDevmodeA
-260 stub IsValidDevmodeW
+259 stdcall IsValidDevmodeA(ptr long)
+260 stdcall IsValidDevmodeW(ptr long)
 261 stdcall OpenPrinterA(str ptr ptr)
 262 stdcall OpenPrinterW(wstr ptr ptr)
 263 stub PlayGdiScriptOnPrinterIC
index b7a356b..c1c7e6a 100644 (file)
@@ -4,6 +4,7 @@ list(APPEND SOURCE
     EnumPrinters.c
     EnumPrintProcessorDatatypes.c
     GetPrintProcessorDirectory.c
+    IsValidDevmode.c
     OpenPrinter.c
     StartDocPrinter.c
     testlist.c)
diff --git a/rostests/apitests/winspool/IsValidDevmode.c b/rostests/apitests/winspool/IsValidDevmode.c
new file mode 100644 (file)
index 0000000..a71eac3
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * PROJECT:     ReactOS Print Spooler DLL API Tests
+ * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
+ * PURPOSE:     Tests for IsValidDevmodeA/IsValidDevmodeW
+ * COPYRIGHT:   Copyright 2016 Colin Finck <colin@reactos.org>
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <winspool.h>
+
+// With very high probability, this is everything you can test for IsValidDevmode.
+// For your own testing, you can fill a DevMode structure with random bytes multiple times,
+// always set dmSize and dmDriverExtra appropriately and feed it to IsValidDevmode.
+// The function will always succeed.
+// I'm not doing that here, because I don't want to introduce randomness.
+
+START_TEST(IsValidDevmodeA)
+{
+    DEVMODEA DevMode;
+
+    // Give no Devmode at all, this has to fail without crashing.
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeA(NULL, sizeof(DEVMODEA)), "IsValidDevmodeA returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    // Give a zeroed Devmode, this has to fail, because dmSize isn't set.
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeA(&DevMode, sizeof(DEVMODEA)), "IsValidDevmodeA returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    // Now set only the dmSize member, IsValidDevmodeA should return TRUE now. The Last Error isn't touched again.
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    DevMode.dmSize = sizeof(DEVMODEA);
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeA(&DevMode, sizeof(DEVMODEA)), "IsValidDevmodeA returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    // IsValidDevmodeA should also succeed if the DevMode appears to be larger.
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    DevMode.dmSize = sizeof(DEVMODEA) + 1;
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeA(&DevMode, sizeof(DEVMODEA) + 1), "IsValidDevmodeA returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    // The DevmodeSize parameter may be larger than dmSize, but not the other way round!
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    DevMode.dmSize = sizeof(DEVMODEA);
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeA(&DevMode, sizeof(DEVMODEA) + 1), "IsValidDevmodeA returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    DevMode.dmSize = sizeof(DEVMODEA) + 1;
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeA(&DevMode, sizeof(DEVMODEA)), "IsValidDevmodeA returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    // dmDriverExtra is also taken into account.
+    ZeroMemory(&DevMode, sizeof(DEVMODEA));
+    DevMode.dmSize = sizeof(DEVMODEA);
+    DevMode.dmDriverExtra = 1;
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeA(&DevMode, sizeof(DEVMODEA)), "IsValidDevmodeA returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeA(&DevMode, sizeof(DEVMODEA) + 1), "IsValidDevmodeA returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeA returns error %lu!\n", GetLastError());
+}
+
+START_TEST(IsValidDevmodeW)
+{
+    DEVMODEW DevMode;
+
+    // Give no Devmode at all, this has to fail without crashing.
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeW(NULL, sizeof(DEVMODEW)), "IsValidDevmodeW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    // Give a zeroed Devmode, this has to fail, because dmSize isn't set.
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeW(&DevMode, sizeof(DEVMODEW)), "IsValidDevmodeW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    // Now set only the dmSize member, IsValidDevmodeW should return TRUE now. The Last Error isn't touched again.
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    DevMode.dmSize = sizeof(DEVMODEW);
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeW(&DevMode, sizeof(DEVMODEW)), "IsValidDevmodeW returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    // IsValidDevmodeW should also succeed if the DevMode appears to be larger.
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    DevMode.dmSize = sizeof(DEVMODEW) + 1;
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeW(&DevMode, sizeof(DEVMODEW) + 1), "IsValidDevmodeW returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+    
+    // The DevmodeSize parameter may be larger than dmSize, but not the other way round!
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    DevMode.dmSize = sizeof(DEVMODEW);
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeW(&DevMode, sizeof(DEVMODEW) + 1), "IsValidDevmodeW returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    DevMode.dmSize = sizeof(DEVMODEW) + 1;
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeW(&DevMode, sizeof(DEVMODEW)), "IsValidDevmodeW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    // dmDriverExtra is also taken into account.
+    ZeroMemory(&DevMode, sizeof(DEVMODEW));
+    DevMode.dmSize = sizeof(DEVMODEW);
+    DevMode.dmDriverExtra = 1;
+    SetLastError(0xDEADBEEF);
+    ok(!IsValidDevmodeW(&DevMode, sizeof(DEVMODEW)), "IsValidDevmodeW returns TRUE!\n");
+    ok(GetLastError() == ERROR_INVALID_DATA, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+
+    SetLastError(0xDEADBEEF);
+    ok(IsValidDevmodeW(&DevMode, sizeof(DEVMODEW) + 1), "IsValidDevmodeW returns FALSE!\n");
+    ok(GetLastError() == 0xDEADBEEF, "IsValidDevmodeW returns error %lu!\n", GetLastError());
+}
index 0581c50..189eb7c 100644 (file)
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Print Spooler DLL API Tests
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Test list
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2016 Colin Finck <colin@reactos.org>
  */
 
 #define __ROS_LONG64__
@@ -14,6 +14,8 @@ extern void func_ClosePrinter(void);
 extern void func_EnumPrinters(void);
 extern void func_EnumPrintProcessorDatatypes(void);
 extern void func_GetPrintProcessorDirectory(void);
+extern void func_IsValidDevmodeA(void);
+extern void func_IsValidDevmodeW(void);
 extern void func_OpenPrinter(void);
 extern void func_StartDocPrinter(void);
 
@@ -23,6 +25,8 @@ const struct test winetest_testlist[] =
     { "EnumPrinters", func_EnumPrinters },
     { "EnumPrintProcessorDatatypes", func_EnumPrintProcessorDatatypes },
     { "GetPrintProcessorDirectory", func_GetPrintProcessorDirectory },
+    { "IsValidDevmodeA", func_IsValidDevmodeA },
+    { "IsValidDevmodeW", func_IsValidDevmodeW },
     { "OpenPrinter", func_OpenPrinter },
     { "StartDocPrinter", func_StartDocPrinter },