mirror of
https://github.com/SSCLI/sscli_20021101
synced 2026-06-08 12:28:57 +00:00
9fa3874800
Moved the original file to the archive subfolder.
249 lines
8.2 KiB
C
249 lines
8.2 KiB
C
/*============================================================
|
|
**
|
|
** Source: createprocessa/test2/parentprocess.c
|
|
**
|
|
** Purpose: Test the following features of CreateProcessA:
|
|
** - Check to see if hProcess & hThread are set in
|
|
** return PROCESS_INFORMATION structure
|
|
** - Check to see if stdin, stdout, & stderr handles
|
|
** are used when STARTF_USESTDHANDLES is specified
|
|
** in STARUPINFO flags and bInheritHandles = TRUE
|
|
** - Check to see that proper arguments are passed to
|
|
** child process
|
|
**
|
|
** Dependencies: CreatePipe
|
|
** strcpy, strlen, strncmp, memset
|
|
** WaitForSingleObject
|
|
** WriteFile, ReadFile
|
|
** GetExitCodeProcess
|
|
**
|
|
**
|
|
** Copyright (c) 2002 Microsoft Corporation. All rights reserved.
|
|
**
|
|
** The use and distribution terms for this software are contained in the file
|
|
** named license.txt, which can be found in the root of this distribution.
|
|
** By using this software in any fashion, you are agreeing to be bound by the
|
|
** terms of this license.
|
|
**
|
|
** You must not remove this notice, or any other, from this software.
|
|
**
|
|
**
|
|
**=========================================================*/
|
|
|
|
#include <palsuite.h>
|
|
#include "test2.h"
|
|
|
|
|
|
|
|
int __cdecl main( int argc, char **argv )
|
|
{
|
|
|
|
/*******************************************
|
|
* Declarations
|
|
*******************************************/
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
HANDLE hTestStdInR = NULL;
|
|
HANDLE hTestStdInW = NULL;
|
|
HANDLE hTestStdOutR = NULL;
|
|
HANDLE hTestStdOutW = NULL;
|
|
HANDLE hTestStdErrR = NULL;
|
|
HANDLE hTestStdErrW = NULL;
|
|
|
|
BOOL bRetVal = FALSE;
|
|
DWORD dwBytesWritten = 0;
|
|
DWORD dwBytesRead = 0;
|
|
DWORD dwExitCode = 0;
|
|
|
|
SECURITY_ATTRIBUTES pipeAttributes;
|
|
|
|
char szStdOutBuf[BUF_LEN];
|
|
char szStdErrBuf[BUF_LEN];
|
|
char szFullPathNameA[_MAX_PATH];
|
|
|
|
|
|
/*******************************************
|
|
* Initialization
|
|
*******************************************/
|
|
|
|
if(0 != (PAL_Initialize(argc, argv)))
|
|
{
|
|
return ( FAIL );
|
|
}
|
|
|
|
/*Setup SECURITY_ATTRIBUTES structure for CreatePipe*/
|
|
pipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
pipeAttributes.lpSecurityDescriptor = NULL;
|
|
pipeAttributes.bInheritHandle = TRUE;
|
|
|
|
|
|
/*Create a StdIn pipe for child*/
|
|
bRetVal = CreatePipe(&hTestStdInR, /* read handle*/
|
|
&hTestStdInW, /* write handle */
|
|
&pipeAttributes, /* security attributes*/
|
|
1024); /* pipe size*/
|
|
|
|
if (bRetVal == FALSE)
|
|
{
|
|
Fail("ERROR: %ld :Unable to create stdin pipe\n", GetLastError());
|
|
}
|
|
|
|
|
|
/*Create a StdOut pipe for child*/
|
|
bRetVal = CreatePipe(&hTestStdOutR, /* read handle*/
|
|
&hTestStdOutW, /* write handle */
|
|
&pipeAttributes, /* security attributes*/
|
|
0); /* pipe size*/
|
|
|
|
if (bRetVal == FALSE)
|
|
{
|
|
Fail("ERROR: %ld :Unable to create stdout pipe\n", GetLastError());
|
|
}
|
|
|
|
|
|
/*Create a StdErr pipe for child*/
|
|
bRetVal = CreatePipe(&hTestStdErrR, /* read handle*/
|
|
&hTestStdErrW, /* write handle */
|
|
&pipeAttributes, /* security attributes*/
|
|
0); /* pipe size*/
|
|
|
|
if (bRetVal == FALSE)
|
|
{
|
|
Fail("ERROR: %ld :Unable to create stderr pipe\n", GetLastError());
|
|
}
|
|
|
|
/* Zero the data structure space */
|
|
ZeroMemory ( &pi, sizeof(pi) );
|
|
ZeroMemory ( &si, sizeof(si) );
|
|
|
|
/* Set the process flags and standard io handles */
|
|
si.cb = sizeof(si);
|
|
si.dwFlags = STARTF_USESTDHANDLES;
|
|
si.hStdInput = hTestStdInR;
|
|
si.hStdOutput = hTestStdOutW;
|
|
si.hStdError = hTestStdErrW;
|
|
|
|
strcpy(szFullPathNameA, szChildFileA);
|
|
strcat(szFullPathNameA, szArgs);
|
|
|
|
/*******************************************
|
|
* Start Testing
|
|
*******************************************/
|
|
|
|
/* Launch the child */
|
|
if ( !CreateProcessA (NULL, szFullPathNameA, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ))
|
|
{
|
|
Fail("ERROR: CreateProcess call failed. GetLastError returned %d\n",
|
|
GetLastError() );
|
|
}
|
|
|
|
/* Check the returned process information for validity */
|
|
if (pi.hProcess == 0 || pi.hThread == 0)
|
|
{
|
|
Fail("ERROR: CreateProcess Error: Process Handle = %u, Thread Handle = %u\n",
|
|
pi.hProcess, pi.hThread);
|
|
}
|
|
|
|
/* Write the Constructed string to stdin pipe for the child process */
|
|
if (WriteFile(hTestStdInW, szTestString, strlen(szTestString), &dwBytesWritten, NULL) == FALSE
|
|
|| WriteFile(hTestStdInW, "\n", strlen("\n"), &dwBytesWritten, NULL) == FALSE)
|
|
{
|
|
Fail("ERROR: %ld :unable to write to write pipe handle "
|
|
"hTestStdInW=0x%lx\n", GetLastError(), hTestStdInW);
|
|
}
|
|
|
|
/* Wait for the child to finish, Max 20 seconds */
|
|
dwExitCode = WaitForSingleObject(pi.hProcess, 20000);
|
|
|
|
/* If the child failed then whole thing fails */
|
|
if (dwExitCode != WAIT_OBJECT_0)
|
|
{
|
|
TerminateProcess(pi.hProcess, 0);
|
|
Fail("ERROR: The child failed to run properly.\n");
|
|
}
|
|
|
|
/* Check for problems in the child process */
|
|
if (GetExitCodeProcess(pi.hProcess, &dwExitCode) == FALSE)
|
|
{
|
|
Fail("ERROR: Call to GetExitCodeProcess failed.\n");
|
|
}
|
|
else if (dwExitCode == EXIT_ERR_CODE1)
|
|
{
|
|
Fail("ERROR: The Child process could not reead the string "
|
|
"written to the stdin pipe.\n");
|
|
}
|
|
else if (dwExitCode == EXIT_ERR_CODE2)
|
|
{
|
|
Fail("ERROR: The Child process could not write the string "
|
|
"the stdout pipe or stderr pipe.\n");
|
|
}
|
|
else if (dwExitCode == EXIT_ERR_CODE3)
|
|
{
|
|
Fail("ERROR: The Child received the wrong number of "
|
|
"command line arguments.\n");
|
|
}
|
|
else if (dwExitCode == EXIT_ERR_CODE4)
|
|
{
|
|
Fail("ERROR: The Child received the wrong "
|
|
"command line arguments.\n");
|
|
}
|
|
else if (dwExitCode != EXIT_OK_CODE)
|
|
{
|
|
Fail("ERROR: Unexpected exit code returned: %u. Child process "
|
|
"did not complete its part of the test.\n", dwExitCode);
|
|
}
|
|
|
|
|
|
/* The child ran ok, so check to see if we received the proper */
|
|
/* strings through the pipes. */
|
|
|
|
/* clear our buffers */
|
|
memset(szStdOutBuf, 0, BUF_LEN);
|
|
memset(szStdErrBuf, 0, BUF_LEN);
|
|
|
|
/* Read the data back from the child process stdout */
|
|
bRetVal = ReadFile(hTestStdOutR, /* handle to read pipe*/
|
|
szStdOutBuf, /* buffer to write to*/
|
|
BUF_LEN, /* number of bytes to read*/
|
|
&dwBytesRead, /* number of bytes read*/
|
|
NULL); /* overlapped buffer*/
|
|
|
|
/*Read the data back from the child process stderr */
|
|
bRetVal = ReadFile(hTestStdErrR, /* handle to read pipe*/
|
|
szStdErrBuf, /* buffer to write to*/
|
|
BUF_LEN, /* number of bytes to read*/
|
|
&dwBytesRead, /* number of bytes read*/
|
|
NULL); /* overlapped buffer*/
|
|
|
|
|
|
/* Confirm that we recieved the same string that we originally */
|
|
/* wrote to the child and was received on both stdout & stderr.*/
|
|
if (strncmp(szTestString, szStdOutBuf, strlen(szTestString)) != 0
|
|
|| strncmp(szTestString, szStdErrBuf, strlen(szTestString)) != 0)
|
|
{
|
|
Fail("ERROR: The data read back from child does not match "
|
|
"what was written. STDOUT: %s STDERR: %s\n",
|
|
szStdOutBuf, szStdErrBuf);
|
|
}
|
|
|
|
|
|
/*******************************************
|
|
* Clean Up
|
|
*******************************************/
|
|
|
|
/* Close process and thread handle */
|
|
CloseHandle ( pi.hProcess );
|
|
CloseHandle ( pi.hThread );
|
|
|
|
CloseHandle(hTestStdInR);
|
|
CloseHandle(hTestStdInW);
|
|
CloseHandle(hTestStdOutR);
|
|
CloseHandle(hTestStdOutW);
|
|
CloseHandle(hTestStdErrR);
|
|
CloseHandle(hTestStdErrW);
|
|
|
|
PAL_Terminate();
|
|
return ( PASS );
|
|
}
|