FreeRDP
TestThreadCreateProcess.c
1 
2 #include <stdio.h>
3 #include <winpr/crt.h>
4 #include <winpr/tchar.h>
5 #include <winpr/synch.h>
6 #include <winpr/thread.h>
7 #include <winpr/environment.h>
8 #include <winpr/pipe.h>
9 
10 #define TESTENV_A "HELLO=WORLD"
11 #define TESTENV_T _T(TESTENV_A)
12 
13 int TestThreadCreateProcess(int argc, char* argv[])
14 {
15  BOOL status = 0;
16  DWORD exitCode = 0;
17  LPCTSTR lpApplicationName = NULL;
18 
19 #ifdef _WIN32
20  TCHAR lpCommandLine[200] = _T("cmd /C set");
21 #else
22  TCHAR lpCommandLine[200] = _T("printenv");
23 #endif
24 
25  // LPTSTR lpCommandLine;
26  LPSECURITY_ATTRIBUTES lpProcessAttributes = NULL;
27  LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
28  BOOL bInheritHandles = 0;
29  DWORD dwCreationFlags = 0;
30  LPVOID lpEnvironment = NULL;
31  LPCTSTR lpCurrentDirectory = NULL;
32  STARTUPINFO StartupInfo = { 0 };
33  PROCESS_INFORMATION ProcessInformation = { 0 };
34  LPTCH lpszEnvironmentBlock = NULL;
35  HANDLE pipe_read = NULL;
36  HANDLE pipe_write = NULL;
37  char buf[1024] = { 0 };
38  DWORD read_bytes = 0;
39  int ret = 0;
40  SECURITY_ATTRIBUTES saAttr;
41 
42  WINPR_UNUSED(argc);
43  WINPR_UNUSED(argv);
44 
45  lpszEnvironmentBlock = GetEnvironmentStrings();
46 
47  lpApplicationName = NULL;
48 
49  lpProcessAttributes = NULL;
50  lpThreadAttributes = NULL;
51  bInheritHandles = FALSE;
52  dwCreationFlags = 0;
53 #ifdef _UNICODE
54  dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
55 #endif
56  lpEnvironment = lpszEnvironmentBlock;
57  lpCurrentDirectory = NULL;
58  StartupInfo.cb = sizeof(STARTUPINFO);
59 
60  status = CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
61  lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
62  lpCurrentDirectory, &StartupInfo, &ProcessInformation);
63 
64  if (!status)
65  {
66  printf("CreateProcess failed. error=%" PRIu32 "\n", GetLastError());
67  return 1;
68  }
69 
70  if (WaitForSingleObject(ProcessInformation.hProcess, 5000) != WAIT_OBJECT_0)
71  {
72  printf("Failed to wait for first process. error=%" PRIu32 "\n", GetLastError());
73  return 1;
74  }
75 
76  exitCode = 0;
77  status = GetExitCodeProcess(ProcessInformation.hProcess, &exitCode);
78 
79  printf("GetExitCodeProcess status: %" PRId32 "\n", status);
80  printf("Process exited with code: 0x%08" PRIX32 "\n", exitCode);
81 
82  (void)CloseHandle(ProcessInformation.hProcess);
83  (void)CloseHandle(ProcessInformation.hThread);
84  FreeEnvironmentStrings(lpszEnvironmentBlock);
85 
86  /* Test stdin,stdout,stderr redirection */
87 
88  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
89  saAttr.bInheritHandle = TRUE;
90  saAttr.lpSecurityDescriptor = NULL;
91 
92  if (!CreatePipe(&pipe_read, &pipe_write, &saAttr, 0))
93  {
94  printf("Pipe creation failed. error=%" PRIu32 "\n", GetLastError());
95  return 1;
96  }
97 
98  bInheritHandles = TRUE;
99 
100  ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
101  StartupInfo.cb = sizeof(STARTUPINFO);
102  StartupInfo.hStdOutput = pipe_write;
103  StartupInfo.hStdError = pipe_write;
104  StartupInfo.dwFlags = STARTF_USESTDHANDLES;
105 
106  ZeroMemory(&ProcessInformation, sizeof(PROCESS_INFORMATION));
107 
108  if (!(lpEnvironment = calloc(1, sizeof(TESTENV_T) + sizeof(TCHAR))))
109  {
110  printf("Failed to allocate environment buffer. error=%" PRIu32 "\n", GetLastError());
111  return 1;
112  }
113  memcpy(lpEnvironment, (void*)TESTENV_T, sizeof(TESTENV_T));
114 
115  status = CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes,
116  lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
117  lpCurrentDirectory, &StartupInfo, &ProcessInformation);
118 
119  free(lpEnvironment);
120 
121  if (!status)
122  {
123  (void)CloseHandle(pipe_read);
124  (void)CloseHandle(pipe_write);
125  printf("CreateProcess failed. error=%" PRIu32 "\n", GetLastError());
126  return 1;
127  }
128 
129  if (WaitForSingleObject(ProcessInformation.hProcess, 5000) != WAIT_OBJECT_0)
130  {
131  printf("Failed to wait for second process. error=%" PRIu32 "\n", GetLastError());
132  return 1;
133  }
134 
135  ZeroMemory(buf, sizeof(buf));
136  ReadFile(pipe_read, buf, sizeof(buf) - 1, &read_bytes, NULL);
137  if (!strstr((const char*)buf, TESTENV_A))
138  {
139  printf("No or unexpected data read from pipe\n");
140  ret = 1;
141  }
142 
143  (void)CloseHandle(pipe_read);
144  (void)CloseHandle(pipe_write);
145 
146  exitCode = 0;
147  status = GetExitCodeProcess(ProcessInformation.hProcess, &exitCode);
148 
149  printf("GetExitCodeProcess status: %" PRId32 "\n", status);
150  printf("Process exited with code: 0x%08" PRIX32 "\n", exitCode);
151 
152  (void)CloseHandle(ProcessInformation.hProcess);
153  (void)CloseHandle(ProcessInformation.hThread);
154 
155  return ret;
156 }