libwinpr-thread: initial CreateProcess() implementation
This commit is contained in:
parent
bb9db97204
commit
8d142eb85f
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
52
winpr/libwinpr/thread/test/TestThreadCreateProcess.c
Normal file
52
winpr/libwinpr/thread/test/TestThreadCreateProcess.c
Normal 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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user