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: test3.c |
8 | ** |
9 | ** Purpose: Test to ensure that OpenEventW() works when |
10 | ** opening an event created by another process. This test |
11 | ** program launches a child process which creates a |
12 | ** named, initially-unset event. The child waits up to |
13 | ** 10 seconds for the parent process to open that event |
14 | ** and set it, and returns PASS if the event was set or FAIL |
15 | ** otherwise. The parent process checks the return value |
16 | ** from the child to verify that the opened event was |
17 | ** properly used across processes. |
18 | ** |
19 | ** Dependencies: PAL_Initialize |
20 | ** PAL_Terminate |
21 | ** Fail |
22 | ** ZeroMemory |
23 | ** GetCurrentDirectoryW |
24 | ** CreateProcessW |
25 | ** WaitForSingleObject |
26 | ** GetExitCodeProcess |
27 | ** GetLastError |
28 | ** strlen |
29 | ** strncpy |
30 | ** |
31 | ** |
32 | **===========================================================================*/ |
33 | #include <palsuite.h> |
34 | |
35 | #define TIMEOUT 60000 |
36 | |
37 | int __cdecl main( int argc, char **argv ) |
38 | { |
39 | BOOL ret = FAIL; |
40 | LPSECURITY_ATTRIBUTES lpEventAttributes = NULL; |
41 | |
42 | STARTUPINFO si; |
43 | PROCESS_INFORMATION pi; |
44 | |
45 | DWORD dwExitCode; |
46 | |
47 | DWORD dwRet = 0; |
48 | HANDLE hEvent = NULL; |
49 | WCHAR wcName[] = {'P','A','L','R','o','c','k','s','\0'}; |
50 | LPWSTR lpName = wcName; |
51 | char lpCommandLine[MAX_PATH] = "" ; |
52 | |
53 | /* initialize the PAL */ |
54 | if( PAL_Initialize(argc, argv) != 0 ) |
55 | { |
56 | return( FAIL ); |
57 | } |
58 | |
59 | /* zero our process and startup info structures */ |
60 | ZeroMemory( &si, sizeof(si) ); |
61 | si.cb = sizeof( si ); |
62 | ZeroMemory( &pi, sizeof(pi) ); |
63 | |
64 | /* create an event which we can use with SetEvent */ |
65 | hEvent = CreateEventW( lpEventAttributes, |
66 | TRUE, /* manual reset */ |
67 | FALSE, /* unsignalled */ |
68 | lpName ); |
69 | |
70 | if( hEvent == NULL ) |
71 | { |
72 | /* ERROR */ |
73 | Fail( "ERROR:%lu:CreateEventW() call failed in child\n" , |
74 | GetLastError()); |
75 | } |
76 | |
77 | ZeroMemory( lpCommandLine, MAX_PATH ); |
78 | if ( sprintf_s( lpCommandLine, MAX_PATH-1, "childprocess " ) < 0 ) |
79 | { |
80 | Fail ("Error: Insufficient lpCommandline for\n" ); |
81 | } |
82 | |
83 | /* launch the child process */ |
84 | if( !CreateProcess( NULL, /* module name to execute */ |
85 | lpCommandLine, /* command line */ |
86 | NULL, /* process handle not */ |
87 | /* inheritable */ |
88 | NULL, /* thread handle not */ |
89 | /* inheritable */ |
90 | FALSE, /* handle inheritance */ |
91 | CREATE_NEW_CONSOLE, /* dwCreationFlags */ |
92 | NULL, /* use parent's environment */ |
93 | NULL, /* use parent's starting */ |
94 | /* directory */ |
95 | &si, /* startup info struct */ |
96 | &pi ) /* process info struct */ |
97 | ) |
98 | { |
99 | Fail( "ERROR:%lu:CreateProcess call failed\n" , |
100 | GetLastError() ); |
101 | } |
102 | |
103 | /* verify that the event is signalled by the child process */ |
104 | dwRet = WaitForSingleObject( hEvent, TIMEOUT ); |
105 | if( dwRet != WAIT_OBJECT_0 ) |
106 | { |
107 | ret = FAIL; |
108 | /* ERROR */ |
109 | Trace( "ERROR:WaitForSingleObject() call returned %lu, " |
110 | "expected WAIT_TIMEOUT\n" , |
111 | "expected WAIT_OBJECT_0\n" , |
112 | dwRet ); |
113 | |
114 | goto cleanup; |
115 | |
116 | if( !CloseHandle( hEvent ) ) |
117 | { |
118 | Trace( "ERROR:%lu:CloseHandle() call failed in child\n" , |
119 | GetLastError()); |
120 | } |
121 | goto cleanup; |
122 | } |
123 | |
124 | /* wait for the child process to complete */ |
125 | dwRet = WaitForSingleObject ( pi.hProcess, TIMEOUT ); |
126 | if( dwRet != WAIT_OBJECT_0 ) |
127 | { |
128 | ret = FAIL; |
129 | Trace( "ERROR:WaitForSingleObject() returned %lu, " |
130 | "expected %lu\n" , |
131 | dwRet, |
132 | WAIT_OBJECT_0 ); |
133 | goto cleanup; |
134 | } |
135 | |
136 | /* check the exit code from the process */ |
137 | if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) ) |
138 | { |
139 | ret = FAIL; |
140 | Trace( "ERROR:%lu:GetExitCodeProcess call failed\n" , |
141 | GetLastError() ); |
142 | goto cleanup; |
143 | } |
144 | |
145 | /* check for success */ |
146 | ret = (dwExitCode == PASS) ? PASS : FAIL; |
147 | |
148 | cleanup: |
149 | if( hEvent != NULL ) |
150 | { |
151 | if( ! CloseHandle ( hEvent ) ) |
152 | { |
153 | Trace( "ERROR:%lu:CloseHandle call failed on event handle\n" , |
154 | GetLastError() ); |
155 | ret = FAIL; |
156 | } |
157 | } |
158 | |
159 | |
160 | /* close process and thread handle */ |
161 | if( ! CloseHandle ( pi.hProcess ) ) |
162 | { |
163 | Trace( "ERROR:%lu:CloseHandle call failed on process handle\n" , |
164 | GetLastError() ); |
165 | ret = FAIL; |
166 | } |
167 | |
168 | if( ! CloseHandle ( pi.hThread ) ) |
169 | { |
170 | Trace( "ERROR:%lu:CloseHandle call failed on thread handle\n" , |
171 | GetLastError() ); |
172 | ret = FAIL; |
173 | } |
174 | |
175 | /* output a convenient error message and exit if we failed */ |
176 | if( ret == FAIL ) |
177 | { |
178 | Fail( "test failed\n" ); |
179 | } |
180 | |
181 | |
182 | /* terminate the PAL */ |
183 | PAL_Terminate(); |
184 | |
185 | /* return success */ |
186 | return ret; |
187 | } |
188 | |