155 lines
4.2 KiB
C
155 lines
4.2 KiB
C
|
|
||
|
#include <stdio.h>
|
||
|
#include <winpr/crt.h>
|
||
|
#include <winpr/tchar.h>
|
||
|
#include <winpr/synch.h>
|
||
|
#include <winpr/thread.h>
|
||
|
#include <winpr/environment.h>
|
||
|
#include <winpr/pipe.h>
|
||
|
|
||
|
#define TESTENV_A "HELLO=WORLD"
|
||
|
#define TESTENV_T _T(TESTENV_A)
|
||
|
|
||
|
int TestThreadCreateProcess(int argc, char* argv[])
|
||
|
{
|
||
|
BOOL status;
|
||
|
DWORD exitCode;
|
||
|
LPCTSTR lpApplicationName;
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
TCHAR lpCommandLine[200] = _T("cmd /C set");
|
||
|
#else
|
||
|
TCHAR lpCommandLine[200] = _T("printenv");
|
||
|
#endif
|
||
|
|
||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes;
|
||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes;
|
||
|
BOOL bInheritHandles;
|
||
|
DWORD dwCreationFlags;
|
||
|
LPVOID lpEnvironment;
|
||
|
LPCTSTR lpCurrentDirectory;
|
||
|
STARTUPINFO StartupInfo;
|
||
|
PROCESS_INFORMATION ProcessInformation;
|
||
|
LPTCH lpszEnvironmentBlock;
|
||
|
HANDLE pipe_read = NULL;
|
||
|
HANDLE pipe_write = NULL;
|
||
|
char buf[1024];
|
||
|
DWORD read_bytes;
|
||
|
int ret = 0;
|
||
|
SECURITY_ATTRIBUTES saAttr;
|
||
|
|
||
|
lpszEnvironmentBlock = GetEnvironmentStrings();
|
||
|
|
||
|
lpApplicationName = NULL;
|
||
|
|
||
|
lpProcessAttributes = NULL;
|
||
|
lpThreadAttributes = NULL;
|
||
|
bInheritHandles = FALSE;
|
||
|
dwCreationFlags = 0;
|
||
|
#ifdef _UNICODE
|
||
|
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
|
||
|
#endif
|
||
|
lpEnvironment = lpszEnvironmentBlock;
|
||
|
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);
|
||
|
|
||
|
if (!status)
|
||
|
{
|
||
|
printf("CreateProcess failed. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (WaitForSingleObject(ProcessInformation.hProcess, 5000) != WAIT_OBJECT_0)
|
||
|
{
|
||
|
printf("Failed to wait for first process. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
exitCode = 0;
|
||
|
status = GetExitCodeProcess(ProcessInformation.hProcess, &exitCode);
|
||
|
|
||
|
printf("GetExitCodeProcess status: %" PRId32 "\n", status);
|
||
|
printf("Process exited with code: 0x%08" PRIX32 "\n", exitCode);
|
||
|
|
||
|
CloseHandle(ProcessInformation.hProcess);
|
||
|
CloseHandle(ProcessInformation.hThread);
|
||
|
FreeEnvironmentStrings(lpszEnvironmentBlock);
|
||
|
|
||
|
/* Test stdin,stdout,stderr redirection */
|
||
|
|
||
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||
|
saAttr.bInheritHandle = TRUE;
|
||
|
saAttr.lpSecurityDescriptor = NULL;
|
||
|
|
||
|
if (!CreatePipe(&pipe_read, &pipe_write, &saAttr, 0))
|
||
|
{
|
||
|
printf("Pipe creation failed. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bInheritHandles = TRUE;
|
||
|
|
||
|
ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
|
||
|
StartupInfo.cb = sizeof(STARTUPINFO);
|
||
|
StartupInfo.hStdOutput = pipe_write;
|
||
|
StartupInfo.hStdError = pipe_write;
|
||
|
StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||
|
|
||
|
ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
|
||
|
|
||
|
if (!(lpEnvironment = calloc(1, sizeof(TESTENV_T) + sizeof(TCHAR))))
|
||
|
{
|
||
|
printf("Failed to allocate environment buffer. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
memcpy(lpEnvironment, (void*)TESTENV_T, sizeof(TESTENV_T));
|
||
|
|
||
|
status = CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
|
||
|
lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
|
||
|
lpCurrentDirectory, &StartupInfo, &ProcessInformation);
|
||
|
|
||
|
free(lpEnvironment);
|
||
|
|
||
|
if (!status)
|
||
|
{
|
||
|
CloseHandle(pipe_read);
|
||
|
CloseHandle(pipe_write);
|
||
|
printf("CreateProcess failed. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (WaitForSingleObject(ProcessInformation.hProcess, 5000) != WAIT_OBJECT_0)
|
||
|
{
|
||
|
printf("Failed to wait for second process. error=%" PRIu32 "\n", GetLastError());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ZeroMemory(buf, sizeof(buf));
|
||
|
ReadFile(pipe_read, buf, sizeof(buf) - 1, &read_bytes, NULL);
|
||
|
if (!strstr((const char*)buf, TESTENV_A))
|
||
|
{
|
||
|
printf("No or unexpected data read from pipe\n");
|
||
|
ret = 1;
|
||
|
}
|
||
|
|
||
|
CloseHandle(pipe_read);
|
||
|
CloseHandle(pipe_write);
|
||
|
|
||
|
exitCode = 0;
|
||
|
status = GetExitCodeProcess(ProcessInformation.hProcess, &exitCode);
|
||
|
|
||
|
printf("GetExitCodeProcess status: %" PRId32 "\n", status);
|
||
|
printf("Process exited with code: 0x%08" PRIX32 "\n", exitCode);
|
||
|
|
||
|
CloseHandle(ProcessInformation.hProcess);
|
||
|
CloseHandle(ProcessInformation.hThread);
|
||
|
|
||
|
return ret;
|
||
|
}
|