#include #include #include #include #include #include #include #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; }