mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
281 lines
8.4 KiB
C
281 lines
8.4 KiB
C
|
/*
|
|||
|
* PROJECT: ReactOS API Tests
|
|||
|
* LICENSE: GPLv2+ - See COPYING in the top level directory
|
|||
|
* PURPOSE: Test for CRT command-line handling.
|
|||
|
* PROGRAMMER: Herm<EFBFBD>s B<EFBFBD>LUSCA - MA<EFBFBD>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 */
|