1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*=============================================================================
6**
7** Source: test1.c
8**
9** Purpose: Test to ensure GetExitCodeProcess works properly.
10**
11** Dependencies: PAL_Initialize
12** PAL_Terminate
13** Fail
14** ZeroMemory
15** GetCurrentDirectoryW
16** CreateProcessW
17** WaitForSingleObject
18** GetLastError
19** strlen
20** strncpy
21**
22
23**
24**===========================================================================*/
25#include <palsuite.h>
26#include "myexitcode.h"
27
28
29static const char* rgchPathDelim = "\\";
30
31
32int
33mkAbsoluteFilename( LPSTR dirName,
34 DWORD dwDirLength,
35 LPCSTR fileName,
36 DWORD dwFileLength,
37 LPSTR absPathName )
38{
39 DWORD sizeDN, sizeFN, sizeAPN;
40
41 sizeDN = strlen( dirName );
42 sizeFN = strlen( fileName );
43 sizeAPN = (sizeDN + 1 + sizeFN + 1);
44
45 /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */
46 if( sizeAPN > _MAX_PATH )
47 {
48 return ( 0 );
49 }
50
51 strncpy( absPathName, dirName, dwDirLength +1 );
52 strncpy( absPathName, rgchPathDelim, 2 );
53 strncpy( absPathName, fileName, dwFileLength +1 );
54
55 return (sizeAPN);
56
57}
58
59
60int __cdecl main( int argc, char **argv )
61
62{
63 const char* rgchChildFile = "childprocess";
64
65 STARTUPINFO si;
66 PROCESS_INFORMATION pi;
67
68 DWORD dwError;
69 DWORD dwExitCode;
70 DWORD dwFileLength;
71 DWORD dwDirLength;
72 DWORD dwSize;
73
74 char rgchDirName[_MAX_DIR];
75 char absPathBuf[_MAX_PATH];
76 char* rgchAbsPathName;
77
78 /* initialize the PAL */
79 if( PAL_Initialize(argc, argv) != 0 )
80 {
81 return( FAIL );
82 }
83
84 /* zero our process and startup info structures */
85 ZeroMemory( &si, sizeof(si) );
86 si.cb = sizeof( si );
87 ZeroMemory( &pi, sizeof(pi) );
88
89 /* build the absolute path to the child process */
90 rgchAbsPathName = &absPathBuf[0];
91 dwFileLength = strlen( rgchChildFile );
92
93 dwDirLength = GetCurrentDirectory( _MAX_PATH, rgchDirName );
94 if( dwDirLength == 0 )
95 {
96 dwError = GetLastError();
97 Fail( "GetCurrentDirectory call failed with error code %d\n",
98 dwError );
99 }
100
101 dwSize = mkAbsoluteFilename( rgchDirName,
102 dwDirLength,
103 rgchChildFile,
104 dwFileLength,
105 rgchAbsPathName );
106 if( dwSize == 0 )
107 {
108 Fail( "Palsuite Code: mkAbsoluteFilename() call failed. Could ",
109 "not build absolute path name to file\n. Exiting.\n" );
110 }
111
112 /* launch the child process */
113 if( !CreateProcess( NULL, /* module name to execute */
114 rgchAbsPathName, /* command line */
115 NULL, /* process handle not */
116 /* inheritable */
117 NULL, /* thread handle not */
118 /* inheritable */
119 FALSE, /* handle inheritance */
120 CREATE_NEW_CONSOLE, /* dwCreationFlags */
121 NULL, /* use parent's environment */
122 NULL, /* use parent's starting */
123 /* directory */
124 &si, /* startup info struct */
125 &pi ) /* process info struct */
126 )
127 {
128 dwError = GetLastError();
129 Fail( "CreateProcess call failed with error code %d\n",
130 dwError );
131 }
132
133 /* wait for the child process to complete */
134 WaitForSingleObject ( pi.hProcess, INFINITE );
135
136 /* check the exit code from the process */
137 if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
138 {
139 dwError = GetLastError();
140 CloseHandle ( pi.hProcess );
141 CloseHandle ( pi.hThread );
142 Fail( "GetExitCodeProcess call failed with error code %d\n",
143 dwError );
144 }
145
146 /* close process and thread handle */
147 CloseHandle ( pi.hProcess );
148 CloseHandle ( pi.hThread );
149
150 /* check for the expected exit code */
151 if( dwExitCode != TEST_EXIT_CODE )
152 {
153 Fail( "GetExitCodeProcess returned an incorrect exit code %d, "
154 "expected value is %d\n",
155 dwExitCode, TEST_EXIT_CODE );
156 }
157
158 /* terminate the PAL */
159 PAL_Terminate();
160
161 /* return success */
162 return PASS;
163}
164