libwinpr-thread: initial CreateProcess() implementation

This commit is contained in:
Marc-André Moreau 2013-09-22 17:23:00 -04:00
parent bb9db97204
commit 8d142eb85f
9 changed files with 177 additions and 34 deletions

View File

@ -52,6 +52,15 @@ BOOL CloseHandle(HANDLE hObject)
return TRUE;
}
else if (Type == HANDLE_TYPE_PROCESS)
{
WINPR_PROCESS* process;
process = (WINPR_PROCESS*) Object;
free(process);
return TRUE;
}
else if (Type == HANDLE_TYPE_MUTEX)
{
WINPR_MUTEX* mutex;

View File

@ -23,13 +23,14 @@
#include <winpr/handle.h>
#define HANDLE_TYPE_NONE 0
#define HANDLE_TYPE_THREAD 1
#define HANDLE_TYPE_EVENT 2
#define HANDLE_TYPE_MUTEX 3
#define HANDLE_TYPE_SEMAPHORE 4
#define HANDLE_TYPE_TIMER 5
#define HANDLE_TYPE_NAMED_PIPE 6
#define HANDLE_TYPE_ANONYMOUS_PIPE 7
#define HANDLE_TYPE_PROCESS 1
#define HANDLE_TYPE_THREAD 2
#define HANDLE_TYPE_EVENT 3
#define HANDLE_TYPE_MUTEX 4
#define HANDLE_TYPE_SEMAPHORE 5
#define HANDLE_TYPE_TIMER 6
#define HANDLE_TYPE_NAMED_PIPE 7
#define HANDLE_TYPE_ANONYMOUS_PIPE 8
#define WINPR_HANDLE_DEF() \
ULONG Type

View File

@ -43,6 +43,8 @@
#ifndef _WIN32
#include <sys/wait.h>
#include "../handle/handle.h"
#include "../pipe/pipe.h"
@ -102,6 +104,17 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
thread->dwExitCode = ((DWORD) (size_t) thread_status);
}
}
else if (Type == HANDLE_TYPE_PROCESS)
{
WINPR_PROCESS* process;
process = (WINPR_PROCESS*) Object;
if (waitpid(process->pid, &(process->status), 0) != -1)
{
return WAIT_FAILED;
}
}
else if (Type == HANDLE_TYPE_MUTEX)
{
WINPR_MUTEX* mutex;

View File

@ -101,7 +101,7 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
int maxBufferSize;
int currentIndex;
int cmdLineLength;
LPSTR lpEscapedChars;
BOOL* lpEscapedChars;
LPSTR lpEscapedCmdLine;
if (!lpCmdLine)
@ -116,15 +116,15 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
lpEscapedCmdLine = NULL;
cmdLineLength = strlen(lpCmdLine);
lpEscapedChars = (char*) malloc(cmdLineLength + 1);
ZeroMemory(lpEscapedChars, cmdLineLength + 1);
lpEscapedChars = (BOOL*) malloc((cmdLineLength + 1) * sizeof(BOOL));
ZeroMemory(lpEscapedChars, (cmdLineLength + 1) * sizeof(BOOL));
if (strstr(lpCmdLine, "\\\""))
{
int i, n;
char* pLastEnd = NULL;
lpEscapedCmdLine = (char*) malloc(cmdLineLength + 1);
lpEscapedCmdLine = (char*) malloc((cmdLineLength + 1) * sizeof(char));
p = (char*) lpCmdLine;
pLastEnd = (char*) lpCmdLine;
@ -173,7 +173,7 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
p += n + 1;
if ((n % 2) != 0)
lpEscapedChars[pOutput - lpEscapedCmdLine] = '\\';
lpEscapedChars[pOutput - lpEscapedCmdLine] = TRUE;
*pOutput = '"';
pOutput++;
@ -188,7 +188,7 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
cmdLineLength = strlen(lpCmdLine);
}
maxNumArgs = 1;
maxNumArgs = 2;
currentIndex = 0;
p = (char*) lpCmdLine;
@ -240,7 +240,7 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
/* no whitespace escaped with double quotes */
p = &p[index + 1];
pEnd = p;
pEnd = p - 1;
length = (pEnd - pBeg);
@ -274,14 +274,14 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
if (p[index] == '\0')
{
p = &p[index + 1];
pEnd = p;
pEnd = p - 1;
}
else
{
p = &p[index + 1];
index = strcspn(p, " \t\0");
p = &p[index + 1];
pEnd = p;
pEnd = p - 1;
}
length = 0;
@ -312,7 +312,8 @@ LPSTR* CommandLineToArgvA(LPCSTR lpCmdLine, int* pNumArgs)
if (lpEscapedCmdLine)
free(lpEscapedCmdLine);
free(lpEscapedChars);
if (lpEscapedChars)
free(lpEscapedChars);
*pNumArgs = numArgs;

View File

@ -55,20 +55,69 @@
#include <unistd.h>
#endif
#include <winpr/crt.h>
#include <errno.h>
#include <spawn.h>
#include <sys/wait.h>
#include <pthread.h>
typedef void *(*pthread_start_routine)(void*);
#include "thread.h"
#include "../handle/handle.h"
BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
{
int status = 0;
pid_t pid;
char* envp;
int status;
int numArgs;
LPSTR* pArgs;
WINPR_THREAD* thread;
WINPR_PROCESS* process;
if (!lpApplicationName)
pid = 0;
numArgs = 0;
pArgs = CommandLineToArgvA(lpCommandLine, &numArgs);
envp = NULL;
status = posix_spawnp(&pid, pArgs[0], NULL, NULL, pArgs, &envp);
if (status != 0)
return FALSE;
status = execve(lpApplicationName, NULL, NULL);
process = (WINPR_PROCESS*) malloc(sizeof(WINPR_PROCESS));
if (!process)
return FALSE;
ZeroMemory(process, sizeof(WINPR_PROCESS));
WINPR_HANDLE_SET_TYPE(process, HANDLE_TYPE_PROCESS);
process->pid = pid;
process->status = 0;
thread = (WINPR_THREAD*) malloc(sizeof(WINPR_THREAD));
ZeroMemory(thread, sizeof(WINPR_THREAD));
if (!thread)
return FALSE;
WINPR_HANDLE_SET_TYPE(thread, HANDLE_TYPE_THREAD);
thread->mainProcess = TRUE;
lpProcessInformation->hProcess = (HANDLE) process;
lpProcessInformation->hThread = (HANDLE) thread;
lpProcessInformation->dwProcessId = (DWORD) pid;
lpProcessInformation->dwThreadId = (DWORD) pid;
return TRUE;
}

View File

@ -5,7 +5,8 @@ set(MODULE_PREFIX "TEST_THREAD")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestThreadCommandLineToArgv.c)
TestThreadCommandLineToArgv.c
TestThreadCreateProcess.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}

View File

@ -3,69 +3,76 @@
#include <winpr/crt.h>
#include <winpr/thread.h>
const char* test_args_line_1 = "abc d e";
const char* test_args_line_1 = "app.exe abc d e";
const char* test_args_list_1[] =
{
"app.exe",
"abc",
"d",
"e",
NULL
};
const char* test_args_line_2 = "abc \t def";
const char* test_args_line_2 = "app.exe abc \t def";
const char* test_args_list_2[] =
{
"app.exe",
"abc",
"def",
NULL
};
const char* test_args_line_3 = "\"abc\" d e";
const char* test_args_line_3 = "app.exe \"abc\" d e";
const char* test_args_list_3[] =
{
"app.exe",
"abc",
"d",
"e",
NULL
};
const char* test_args_line_4 = "a\\\\b d\"e f\"g h";
const char* test_args_line_4 = "app.exe a\\\\b d\"e f\"g h";
const char* test_args_list_4[] =
{
"app.exe",
"a\\\\b",
"de fg",
"h",
NULL
};
const char* test_args_line_5 = "a\\\\\\\"b c d";
const char* test_args_line_5 = "app.exe a\\\\\\\"b c d";
const char* test_args_list_5[] =
{
"app.exe",
"a\\\"b",
"c",
"d",
NULL
};
const char* test_args_line_6 = "a\\\\\\\\\"b c\" d e";
const char* test_args_line_6 = "app.exe a\\\\\\\\\"b c\" d e";
const char* test_args_list_6[] =
{
"app.exe",
"a\\\\b c",
"d",
"e",
NULL
};
const char* test_args_line_7 = "a\\\\\\\\\"b c\" d e f\\\\\\\\\"g h\" i j";
const char* test_args_line_7 = "app.exe a\\\\\\\\\"b c\" d e f\\\\\\\\\"g h\" i j";
const char* test_args_list_7[] =
{
"app.exe",
"a\\\\b c",
"d",
"e",
@ -79,18 +86,18 @@ static int test_command_line_parsing_case(const char* line, const char** list)
{
int i;
LPSTR* pArgs;
int pNumArgs;
int numArgs;
pArgs = NULL;
pNumArgs = 0;
numArgs = 0;
printf("Parsing: %s\n", line);
pArgs = CommandLineToArgvA(line, &pNumArgs);
pArgs = CommandLineToArgvA(line, &numArgs);
printf("pNumArgs: %d\n", pNumArgs);
printf("pNumArgs: %d\n", numArgs);
for (i = 0; i < pNumArgs; i++)
for (i = 0; i < numArgs; i++)
{
printf("argv[%d] = %s\n", i, pArgs[i]);
}

View File

@ -0,0 +1,52 @@
#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/tchar.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
int TestThreadCreateProcess(int argc, char* argv[])
{
BOOL status;
LPCTSTR lpApplicationName;
LPTSTR lpCommandLine;
LPSECURITY_ATTRIBUTES lpProcessAttributes;
LPSECURITY_ATTRIBUTES lpThreadAttributes;
BOOL bInheritHandles;
DWORD dwCreationFlags;
LPVOID lpEnvironment;
LPCTSTR lpCurrentDirectory;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
lpApplicationName = NULL;
lpCommandLine = _T("ls -l /");
lpProcessAttributes = NULL;
lpThreadAttributes = NULL;
bInheritHandles = FALSE;
dwCreationFlags = 0;
lpEnvironment = NULL;
lpCurrentDirectory = NULL;
ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
StartupInfo.cb = sizeof(STARTUPINFO);
ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
status = CreateProcess(lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
&StartupInfo,
&ProcessInformation);
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
return 0;
}

View File

@ -35,6 +35,7 @@ struct winpr_thread
WINPR_HANDLE_DEF();
BOOL started;
BOOL mainProcess;
DWORD dwExitCode;
pthread_t thread;
SIZE_T dwStackSize;
@ -45,6 +46,15 @@ struct winpr_thread
};
typedef struct winpr_thread WINPR_THREAD;
struct winpr_process
{
WINPR_HANDLE_DEF();
pid_t pid;
int status;
};
typedef struct winpr_process WINPR_PROCESS;
#endif
#endif /* WINPR_THREAD_PRIVATE_H */