[MSVCRT:APITEST]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 9 Oct 2012 20:56:11 +0000 (20:56 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 9 Oct 2012 20:56:11 +0000 (20:56 +0000)
- Add a test which allows testing the command line argument lpCmdLine in WinMain function (GUI programs).

svn path=/trunk/; revision=57524

rostests/apitests/msvcrt/CMakeLists.txt
rostests/apitests/msvcrt/CommandLine.c [new file with mode: 0644]
rostests/apitests/msvcrt/cmdline_util/CMakeLists.txt [new file with mode: 0644]
rostests/apitests/msvcrt/cmdline_util/cmdline_util.c [new file with mode: 0644]
rostests/apitests/msvcrt/testlist.c

index 59c6772..07022be 100644 (file)
@@ -1,7 +1,10 @@
 
+add_subdirectory(cmdline_util)
+
 add_definitions(-D_DLL -D__USE_CRTIMP)
 
 list(APPEND SOURCE
+    CommandLine.c
     ieee.c
     splitpath.c
     testlist.c)
diff --git a/rostests/apitests/msvcrt/CommandLine.c b/rostests/apitests/msvcrt/CommandLine.c
new file mode 100644 (file)
index 0000000..e6b6c99
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * PROJECT:         ReactOS API Tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Test for CRT command-line handling.
+ * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO <hermes.belusca@sfr.fr>
+ */
+
+#define WIN32_NO_STATUS
+#define UNICODE
+#include <stdio.h>
+#include <wine/test.h>
+#include <ndk/ntndk.h>
+
+#define COUNT_OF(x) (sizeof((x))/sizeof((x)[0]))
+
+/*
+ * The path to the data file is hardcoded in cmdline_util.c
+ * Please synchronize it whenever you do a change.
+ */
+#define DATAFILE    L"C:\\cmdline.dat"
+
+/**
+ * Extracts the command tail from the command line
+ * (deletes the program's name and keep the rest).
+ **/
+#define SPACECHAR   L' '
+#define DQUOTECHAR  L'\"'
+
+LPWSTR ExtractCmdLine(IN LPWSTR lpszCommandLine)
+{
+    BOOL inDoubleQuote = FALSE;
+
+    /*
+     * Skip the program's name (the first token in the command line).
+     * Handle quoted program's name.
+     */
+    if (lpszCommandLine)
+    {
+        while ( (*lpszCommandLine > SPACECHAR) ||
+                (*lpszCommandLine && inDoubleQuote) )
+        {
+            if (*lpszCommandLine == DQUOTECHAR)
+                inDoubleQuote = !inDoubleQuote;
+
+            ++lpszCommandLine;
+        }
+
+        /* Skip all white spaces preceeding the second token. */
+        while (*lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
+            ++lpszCommandLine;
+    }
+
+    return lpszCommandLine;
+}
+
+VOID ExtractCmdLine_U(IN OUT PUNICODE_STRING pCommandLine_U)
+{
+    BOOL inDoubleQuote = FALSE;
+    PWSTR lpszCommandLine;
+
+    /*
+     * Skip the program's name (the first token in the command line).
+     * Handle quoted program's name.
+     */
+    if (pCommandLine_U && pCommandLine_U->Buffer && (pCommandLine_U->Length != 0))
+    {
+        lpszCommandLine = pCommandLine_U->Buffer;
+
+        while ( (pCommandLine_U->Length > 0) &&
+                ( (*lpszCommandLine > SPACECHAR) ||
+                  (*lpszCommandLine && inDoubleQuote) ) )
+        {
+            if (*lpszCommandLine == DQUOTECHAR)
+                inDoubleQuote = !inDoubleQuote;
+
+            ++lpszCommandLine;
+            pCommandLine_U->Length -= sizeof(WCHAR);
+        }
+
+        /* Skip all white spaces preceeding the second token. */
+        while ((pCommandLine_U->Length > 0) && *lpszCommandLine && (*lpszCommandLine <= SPACECHAR))
+        {
+            ++lpszCommandLine;
+            pCommandLine_U->Length -= sizeof(WCHAR);
+        }
+
+        pCommandLine_U->Buffer = lpszCommandLine;
+    }
+
+    return;
+}
+
+
+typedef struct _TEST_CASE
+{
+    LPWSTR CmdLine;
+} TEST_CASE, *PTEST_CASE;
+
+static TEST_CASE TestCases[] =
+{
+    {L"cmdline_util.exe"},
+    {L"cmdline_util.exe foo bar"},
+    {L"cmdline_util.exe \"foo bar\""},
+    {L"cmdline_util.exe foo \"bar John\" Doe"},
+
+    {L"\"cmdline_util.exe\""},
+    {L"\"cmdline_util.exe\" foo bar"},
+    {L"\"cmdline_util.exe\" \"foo bar\""},
+    {L"\"cmdline_util.exe\" foo \"bar John\" Doe"},
+
+    {L"\"cmdline_util.exe\""},
+    {L"\"cmdline_util.exe \"foo bar\"\""},
+};
+
+static void Test_CommandLine(IN ULONG TestNumber,
+                             IN PTEST_CASE TestCase)
+{
+    BOOL bRet;
+
+    WCHAR CmdLine[MAX_PATH];
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+
+    ZeroMemory(&si, sizeof(si));
+    ZeroMemory(&pi, sizeof(pi));
+    si.cb = sizeof(si);
+
+    wcscpy(CmdLine, TestCase->CmdLine);
+
+    /*
+     * Launch the utility program and wait till it's terminated.
+     */
+    bRet = CreateProcessW(NULL,
+                          CmdLine,
+                          NULL, NULL,
+                          FALSE,
+                          CREATE_UNICODE_ENVIRONMENT,
+                          NULL, NULL,
+                          &si, &pi);
+    ok(bRet, "Test %lu - Failed to launch ' %S ', error = %lu.\n", TestNumber, TestCase->CmdLine, GetLastError());
+
+    if (bRet)
+    {
+        /* Wait until child process exits. */
+        WaitForSingleObject(pi.hProcess, INFINITE);
+
+        /* Close process and thread handles. */
+        CloseHandle(pi.hThread);
+        CloseHandle(pi.hProcess);
+    }
+
+    /*
+     * Analyses the result.
+     */
+    {
+        /* Open the data file. */
+        HANDLE hFile = CreateFileW(DATAFILE,
+                                   GENERIC_READ,
+                                   0, NULL,
+                                   OPEN_EXISTING,
+                                   FILE_ATTRIBUTE_NORMAL,
+                                   NULL);
+        ok(hFile != INVALID_HANDLE_VALUE, "Test %lu - Failed to open the data file 'C:\\cmdline.dat', error = %lu.\n", TestNumber, GetLastError());
+
+        if (hFile != INVALID_HANDLE_VALUE)
+        {
+            WCHAR BuffWinMain[MAX_PATH]; LPWSTR WinMainCmdLine = BuffWinMain;
+            WCHAR BuffWin32[MAX_PATH]  ; LPWSTR Win32CmdLine   = BuffWin32  ;
+            WCHAR BuffNT[0xffff /* Maximum USHORT size */];
+            UNICODE_STRING NTCmdLine;
+
+            DWORD dwSize, dwStringSize;
+
+            /*
+             * Format of the data file :
+             *
+             * [size_of_string 4 bytes][null_terminated_C_string]
+             * [size_of_string 4 bytes][null_terminated_C_string]
+             * [UNICODE_STRING_structure][string_buffer_of_UNICODE_STRING]
+             */
+
+            /* 1- Read the WinMain's command line. */
+            dwStringSize = 0;
+
+            ReadFile(hFile,
+                     &dwStringSize,
+                     sizeof(dwStringSize),
+                     &dwSize,
+                     NULL);
+
+            dwStringSize = min(dwStringSize, sizeof(BuffWinMain));
+            ReadFile(hFile,
+                     WinMainCmdLine,
+                     dwStringSize,
+                     &dwSize,
+                     NULL);
+            *(LPWSTR)((ULONG_PTR)WinMainCmdLine + dwStringSize) = 0;
+
+            /* 2- Read the Win32 mode command line. */
+            dwStringSize = 0;
+
+            ReadFile(hFile,
+                     &dwStringSize,
+                     sizeof(dwStringSize),
+                     &dwSize,
+                     NULL);
+
+            dwStringSize = min(dwStringSize, sizeof(BuffWin32));
+            ReadFile(hFile,
+                     Win32CmdLine,
+                     dwStringSize,
+                     &dwSize,
+                     NULL);
+            *(LPWSTR)((ULONG_PTR)Win32CmdLine + dwStringSize) = 0;
+
+            /* 3- Finally, read the UNICODE_STRING command line. */
+            ReadFile(hFile,
+                     &NTCmdLine,
+                     sizeof(NTCmdLine),
+                     &dwSize,
+                     NULL);
+
+            NTCmdLine.Buffer = BuffNT;
+            ReadFile(hFile,
+                     NTCmdLine.Buffer,
+                     NTCmdLine.Length,
+                     &dwSize,
+                     NULL);
+
+            /* Now close the file. */
+            CloseHandle(hFile);
+
+            /*
+             * Remove the program's name in the Win32 and NT command lines.
+             */
+            Win32CmdLine = ExtractCmdLine(Win32CmdLine);
+            ExtractCmdLine_U(&NTCmdLine);
+
+            /* Print the results */
+            *(LPWSTR)((ULONG_PTR)NTCmdLine.Buffer + NTCmdLine.Length) = 0;
+            printf("WinMain cmdline = '%S'\n"
+                   "Win32   cmdline = '%S'\n"
+                   "NT      cmdline = '%S'\n"
+                   "NT       length = %u\n",
+                   WinMainCmdLine,
+                   Win32CmdLine,
+                   NTCmdLine.Buffer, NTCmdLine.Length);
+
+            /*
+             * Now check the results.
+             */
+            dwStringSize = min(wcslen(WinMainCmdLine), wcslen(Win32CmdLine));
+            ok(wcslen(WinMainCmdLine) == wcslen(Win32CmdLine), "Test %lu - WinMain and Win32 command lines do not have the same length !\n", TestNumber);
+            ok(wcsncmp(WinMainCmdLine, Win32CmdLine, dwStringSize) == 0, "Test %lu - WinMain and Win32 command lines are different !\n", TestNumber);
+
+            dwStringSize = min(wcslen(WinMainCmdLine), NTCmdLine.Length / sizeof(WCHAR));
+            ok(wcsncmp(WinMainCmdLine, NTCmdLine.Buffer, dwStringSize) == 0, "Test %lu - WinMain and NT command lines are different !\n", TestNumber);
+
+            dwStringSize = min(wcslen(Win32CmdLine), NTCmdLine.Length / sizeof(WCHAR));
+            ok(wcsncmp(Win32CmdLine, NTCmdLine.Buffer, dwStringSize) == 0, "Test %lu - Win32 and NT command lines are different !\n", TestNumber);
+        }
+    }
+
+    /*
+     * Always delete the data file.
+     */
+    DeleteFileW(DATAFILE);
+}
+
+START_TEST(CommandLine)
+{
+    ULONG i;
+
+    for (i = 0 ; i < COUNT_OF(TestCases) ; ++i)
+    {
+        Test_CommandLine(i, &TestCases[i]);
+    }
+}
+
+/* EOF */
diff --git a/rostests/apitests/msvcrt/cmdline_util/CMakeLists.txt b/rostests/apitests/msvcrt/cmdline_util/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ce0cf5b
--- /dev/null
@@ -0,0 +1,10 @@
+
+add_definitions(-D_DLL -D__USE_CRTIMP)
+
+list(APPEND SOURCE
+     cmdline_util.c)
+
+add_executable(cmdline_util ${SOURCE})
+set_module_type(cmdline_util win32gui UNICODE)
+add_importlibs(cmdline_util msvcrt kernel32 ntdll)
+add_cd_file(TARGET cmdline_util DESTINATION reactos/bin FOR all)
diff --git a/rostests/apitests/msvcrt/cmdline_util/cmdline_util.c b/rostests/apitests/msvcrt/cmdline_util/cmdline_util.c
new file mode 100644 (file)
index 0000000..007e7f0
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * PROJECT:         ReactOS API Tests
+ * LICENSE:         GPLv2+ - See COPYING in the top level directory
+ * PURPOSE:         Test for CRT command-line handling - Utility GUI program.
+ * PROGRAMMER:      Hermès BÉLUSCA - MAÏTO <hermes.belusca@sfr.fr>
+ */
+
+#define WIN32_NO_STATUS
+#include <stdio.h>
+#include <windows.h>
+#include <ndk/ntndk.h>
+
+int APIENTRY wWinMain(HINSTANCE hInstance,
+                      HINSTANCE hPrevInstance,
+                      LPWSTR    lpCmdLine,
+                      int       nCmdShow)
+{
+    /*
+     * Get the unparsed command line as seen in Win32 mode,
+     * and the NT-native mode one.
+     */
+    LPWSTR CmdLine = GetCommandLineW();
+    UNICODE_STRING CmdLine_U = NtCurrentPeb()->ProcessParameters->CommandLine;
+
+    /* Write the results into a file. */
+    HANDLE hFile = CreateFileW(L"C:\\cmdline.dat",
+                               GENERIC_WRITE,
+                               0, NULL,
+                               CREATE_ALWAYS,
+                               FILE_ATTRIBUTE_NORMAL,
+                               NULL);
+    if (hFile != INVALID_HANDLE_VALUE)
+    {
+        DWORD dwSize, dwStringSize;
+
+        /*
+         * Format of the data file :
+         *
+         * [size_of_string 4 bytes][null_terminated_C_string]
+         * [size_of_string 4 bytes][null_terminated_C_string]
+         * [UNICODE_STRING_structure][string_buffer_of_UNICODE_STRING]
+         */
+
+        /* 1- Write the WinMain's command line. */
+        dwStringSize = (wcslen(lpCmdLine) + 1) * sizeof(WCHAR);
+
+        WriteFile(hFile,
+                  &dwStringSize,
+                  sizeof(dwStringSize),
+                  &dwSize,
+                  NULL);
+
+        WriteFile(hFile,
+                  lpCmdLine,
+                  dwStringSize,
+                  &dwSize,
+                  NULL);
+
+        /* 2- Write the Win32 mode command line. */
+        dwStringSize = (wcslen(CmdLine) + 1) * sizeof(WCHAR);
+
+        WriteFile(hFile,
+                  &dwStringSize,
+                  sizeof(dwStringSize),
+                  &dwSize,
+                  NULL);
+
+        WriteFile(hFile,
+                  CmdLine,
+                  dwStringSize,
+                  &dwSize,
+                  NULL);
+
+        /* 3- Finally, write the UNICODE_STRING command line. */
+        WriteFile(hFile,
+                  &CmdLine_U,
+                  sizeof(CmdLine_U),
+                  &dwSize,
+                  NULL);
+
+        WriteFile(hFile,
+                  CmdLine_U.Buffer,
+                  CmdLine_U.Length,
+                  &dwSize,
+                  NULL);
+
+        /* Now close the file. */
+        CloseHandle(hFile);
+    }
+
+    return 0;
+}
+
+/* EOF */
index 0e57890..e55fbda 100644 (file)
@@ -5,14 +5,15 @@
 #define STANDALONE
 #include "wine/test.h"
 
+extern void func_CommandLine(void);
 extern void func_ieee(void);
 extern void func_splitpath(void);
 
 const struct test winetest_testlist[] =
 {
+    { "CommandLine", func_CommandLine },
     { "ieee", func_ieee },
     { "splitpath", func_splitpath },
 
     { 0, 0 }
 };
-