mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
[MSVCRT:APITEST]
- Add a test which allows testing the command line argument lpCmdLine in WinMain function (GUI programs). svn path=/trunk/; revision=57524
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 <[email protected]>
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -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)
|
||||
@@ -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 <[email protected]>
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user