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