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; 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) else if (Type == HANDLE_TYPE_MUTEX)
{ {
WINPR_MUTEX* mutex; WINPR_MUTEX* mutex;

View File

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

View File

@ -43,6 +43,8 @@
#ifndef _WIN32 #ifndef _WIN32
#include <sys/wait.h>
#include "../handle/handle.h" #include "../handle/handle.h"
#include "../pipe/pipe.h" #include "../pipe/pipe.h"
@ -102,6 +104,17 @@ DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds)
thread->dwExitCode = ((DWORD) (size_t) thread_status); 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) else if (Type == HANDLE_TYPE_MUTEX)
{ {
WINPR_MUTEX* mutex; WINPR_MUTEX* mutex;

View File

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

View File

@ -55,20 +55,69 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <winpr/crt.h>
#include <errno.h>
#include <spawn.h>
#include <sys/wait.h>
#include <pthread.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, BOOL CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) 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; 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; return TRUE;
} }

View File

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

View File

@ -3,69 +3,76 @@
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/thread.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[] = const char* test_args_list_1[] =
{ {
"app.exe",
"abc", "abc",
"d", "d",
"e", "e",
NULL 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[] = const char* test_args_list_2[] =
{ {
"app.exe",
"abc", "abc",
"def", "def",
NULL 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[] = const char* test_args_list_3[] =
{ {
"app.exe",
"abc", "abc",
"d", "d",
"e", "e",
NULL 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[] = const char* test_args_list_4[] =
{ {
"app.exe",
"a\\\\b", "a\\\\b",
"de fg", "de fg",
"h", "h",
NULL 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[] = const char* test_args_list_5[] =
{ {
"app.exe",
"a\\\"b", "a\\\"b",
"c", "c",
"d", "d",
NULL 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[] = const char* test_args_list_6[] =
{ {
"app.exe",
"a\\\\b c", "a\\\\b c",
"d", "d",
"e", "e",
NULL 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[] = const char* test_args_list_7[] =
{ {
"app.exe",
"a\\\\b c", "a\\\\b c",
"d", "d",
"e", "e",
@ -79,18 +86,18 @@ static int test_command_line_parsing_case(const char* line, const char** list)
{ {
int i; int i;
LPSTR* pArgs; LPSTR* pArgs;
int pNumArgs; int numArgs;
pArgs = NULL; pArgs = NULL;
pNumArgs = 0; numArgs = 0;
printf("Parsing: %s\n", line); 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]); 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(); WINPR_HANDLE_DEF();
BOOL started; BOOL started;
BOOL mainProcess;
DWORD dwExitCode; DWORD dwExitCode;
pthread_t thread; pthread_t thread;
SIZE_T dwStackSize; SIZE_T dwStackSize;
@ -45,6 +46,15 @@ struct winpr_thread
}; };
typedef struct winpr_thread 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
#endif /* WINPR_THREAD_PRIVATE_H */ #endif /* WINPR_THREAD_PRIVATE_H */