/*
 * Setup and run the server. This is called from Init via the loader.
 */
DWORD server_setup( SOCKET fd )
{
	Remote * remote        = NULL;
	char cStationName[256] = {0};
	char cDesktopName[256] = {0};
	DWORD res              = 0;

	dprintf("[SERVER] Initializing...");

#ifdef _UNIX
	int local_error = 0;
#endif

	// if hAppInstance is still == NULL it means that we havent been
	// reflectivly loaded so we must patch in the hAppInstance value
	// for use with loading server extensions later.
	InitAppInstance();

	srand( (unsigned int)time(NULL) );
	
	__try 
	{
		do
		{
			dprintf( "[SERVER] module loaded at 0x%08X", hAppInstance );
			
			// Open a THREAD item for the servers main thread, we use this to manage migration later.
			serverThread = thread_open();

			dprintf( "[SERVER] main server thread: handle=0x%08X id=0x%08X sigterm=0x%08X", serverThread->handle, serverThread->id, serverThread->sigterm );

			if( !(remote = remote_allocate(fd)) )
			{
				SetLastError( ERROR_NOT_ENOUGH_MEMORY );
				break;
			}

			// Do not allow the file descriptor to be inherited by child processes
			SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);

			dprintf("[SERVER] Initializing tokens...");

			// Store our thread handle
			remote->hServerThread = serverThread->handle;

#ifdef _WIN32
			// Store our process token
			if (!OpenThreadToken(remote->hServerThread, TOKEN_ALL_ACCESS, TRUE, &remote->hServerToken))
				OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &remote->hServerToken);

			// Copy it to the thread token
			remote->hThreadToken = remote->hServerToken;

			// Save the initial session/station/desktop names...
			remote->dwOrigSessionId      = server_sessionid();
			remote->dwCurrentSessionId   = remote->dwOrigSessionId;
			GetUserObjectInformation( GetProcessWindowStation(), UOI_NAME, &cStationName, 256, NULL );
			remote->cpOrigStationName    = _strdup( cStationName );
			remote->cpCurrentStationName = _strdup( cStationName );
			GetUserObjectInformation( GetThreadDesktop( GetCurrentThreadId() ), UOI_NAME, &cDesktopName, 256, NULL );
			remote->cpOrigDesktopName    = _strdup( cDesktopName );
			remote->cpCurrentDesktopName = _strdup( cDesktopName );
#endif

			dprintf("[SERVER] Flushing the socket handle...");
			server_socket_flush( remote );
		
			dprintf("[SERVER] Initializing SSL...");
			if( !server_initialize_ssl( remote ) )
				break;

			dprintf("[SERVER] Negotiating SSL...");
			if( !server_negotiate_ssl( remote ) )
				break;

			dprintf("[SERVER] Registering dispatch routines...");
			register_dispatch_routines();

			dprintf("[SERVER] Entering the main server dispatch loop...");
			server_dispatch( remote );
		
			dprintf("[SERVER] Deregistering dispatch routines...");
			deregister_dispatch_routines();

		} while (0);

		dprintf("[SERVER] Closing down SSL...");

		server_destroy_ssl( remote );

		if( remote )
			remote_deallocate( remote );

	} 
	__except( exceptionfilter(GetExceptionCode(), GetExceptionInformation()) )
	{
		dprintf("[SERVER] *** exception triggered!");

		thread_kill( serverThread );
	}

	dprintf("[SERVER] Finished.");
	return res;
}
Example #2
0
//  Returns -1 if we could not make the socket pair successfully
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
{
#if defined ZMQ_HAVE_EVENTFD
    fd_t fd = eventfd (0, 0);
    if (fd == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    }
    else {
        *w_ = *r_ = fd;
        return 0;
    }

#elif defined ZMQ_HAVE_WINDOWS
#   if !defined _WIN32_WCE
    // Windows CE does not manage security attributes
    SECURITY_DESCRIPTOR sd;
    SECURITY_ATTRIBUTES sa;
    memset (&sd, 0, sizeof (sd));
    memset (&sa, 0, sizeof (sa));

    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = &sd;
#   endif

    //  This function has to be in a system-wide critical section so that
    //  two instances of the library don't accidentally create signaler
    //  crossing the process boundary.
    //  We'll use named event object to implement the critical section.
    //  Note that if the event object already exists, the CreateEvent requests
    //  EVENT_ALL_ACCESS access right. If this fails, we try to open
    //  the event object asking for SYNCHRONIZE access only.
    HANDLE sync = NULL;

    //  Create critical section only if using fixed signaler port
    //  Use problematic Event implementation for compatibility if using old port 5905.
    //  Otherwise use Mutex implementation.
    int event_signaler_port = 5905;

    if (signaler_port == event_signaler_port) {
#       if !defined _WIN32_WCE
        sync = CreateEvent (&sa, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#       else
        sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#       endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE,
                              FALSE, TEXT ("Global\\zmq-signaler-port-sync"));

        win_assert (sync != NULL);
    }
    else if (signaler_port != 0) {
        TCHAR mutex_name[64];
        _stprintf (mutex_name, TEXT ("Global\\zmq-signaler-port-%d"), signaler_port);

#       if !defined _WIN32_WCE
        sync = CreateMutex (&sa, FALSE, mutex_name);
#       else
        sync = CreateMutex (NULL, FALSE, mutex_name);
#       endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenMutex (SYNCHRONIZE, FALSE, mutex_name);

        win_assert (sync != NULL);
    }

    //  Windows has no 'socketpair' function. CreatePipe is no good as pipe
    //  handles cannot be polled on. Here we create the socketpair by hand.
    *w_ = INVALID_SOCKET;
    *r_ = INVALID_SOCKET;

    //  Create listening socket.
    SOCKET listener;
    listener = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (listener != INVALID_SOCKET);

    //  Set SO_REUSEADDR and TCP_NODELAY on listening socket.
    BOOL so_reuseaddr = 1;
    int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR,
        (char *)&so_reuseaddr, sizeof (so_reuseaddr));
    wsa_assert (rc != SOCKET_ERROR);
    BOOL tcp_nodelay = 1;
    rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY,
        (char *)&tcp_nodelay, sizeof (tcp_nodelay));
    wsa_assert (rc != SOCKET_ERROR);

    //  Init sockaddr to signaler port.
    struct sockaddr_in addr;
    memset (&addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    addr.sin_port = htons (signaler_port);

    //  Create the writer socket.
    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (*w_ != INVALID_SOCKET);

    //  Set TCP_NODELAY on writer socket.
    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY,
        (char *)&tcp_nodelay, sizeof (tcp_nodelay));
    wsa_assert (rc != SOCKET_ERROR);

    if (sync != NULL) {
        //  Enter the critical section.
        DWORD dwrc = WaitForSingleObject (sync, INFINITE);
        zmq_assert (dwrc == WAIT_OBJECT_0 || dwrc == WAIT_ABANDONED);
    }

    //  Bind listening socket to signaler port.
    rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));

    if (rc != SOCKET_ERROR && signaler_port == 0) {
        //  Retrieve ephemeral port number
        int addrlen = sizeof (addr);
        rc = getsockname (listener, (struct sockaddr*) &addr, &addrlen);
    }

    //  Listen for incoming connections.
    if (rc != SOCKET_ERROR)
        rc = listen (listener, 1);

    //  Connect writer to the listener.
    if (rc != SOCKET_ERROR)
        rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));

    //  Accept connection from writer.
    if (rc != SOCKET_ERROR)
        *r_ = accept (listener, NULL, NULL);

    //  Save errno if error occurred in bind/listen/connect/accept.
    int saved_errno = 0;
    if (*r_ == INVALID_SOCKET)
        saved_errno = WSAGetLastError ();

    //  We don't need the listening socket anymore. Close it.
    closesocket (listener);

    if (sync != NULL) {
        //  Exit the critical section.
        BOOL brc;
        if (signaler_port == event_signaler_port)
            brc = SetEvent (sync);
        else
            brc = ReleaseMutex (sync);
        win_assert (brc != 0);

        //  Release the kernel object
        brc = CloseHandle (sync);
        win_assert (brc != 0);
    }

    if (*r_ != INVALID_SOCKET) {
#   if !defined _WIN32_WCE
        //  On Windows, preventing sockets to be inherited by child processes.
        BOOL brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
        win_assert (brc);
#   endif
        return 0;
    }
    else {
        //  Cleanup writer if connection failed
        if (*w_ != INVALID_SOCKET) {
            rc = closesocket (*w_);
            wsa_assert (rc != SOCKET_ERROR);
            *w_ = INVALID_SOCKET;
        }
        //  Set errno from saved value
        errno = wsa_error_to_errno (saved_errno);
        return -1;
    }

#elif defined ZMQ_HAVE_OPENVMS

    //  Whilst OpenVMS supports socketpair - it maps to AF_INET only.  Further,
    //  it does not set the socket options TCP_NODELAY and TCP_NODELACK which
    //  can lead to performance problems.
    //
    //  The bug will be fixed in V5.6 ECO4 and beyond.  In the meantime, we'll
    //  create the socket pair manually.
    struct sockaddr_in lcladdr;
    memset (&lcladdr, 0, sizeof (lcladdr));
    lcladdr.sin_family = AF_INET;
    lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    lcladdr.sin_port = 0;

    int listener = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (listener != -1);

    int on = 1;
    int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
    errno_assert (rc != -1);

    socklen_t lcladdr_len = sizeof (lcladdr);

    rc = getsockname (listener, (struct sockaddr*) &lcladdr, &lcladdr_len);
    errno_assert (rc != -1);

    rc = listen (listener, 1);
    errno_assert (rc != -1);

    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (*w_ != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = connect (*w_, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
    errno_assert (rc != -1);

    *r_ = accept (listener, NULL, NULL);
    errno_assert (*r_ != -1);

    close (listener);

    return 0;

#else
    // All other implementations support socketpair()
    int sv [2];
    int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
    if (rc == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    }
    else {
        *w_ = sv [0];
        *r_ = sv [1];
        return 0;
    }
#endif
}
Example #3
0
/// Do 'execute' instruction.
///
/// \param sCommand_line    fully command line, after modify
///
/// Return AGENT_RET_SUCCESS if succeed, or AGENT_RET_FAIL if fail
static MBA_AGENT_RETURN execute_cmd(char *sCmdline) {
    // Child  : hOutputWrite, hInputRead, hErrorWrite
    // Parent : hOutputRead, hInputWrite
    HANDLE hOutputRead, hOutputWrite;
    HANDLE hInputRead, hInputWrite;
    HANDLE hErrorWrite;
    
    // Thread handler
    HANDLE hThread;
    DWORD dTid;
    
    DWORD dEndSize = 0;

    WSAPROTOCOL_INFO protoInfo;
    
    SECURITY_ATTRIBUTES pipeAttr;

    // Set up the security attributes struct.
    pipeAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    pipeAttr.lpSecurityDescriptor = NULL;
    pipeAttr.bInheritHandle = TRUE;

    // Create the child output pipe.
    if (!CreatePipe(&hOutputRead, &hOutputWrite, &pipeAttr, 0)) {
        display_error("execute_cmd - CreatePipe", TRUE);
        return AGENT_RET_FAIL;
    }

    // Create a duplicate of the output write handle for the std error write handle.
    // This is necessary in case the child application closes one of its std output handles.
    if ( !DuplicateHandle(
            GetCurrentProcess(), hOutputWrite,
            GetCurrentProcess(), &hErrorWrite,
            0, TRUE, DUPLICATE_SAME_ACCESS) ) {
                display_error("execute_cmd - DuplicateHandle : hErrorWrite -> hOutputWrite", TRUE);
                return AGENT_RET_FAIL;
            }
        

    // Create the child input pipe.
    if ( !CreatePipe( &hInputRead, &hInputWrite, &pipeAttr,0) ){
        display_error("execute_cmd - CreatePipe", TRUE);
        return AGENT_RET_FAIL;
    }

    // Ensure the handle for reading from child stdout pipe is not inherited
    if ( !SetHandleInformation( hOutputRead, HANDLE_FLAG_INHERIT, 0) ) {
        display_error("execute_cmd - SetHandleInformation : Child read", TRUE);
        return AGENT_RET_FAIL;
    }

    // Ensure the handle for writing to child stdin pipe is not inherited
    if ( !SetHandleInformation( hInputWrite, HANDLE_FLAG_INHERIT, 0) ) {
        display_error("execute_cmd - SetHandleInformation : Child write", TRUE);
        return AGENT_RET_FAIL;
    }
        
    // Sets up STARTUPINFO structure, and launches redirected child.
    prep_and_launch_redirected_child(sCmdline, hOutputWrite, hInputRead, hErrorWrite);

    // Close pipe handles (do not continue to modify in the parent).
    if (!CloseHandle(hOutputWrite)) {
        display_error("execute_cmd - CloseHandle : Child Write", TRUE);
        return AGENT_RET_FAIL;
    }
    if (!CloseHandle(hInputRead)) {
        display_error("execute_cmd - CloseHandle : Child Read", TRUE);
        return AGENT_RET_FAIL;
    }
    if (!CloseHandle(hErrorWrite)) {
        display_error("execute_cmd - CloseHandle : Child Error", TRUE);
        return AGENT_RET_FAIL;
    }

    // Duplicate ClientSocket for thread
    WSADuplicateSocket( g_sClientSocket, GetCurrentProcessId(), &protoInfo );
    g_sClientDupSocket = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, &protoInfo, 0, 0 );
    if( g_sClientDupSocket == INVALID_SOCKET ) {
        display_error("execute_cmd - WSASocket : Dup ClientSocket", TRUE );
        return AGENT_RET_FAIL;
    }

    // Launch the thread that gets the input and sends it to the child.
    hThread = CreateThread(
        NULL,                       // a pointer to a SECURITY_ATTRIBUTES structure
        0,                          // the initial size of the stack, in bytes
        get_and_send_input_thread,  // a pointer to the application-defined function to be executed by the thread
        (LPVOID)hInputWrite,        // a pointer to a variable to be passed to the thread.
        0,                          // the flags that control the creation of the thread
        &dTid);                      // a pointer to a variable that receives the thread identifier.
                                    //      If this parameter is NULL, the thread identifier is not returned.
    if (hThread == NULL) {
        display_error("execute_cmd - CreateThread : Write", TRUE);
        return AGENT_RET_FAIL;
    }

    // Read the child's output
    read_and_handle_output( hOutputRead );
    // Redirection is complete 

    // Tell the thread to exit and wait for thread to die.
    closesocket( g_sClientDupSocket );
    
    // send out the zero-sized message to terminate agent 'exec' action
    send(g_sClientSocket, (const char*)&dEndSize, sizeof(dEndSize), 0);

    // Wait Thread which keep receiving & forwarding commands
    if (WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED) {
        display_error("WaitForSingleObject", TRUE);
        return AGENT_RET_FAIL;
    }

    // Close input and output handle
    if (!CloseHandle(hOutputRead)) {
        display_error("execute_cmd - CloseHandle : hOutputRead", TRUE);
        return AGENT_RET_FAIL;
    }
    if (!CloseHandle(hInputWrite)) {
        display_error("execute_cmd - CloseHandle : hInputWrite", TRUE);
        return AGENT_RET_FAIL;
    }
    return AGENT_RET_SUCCESS;
}
void Process::run() {
	SECURITY_ATTRIBUTES saAttr; 

	// Set the bInheritHandle flag so pipe handles are inherited. 
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
	saAttr.bInheritHandle = TRUE; 
	saAttr.lpSecurityDescriptor = NULL; 

	// Create a pipe for the child process's STDOUT. 
	if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) 
		ErrorExit(TEXT("StdoutRd CreatePipe")); 

	// Ensure the read handle to the pipe for STDOUT is not inherited.
	if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
		ErrorExit(TEXT("Stdout SetHandleInformation")); 

	// Create a pipe for the child process's STDIN. 
	if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
		ErrorExit(TEXT("Stdin CreatePipe")); 

	// Ensure the write handle to the pipe for STDIN is not inherited. 
	if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
		ErrorExit(TEXT("Stdin SetHandleInformation")); 

	
	std::string mycmd = "cmd.exe /D /c " + cmd;


	//Create child process


	PROCESS_INFORMATION piProcInfo; 
	STARTUPINFO siStartInfo;
	BOOL bSuccess = FALSE; 

	// Set up members of the PROCESS_INFORMATION structure. 

	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

	// Set up members of the STARTUPINFO structure. 
	// This structure specifies the STDIN and STDOUT handles for redirection.

	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 
	siStartInfo.hStdError = g_hChildStd_OUT_Wr;
	siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
	siStartInfo.hStdInput = g_hChildStd_IN_Rd;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

	// Create the child process. 

	bSuccess = CreateProcess(
		NULL, 
		(LPSTR)cmd.c_str(),     // command line 
		NULL,          // process security attributes 
		NULL,          // primary thread security attributes 
		TRUE,          // handles are inherited 
		0,             // creation flags 
		NULL,          // use parent's environment 
		NULL,          // use parent's current directory 
		&siStartInfo,  // STARTUPINFO pointer 
		&piProcInfo);  // receives PROCESS_INFORMATION 

	// If an error occurs, exit the application. 
	if ( ! bSuccess ) 
		ErrorExit(TEXT("CreateProcess"));
	else 
	{
		running = true;

		/********************************************************************************
		* IF YOU PLAN TO ATTACH TO YOUR'S BOTS PROCESS, UNCOMMENT OUT THIS CODE TO HELP.
		* IT WILL PAUSE UNTIL YOU TYPE A KEY AND HIT ENTER								*
		********************************************************************************/

	    //if( cmd == "C:\\planetwars\\cpp_framework\\albertz-planet_wars-cpp-2fc1dda\\VC\\Debug\\alcsbot.exe" )
		//{
		//	std::cout << "Attach to mybot.exe process, type some char and hit enter when ready";
		//	char n;
		//	std::cin >> n;
		//}


		//CloseHandle(piProcInfo.hProcess);
		hProcess = piProcInfo.hProcess;
		CloseHandle(piProcInfo.hThread);
	}


}
Example #5
0
void MythSystemWindows::Fork(time_t timeout)
{
    QString LOC_ERR = QString("myth_system('%1'): Error: ").arg(GetLogCmd());

    // For use in the child
    char locerr[MAX_BUFLEN];
    strncpy(locerr, (const char *)LOC_ERR.toUtf8().constData(), MAX_BUFLEN);
    locerr[MAX_BUFLEN-1] = '\0';

    LOG(VB_SYSTEM, LOG_DEBUG, QString("Launching: %1").arg(GetLogCmd()));

    GetBuffer(0)->setBuffer(0);
    GetBuffer(1)->setBuffer(0);
    GetBuffer(2)->setBuffer(0);

    HANDLE p_stdin[2] = { NULL, NULL };
    HANDLE p_stdout[2] = { NULL, NULL };
    HANDLE p_stderr[2] = { NULL, NULL };

    SECURITY_ATTRIBUTES saAttr; 
    STARTUPINFO si;

    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
        
    // Set the bInheritHandle flag so pipe handles are inherited. 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    /* set up pipes */
    if( GetSetting("UseStdin") )
    {
        if (!CreatePipe(&p_stdin[0], &p_stdin[1], &saAttr, 0)) 
        {
            LOG(VB_GENERAL, LOG_ERR, "stdin pipe() failed");
            SetStatus( GENERIC_EXIT_NOT_OK );
        }
        else
        {
            // Ensure the write handle to the pipe for STDIN is not inherited. 
            if (!SetHandleInformation(p_stdin[1], HANDLE_FLAG_INHERIT, 0))
            {
                LOG(VB_SYSTEM, LOG_ERR, "stdin inheritance error");
                SetStatus( GENERIC_EXIT_NOT_OK );
            }
            else
            {
                si.hStdInput = p_stdin[0];
                si.dwFlags |= STARTF_USESTDHANDLES;
            }
        }
    }

    if( GetSetting("UseStdout") )
    {
        if (!CreatePipe(&p_stdout[0], &p_stdout[1], &saAttr, 0)) 
        {
            LOG(VB_SYSTEM, LOG_ERR, "stdout pipe() failed");
            SetStatus( GENERIC_EXIT_NOT_OK );
        }
        else
        {
            // Ensure the read handle to the pipe for STDOUT is not inherited.
            if (!SetHandleInformation(p_stdout[0], HANDLE_FLAG_INHERIT, 0))
            {
                LOG(VB_SYSTEM, LOG_ERR, "stdout inheritance error");
                SetStatus( GENERIC_EXIT_NOT_OK );
            }
            else
            {
                si.hStdOutput = p_stdout[1];
                si.dwFlags |= STARTF_USESTDHANDLES;
            }
        }
    }

    if( GetSetting("UseStderr") )
    {
        if (!CreatePipe(&p_stderr[0], &p_stderr[1], &saAttr, 0)) 
        {
            LOG(VB_SYSTEM, LOG_ERR, "stderr pipe() failed");
            SetStatus( GENERIC_EXIT_NOT_OK );
        }
        else
        {
            // Ensure the read handle to the pipe for STDERR is not inherited.
            if (!SetHandleInformation(p_stderr[0], HANDLE_FLAG_INHERIT, 0))
            {
                LOG(VB_SYSTEM, LOG_ERR, "stderr inheritance error");
                SetStatus( GENERIC_EXIT_NOT_OK );
            }
            else
            {
                si.hStdError = p_stderr[1];
                si.dwFlags |= STARTF_USESTDHANDLES;
            }
        }
    }

    // set up command args
    QString cmd = GetCommand() + " " + GetArgs().join(" ");
    if (GetSetting("UseShell"))
        cmd.prepend("cmd.exe /c ");

    SetCommand( cmd );

    QByteArray cmdUTF8 = GetCommand().toUtf8();
    TCHAR *command = TEXT((char *)cmdUTF8.constData());

    const char *directory = NULL;
    QString dir = GetDirectory();
    if (GetSetting("SetDirectory") && !dir.isEmpty())
        directory = strdup(dir.toUtf8().constData());

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    m_timeout = timeout;
    if( timeout )
        m_timeout += time(NULL);

    bool success = CreateProcess(NULL, 
                    command,       // command line 
                    NULL,          // process security attributes 
                    NULL,          // primary thread security attributes 
                    TRUE,          // handles are inherited 
                    0,             // creation flags 
                    NULL,          // use parent's environment 
                    directory,     // use parent's current directory 
                   &si,            // STARTUPINFO pointer 
                   &pi);           // receives PROCESS_INFORMATION 

    if (!success)
    {
        LOG(VB_SYSTEM, LOG_ERR, "CreateProcess() failed");
        SetStatus( GENERIC_EXIT_NOT_OK );
    }
    else
    {
        /* parent */
        m_child = pi.hProcess;
        SetStatus( GENERIC_EXIT_RUNNING );

        LOG(VB_SYSTEM, LOG_INFO,
                QString("Managed child (Handle: %1) has started! "
                        "%2%3 command=%4, timeout=%5")
                    .arg((long long)m_child) 
                    .arg(GetSetting("UseShell") ? "*" : "")
                    .arg(GetSetting("RunInBackground") ? "&" : "")
                    .arg(GetLogCmd()) .arg(timeout));

        /* close unused pipe ends */
        CLOSE(p_stdin[0]);
        CLOSE(p_stdout[1]);
        CLOSE(p_stderr[1]);

        // store the rest
        m_stdpipe[0] = p_stdin[1];
        m_stdpipe[1] = p_stdout[0];
        m_stdpipe[2] = p_stderr[0];

        // clean up the memory use
        if( directory )
            free((void *)directory);
    }

    /* Parent */
    if( GetStatus() != GENERIC_EXIT_RUNNING )
    {
        CLOSE(p_stdin[0]);
        CLOSE(p_stdin[1]);
        CLOSE(p_stdout[0]);
        CLOSE(p_stdout[1]);
        CLOSE(p_stderr[0]);
        CLOSE(p_stderr[1]);
    }
}
Example #6
0
File: tcp.c Project: 337240552/node
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
    SOCKET socket, int imported) {
  DWORD yes = 1;
  int non_ifs_lsp;

  assert(handle->socket == INVALID_SOCKET);

  /* Set the socket to nonblocking mode */
  if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) {
    uv__set_sys_error(loop, WSAGetLastError());
    return -1;
  }

  /* Make the socket non-inheritable */
  if (!SetHandleInformation((HANDLE)socket, HANDLE_FLAG_INHERIT, 0)) {
    uv__set_sys_error(loop, GetLastError());
    return -1;
  }

  /* Associate it with the I/O completion port. */
  /* Use uv_handle_t pointer as completion key. */
  if (CreateIoCompletionPort((HANDLE)socket,
                             loop->iocp,
                             (ULONG_PTR)socket,
                             0) == NULL) {
    if (imported) {
      handle->flags |= UV_HANDLE_EMULATE_IOCP;
    } else {
      uv__set_sys_error(loop, GetLastError());
      return -1;
    }
  }

  non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 :
    uv_tcp_non_ifs_lsp_ipv4;

  if (pSetFileCompletionNotificationModes && !non_ifs_lsp) {
    if (pSetFileCompletionNotificationModes((HANDLE) socket,
        FILE_SKIP_SET_EVENT_ON_HANDLE |
        FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) {
      handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP;
    } else if (GetLastError() != ERROR_INVALID_FUNCTION) {
      uv__set_sys_error(loop, GetLastError());
      return -1;
    }
  }

  if ((handle->flags & UV_HANDLE_TCP_NODELAY) &&
      uv__tcp_nodelay(handle, socket, 1)) {
    return -1;
  }

  /* TODO: Use stored delay. */
  if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) &&
      uv__tcp_keepalive(handle, socket, 1, 60)) {
    return -1;
  }

  handle->socket = socket;

  return 0;
}
Example #7
0
/* Run a command and redirect its input and output handles to a pair of
   anonymous pipes.  The process handle and pipe handles are returned in the
   info struct. Returns the PID of the new process, or -1 on error. */
static int run_command_redirected(char *cmdexec, struct subprocess_info *info)
{
    /* Each named pipe we create has to have a unique name. */
    static int pipe_serial_no = 0;
    char pipe_name[32];
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    /* Make the pipe handles inheritable. */
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    /* The child's input pipe is an ordinary blocking pipe. */
    if (CreatePipe(&info->child_in_r, &info->child_in_w, &sa, 0) == 0) {
        if (o.verbose)
            logdebug("Error in CreatePipe: %d\n", GetLastError());
        return -1;
    }

    /* Pipe names must have this special form. */
    Snprintf(pipe_name, sizeof(pipe_name), "\\\\.\\pipe\\ncat-%d-%d",
        GetCurrentProcessId(), pipe_serial_no);
    if (o.debug > 1)
        logdebug("Creating named pipe \"%s\"\n", pipe_name);

    /* The output pipe has to be nonblocking, which requires this complicated
       setup. */
    info->child_out_r = CreateNamedPipe(pipe_name,
        PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
        PIPE_TYPE_BYTE, 1, 4096, 4096, 1000, &sa);
    if (info->child_out_r == 0) {
        if (o.verbose)
            logdebug("Error in CreateNamedPipe: %d\n", GetLastError());
        CloseHandle(info->child_in_r);
        CloseHandle(info->child_in_w);
        return -1;
    }
    info->child_out_w = CreateFile(pipe_name,
        GENERIC_WRITE, 0, &sa, OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
    if (info->child_out_w == 0) {
        CloseHandle(info->child_in_r);
        CloseHandle(info->child_in_w);
        CloseHandle(info->child_out_r);
        return -1;
    }
    pipe_serial_no++;

    /* Don't inherit our end of the pipes. */
    SetHandleInformation(info->child_in_w, HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(info->child_out_r, HANDLE_FLAG_INHERIT, 0);

    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.hStdInput = info->child_in_r;
    si.hStdOutput = info->child_out_w;
    si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
    si.dwFlags |= STARTF_USESTDHANDLES;

    memset(&pi, 0, sizeof(pi));

    if (CreateProcess(NULL, cmdexec, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0) {
        if (o.verbose)
            logdebug("Error in CreateProcess: %d\n", GetLastError());
        CloseHandle(info->child_in_r);
        CloseHandle(info->child_in_w);
        CloseHandle(info->child_out_r);
        CloseHandle(info->child_out_w);
        return -1;
    }

    /* Close hThread here because we have no use for it. hProcess is closed in
       subprocess_info_close. */
    CloseHandle(pi.hThread);

    info->proc = pi.hProcess;

    return pi.dwProcessId;
}
Example #8
0
CResourceCompilerHelper::ERcCallResult CResourceCompilerHelper::CallResourceCompiler(
	const char* szFileName, 
	const char* szAdditionalSettings, 
	IResourceCompilerListener* listener, 
	bool bMayShowWindow, 
	CResourceCompilerHelper::ERcExePath rcExePath, 
	bool bSilent,
	bool bNoUserDialog,
	const wchar_t* szWorkingDirectory,
	const wchar_t* szRootPath)
{
	// make command for execution
	SettingsManagerHelpers::CFixedString<wchar_t, MAX_PATH*3> wRemoteCmdLine;

	if (!szAdditionalSettings)
	{
		szAdditionalSettings = "";
	}

	wchar_t szRemoteDirectory[512];
	{
		wchar_t pathBuffer[512];
		switch (rcExePath)
		{
		case eRcExePath_registry:
			GetRootPathUtf16(true, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_settingsManager:
			GetRootPathUtf16(false, SettingsManagerHelpers::CWCharBuffer(pathBuffer, sizeof(pathBuffer)));
			break;
		case eRcExePath_currentFolder:
			wcscpy(pathBuffer, L".");
			break;
		case eRcExePath_customPath:
			wcscpy(pathBuffer, szRootPath);
			break;
		default:
			return eRcCallResult_notFound;
		}

		if (!pathBuffer[0])
		{
			wcscpy(pathBuffer, L".");
		}

		swprintf_s(szRemoteDirectory, L"%s/Bin32/rc", pathBuffer);
	}

	if (!szFileName)
	{
		wRemoteCmdLine.appendAscii("\"");
		wRemoteCmdLine.append(szRemoteDirectory);
		wRemoteCmdLine.appendAscii("/rc.exe\" /userdialog=0 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
	}
	else
	{
		wRemoteCmdLine.appendAscii("\"");
		wRemoteCmdLine.append(szRemoteDirectory);
		wRemoteCmdLine.appendAscii("/rc.exe\" \"");
		wRemoteCmdLine.appendAscii(szFileName);
		wRemoteCmdLine.appendAscii("\" ");
		wRemoteCmdLine.appendAscii(bNoUserDialog ? "/userdialog=0 " : "/userdialog=1 ");
		wRemoteCmdLine.appendAscii(szAdditionalSettings);
	}

	// Create a pipe to read the stdout of the RC.
	SECURITY_ATTRIBUTES saAttr;
	::memset(&saAttr, 0, sizeof(saAttr));
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = 0;
	HANDLE hChildStdOutRd, hChildStdOutWr;
	CreatePipe(&hChildStdOutRd, &hChildStdOutWr, &saAttr, 0);
	SetHandleInformation(hChildStdOutRd, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN
	HANDLE hChildStdInRd, hChildStdInWr;
	CreatePipe(&hChildStdInRd, &hChildStdInWr, &saAttr, 0);
	SetHandleInformation(hChildStdInWr, HANDLE_FLAG_INHERIT, 0); // Need to do this according to MSDN

	STARTUPINFOW si;
	ZeroMemory(&si, sizeof(si));
	si.cb = sizeof(si);
	si.dwX = 100;
	si.dwY = 100;
	si.hStdError = hChildStdOutWr;
	si.hStdOutput = hChildStdOutWr;
	si.hStdInput = hChildStdInRd;
	si.dwFlags = STARTF_USEPOSITION | STARTF_USESTDHANDLES;

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));

	bool bShowWindow = false;
	{
		wchar_t buffer[20];
		g_pSettingsManager->GetValueByRef("ShowWindow", SettingsManagerHelpers::CWCharBuffer(buffer, sizeof(buffer)));
		bShowWindow = (wcscmp(buffer, L"true") == 0);
	}

	if (!CreateProcessW(
		NULL,                   // No module name (use command line).
		const_cast<wchar_t*>(wRemoteCmdLine.c_str()), // Command line.
		NULL,                   // Process handle not inheritable.
		NULL,                   // Thread handle not inheritable.
		TRUE,                   // Set handle inheritance to TRUE.
		(bMayShowWindow && bShowWindow) ? 0  : CREATE_NO_WINDOW, // creation flags.
		NULL,                   // Use parent's environment block.
		szWorkingDirectory?szWorkingDirectory:szRemoteDirectory,  // Set starting directory.
		&si,                    // Pointer to STARTUPINFO structure.
		&pi ))                  // Pointer to PROCESS_INFORMATION structure.
	{
		/*
		This code block is commented out instead of being deleted because it's
		good to have at hand for a debugging session.

		const size_t charsInMessageBuffer = 32768;   // msdn about FormatMessage(): "The output buffer cannot be larger than 64K bytes."
		wchar_t szMessageBuffer[charsInMessageBuffer] = L"";   
		FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, szMessageBuffer, charsInMessageBuffer, NULL);
		GetCurrentDirectoryW(charsInMessageBuffer, szMessageBuffer);
		*/

		if (!bSilent)
		{
			MessageBoxA(0, "ResourceCompiler was not found.\n\nPlease verify CryENGINE RootPath.", "Error", MB_ICONERROR|MB_OK);
		}

		return eRcCallResult_notFound;
	}

	// Close the pipe that writes to the child process, since we don't actually have any input for it.
	CloseHandle(hChildStdInWr);

	// Read all the output from the child process.
	CloseHandle(hChildStdOutWr);
	ResourceCompilerLineHandler lineHandler(listener);
	LineStreamBuffer lineBuffer(&lineHandler, &ResourceCompilerLineHandler::HandleLine);
	for (;;)
	{
		char buffer[2048];
		DWORD bytesRead;
		if (!ReadFile(hChildStdOutRd, buffer, sizeof(buffer), &bytesRead, NULL) || (bytesRead == 0))
		{
			break;
		}
		lineBuffer.HandleText(buffer, bytesRead);
	} 

	// Wait until child process exits.
	WaitForSingleObject(pi.hProcess, INFINITE);

	bool ok = true;
	DWORD exitCode = 1;
	{
		if ((GetExitCodeProcess(pi.hProcess, &exitCode) == 0) || (exitCode != 0))
		{
			ok = false;
		}	
	}

	// Close process and thread handles. 
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	if (exitCode == eRcExitCode_Crash)
	{
		return eRcCallResult_crash;
	}

	if (lineBuffer.IsTruncated())
	{
		return eRcCallResult_error;
	}

	return ok ? eRcCallResult_success : eRcCallResult_error;
}
int launch_server()
{
#ifdef HAVE_WIN32_PROC
    /* we need to start the server in the background                    */
    /* we create a PIPE that will be used to wait for the server's "OK" */
    /* message since the pipe handles must be inheritable, we use a     */
    /* security attribute                                               */
    HANDLE                pipe_read, pipe_write;
    SECURITY_ATTRIBUTES   sa;
    STARTUPINFO           startup;
    PROCESS_INFORMATION   pinfo;
    char                  program_path[ MAX_PATH ];
    int                   ret;

    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = TRUE;

    /* create pipe, and ensure its read handle isn't inheritable */
    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
    if (!ret) {
        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
        return -1;
    }

    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );

    ZeroMemory( &startup, sizeof(startup) );
    startup.cb = sizeof(startup);
    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
    startup.hStdOutput = pipe_write;
    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
    startup.dwFlags    = STARTF_USESTDHANDLES;

    ZeroMemory( &pinfo, sizeof(pinfo) );

    /* get path of current program */
    GetModuleFileName( NULL, program_path, sizeof(program_path) );

    ret = CreateProcess(
              program_path,                              /* program path  */
              "adb fork-server server",
              /* the fork-server argument will set the
                 debug = 2 in the child           */
              NULL,                   /* process handle is not inheritable */
              NULL,                    /* thread handle is not inheritable */
              TRUE,                          /* yes, inherit some handles */
              DETACHED_PROCESS, /* the new process doesn't have a console */
              NULL,                     /* use parent's environment block */
              NULL,                    /* use parent's starting directory */
              &startup,                 /* startup info, i.e. std handles */
              &pinfo );

    CloseHandle( pipe_write );

    if (!ret) {
        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
        CloseHandle( pipe_read );
        return -1;
    }

    CloseHandle( pinfo.hProcess );
    CloseHandle( pinfo.hThread );

    /* wait for the "OK\n" message */
    {
        char  temp[3];
        DWORD  count;

        ret = ReadFile( pipe_read, temp, 3, &count, NULL );
        CloseHandle( pipe_read );
        if ( !ret ) {
            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
            return -1;
        }
        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
            fprintf(stderr, "ADB server didn't ACK\n" );
            return -1;
        }
    }
#elif defined(HAVE_FORKEXEC)
    char    path[PATH_MAX];
    int     fd[2];

    // set up a pipe so the child can tell us when it is ready.
    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
    if (pipe(fd)) {
        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
        return -1;
    }
    get_my_path(path);
    pid_t pid = fork();
    if(pid < 0) return -1;

    if (pid == 0) {
        // child side of the fork

        // redirect stderr to the pipe
        // we use stderr instead of stdout due to stdout's buffering behavior.
        adb_close(fd[0]);
        dup2(fd[1], STDERR_FILENO);
        adb_close(fd[1]);

        // child process
        int result = execl(path, "adb", "fork-server", "server", NULL);
        // this should not return
        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
    } else  {
        // parent side of the fork

        char  temp[3];

        temp[0] = 'A';
        temp[1] = 'B';
        temp[2] = 'C';
        // wait for the "OK\n" message
        adb_close(fd[1]);
        int ret = adb_read(fd[0], temp, 3);
        adb_close(fd[0]);
        if (ret < 0) {
            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", errno);
            return -1;
        }
        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
            fprintf(stderr, "ADB server didn't ACK\n" );
            return -1;
        }

        setsid();
    }
#else
#error "cannot implement background server start on this platform"
#endif
    return 0;
}
Example #10
0
File: tcp.c Project: 2hanson/node
static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) {
  uv_loop_t* loop = handle->loop;
  BOOL success;
  DWORD bytes;
  SOCKET accept_socket;
  short family;

  assert(handle->flags & UV_HANDLE_LISTENING);
  assert(req->accept_socket == INVALID_SOCKET);

  /* choose family and extension function */
  if (handle->flags & UV_HANDLE_IPV6) {
    family = AF_INET6;
  } else {
    family = AF_INET;
  }

  /* Open a socket for the accepted connection. */
  accept_socket = socket(family, SOCK_STREAM, 0);
  if (accept_socket == INVALID_SOCKET) {
    SET_REQ_ERROR(req, WSAGetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    return;
  }

  /* Make the socket non-inheritable */
  if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) {
    SET_REQ_ERROR(req, GetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    closesocket(accept_socket);
    return;
  }

  /* Prepare the overlapped structure. */
  memset(&(req->overlapped), 0, sizeof(req->overlapped));
  if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
    req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1);
  }

  success = handle->func_acceptex(handle->socket,
                                  accept_socket,
                                  (void*)req->accept_buffer,
                                  0,
                                  sizeof(struct sockaddr_storage),
                                  sizeof(struct sockaddr_storage),
                                  &bytes,
                                  &req->overlapped);

  if (UV_SUCCEEDED_WITHOUT_IOCP(success)) {
    /* Process the req without IOCP. */
    req->accept_socket = accept_socket;
    handle->reqs_pending++;
    uv_insert_pending_req(loop, (uv_req_t*)req);
  } else if (UV_SUCCEEDED_WITH_IOCP(success)) {
    /* The req will be processed with IOCP. */
    req->accept_socket = accept_socket;
    handle->reqs_pending++;
    if (handle->flags & UV_HANDLE_EMULATE_IOCP &&
        req->wait_handle == INVALID_HANDLE_VALUE &&
        !RegisterWaitForSingleObject(&req->wait_handle,
          req->event_handle, post_completion, (void*) req,
          INFINITE, WT_EXECUTEINWAITTHREAD)) {
      SET_REQ_ERROR(req, GetLastError());
      uv_insert_pending_req(loop, (uv_req_t*)req);
      handle->reqs_pending++;
      return;
    }
  } else {
    /* Make this req pending reporting an error. */
    SET_REQ_ERROR(req, WSAGetLastError());
    uv_insert_pending_req(loop, (uv_req_t*)req);
    handle->reqs_pending++;
    /* Destroy the preallocated client socket. */
    closesocket(accept_socket);
    /* Destroy the event handle */
    if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
      CloseHandle(req->overlapped.hEvent);
      req->event_handle = NULL;
    }
  }
}
Example #11
0
uint64 TZipIn::GetFLen(const TStr& ZipFNm) {
  #ifdef GLib_WIN
  HANDLE ZipStdoutRd, ZipStdoutWr;
  // create pipes
  SECURITY_ATTRIBUTES saAttr;
  saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  saAttr.bInheritHandle = TRUE;
  saAttr.lpSecurityDescriptor = NULL;
    // Create a pipe for the child process's STDOUT.
  const int PipeBufferSz = 32*1024;
  EAssertR(CreatePipe(&ZipStdoutRd, &ZipStdoutWr, &saAttr, PipeBufferSz), "Stdout pipe creation failed");
  // Ensure the read handle to the pipe for STDOUT is not inherited.
  SetHandleInformation(ZipStdoutRd, HANDLE_FLAG_INHERIT, 0);
  //CreateZipProcess(GetCmd(FNm), FNm);
  { const TStr CmdLine = TStr::Fmt("7z.exe l %s", ZipFNm.CStr());
  PROCESS_INFORMATION piProcInfo;
  STARTUPINFO siStartInfo;
  ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION));
  ZeroMemory( &siStartInfo, sizeof(STARTUPINFO));
  siStartInfo.cb = sizeof(STARTUPINFO);
  siStartInfo.hStdOutput = ZipStdoutWr;
  siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
  // Create the child process.
  const BOOL FuncRetn = CreateProcess(NULL, (LPSTR) CmdLine.CStr(),
    NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
  EAssertR(FuncRetn!=0, TStr::Fmt("Can not execute '%s'", CmdLine.CStr()).CStr());
  CloseHandle(piProcInfo.hProcess);
  CloseHandle(piProcInfo.hThread); }
  #else
  const TStr CmdLine = TStr::Fmt("7za l %s", ZipFNm.CStr());
  FILE* ZipStdoutRd = popen(CmdLine.CStr(), "r");
  if (ZipStdoutRd == NULL) { // try using SevenZipPath
    ZipStdoutRd = popen((TZipIn::SevenZipPath+"/"+CmdLine).CStr(), "r");
  }
  EAssertR(ZipStdoutRd != NULL, TStr::Fmt("Can not execute '%s'", CmdLine.CStr()).CStr());
  #endif
  // Read output from the child process
  const int BfSz = 32*1024;
  char* Bf = new char [BfSz];
  int BfC=0, BfL=0;
  memset(Bf, 0, BfSz);
  #ifdef GLib_WIN
  DWORD BytesRead;
  EAssert(ReadFile(ZipStdoutRd, Bf, MxBfL, &BytesRead, NULL) != 0);
  #else
  size_t BytesRead = fread(Bf, 1, MxBfL, ZipStdoutRd);
  EAssert(BytesRead != 0);
  EAssert(pclose(ZipStdoutRd) != -1);
  #endif
  BfL = (int) BytesRead;  IAssert((BfC!=0)||(BfL!=0));
  BfC = 0; Bf[BfL] = 0;
  // find file lenght
  TStr Str(Bf);  delete [] Bf;
  TStrV StrV; Str.SplitOnWs(StrV);
  int n = StrV.Len()-1;
  while (n > 0 && ! StrV[n].IsPrefix("-----")) { n--; }
  if (n-7 <= 0) {
    WrNotify(TStr::Fmt("Corrupt file %s: MESSAGE:\n", ZipFNm.CStr()).CStr(), Str.CStr());
    SaveToErrLog(TStr::Fmt("Corrupt file %s. Message:\n:%s\n", ZipFNm.CStr(), Str.CStr()).CStr());
    return 0;
  }
  return StrV[n-7].GetInt64();
}
Example #12
0
JNIEXPORT jint
JNICALL Java_us_temerity_pipeline_NativeProcessLight_execNativeLight
(
 JNIEnv *env, 
 jobject obj, 
 jobjectArray jcmdarray,   /* IN: command[0] and arguments[1+] */                 
 jobjectArray jenvp,       /* IN: environmental variable name=value pairs */  
 jstring jdir              /* IN: the working directory */  
)
{
  /* exception initialization */ 
  char msg[2048];
  jclass IOException = env->FindClass("java/io/IOException");
  if(IOException == 0) {
    errno = EINVAL;
    perror("NativeProcessLight.execNative(), unable to lookup \"java/lang/IOException\"");
    return -1;
  }

  /* get handles for the NativeProcessLight object's fields/methods */ 
  jclass NativeProcessLightClass = env->GetObjectClass(obj);  
  if(NativeProcessLightClass == 0) {
    env->ThrowNew(IOException, "unable to lookup class: NativeProcessLight");
    return -1;
  }
    
  jfieldID pStdInFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdInFileDesc", "I");
  if(pStdInFileDesc == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdInFileDesc");
    return -1;
  }
    
  jfieldID pStdOutFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdOutFileDesc", "I");
  if(pStdOutFileDesc == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdOutFileDesc");
    return -1;
  }

  jfieldID pStdErrFileDesc = env->GetFieldID(NativeProcessLightClass, "pStdErrFileDesc", "I");
  if(pStdErrFileDesc == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pStdErrFileDesc");
    return -1;
  }
 
  jfieldID pUTime = env->GetFieldID(NativeProcessLightClass, "pUTime", "J");
  if(pUTime == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pUTime");
    return -1;
  }

  jfieldID pSTime = env->GetFieldID(NativeProcessLightClass, "pSTime", "J");
  if(pSTime == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pSTime");
    return -1;
  }
  
  jfieldID pPageFaults = env->GetFieldID(NativeProcessLightClass, "pPageFaults", "J");
  if(pPageFaults == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pPageFaults");
    return -1;
  }
  
  jfieldID pVirtualSize = env->GetFieldID(NativeProcessLightClass, "pVirtualSize", "J");
  if(pVirtualSize == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pVirtualSize");
    return -1;
  }
  
  jfieldID pResidentSize = env->GetFieldID(NativeProcessLightClass, "pResidentSize", "J");
  if(pResidentSize == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pResidentSize");
    return -1;
  }
  
  jfieldID pSwappedSize = env->GetFieldID(NativeProcessLightClass, "pSwappedSize", "J");
  if(pSwappedSize == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.pSwappedSize");
    return -1;
  }
  
  jmethodID setPid = env->GetMethodID(NativeProcessLightClass, "setPid", "(I)V");
  if(setPid == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.setPid()");
    return -1;
  }
  
  jmethodID setIsRunning = env->GetMethodID(NativeProcessLightClass, "setIsRunning", "(Z)V");
  if(setIsRunning == 0) {
    env->ThrowNew(IOException, "unable to access: NativeProcessLight.setIsRunning()");
    return -1;
  }
  
  /* repackage the arguments */ 
  const char* dir = NULL; 
  char* cmdline = NULL; 
  TCHAR envbuf[32768]; 
  {
    {
      dir = env->GetStringUTFChars(jdir, 0);      
      if((dir == NULL) || (strlen(dir) == 0)) {
        env->ThrowNew(IOException,"empty working directory");
        return -1;
      } 

      printf("Dir = %s\n", dir);    // DEBUG

      struct stat buf;
      if(stat(dir, &buf) == -1) {
        sprintf(msg, "stat failed for \"%s\": %s", dir, strerror(errno));
        env->ReleaseStringUTFChars(jdir, dir);

        env->ThrowNew(IOException, msg);
        return -1;
      }
      else if(!(buf.st_mode & _S_IFDIR)) {
        sprintf(msg, "illegal working directory \"%s\"", dir);
        env->ReleaseStringUTFChars(jdir, dir);

        env->ThrowNew(IOException, msg);
        return -1;
      }
    }

    printf("Dir is OK\n");      // DEBUG

    {
      jsize len = env->GetArrayLength(jcmdarray);
      if(len == 0) {
        env->ReleaseStringUTFChars(jdir, dir);

        env->ThrowNew(IOException, "empty command arguments array");
        return -1;
      }

      jsize i;
      size_t csize = 0; 
      for(i=0; i<len; i++) {    
        jstring s = (jstring) env->GetObjectArrayElement(jcmdarray, i);
        const char* arg = env->GetStringUTFChars(s, NULL);
        csize += strlen(arg) + ((i == 0) ? 2 : 1);
        env->ReleaseStringUTFChars(s, arg);     
      }

      printf("Cmdline Size = %d\n", csize);     // DEBUG

      if(csize >= 32767) {
        env->ReleaseStringUTFChars(jdir, dir);

        env->ThrowNew(IOException, "command line exceeds 32K limit on Windows!");
        return -1; 
      }

      cmdline = new char[csize+1];
      cmdline[0] = '\0';
      for(i=0; i<len; i++) {
        jstring s = (jstring) env->GetObjectArrayElement(jcmdarray, i);
        const char* arg = env->GetStringUTFChars(s, NULL);      

        strcat(cmdline, (i == 0) ? "\"" : " ");
        strcat(cmdline, arg);
        if(i == 0)
          strcat(cmdline, "\"");

        env->ReleaseStringUTFChars(s, arg);
      }

      printf("Cmdline = %s\n", cmdline);     // DEBUG
    }

    {
      jsize len = env->GetArrayLength(jenvp);

      printf("Environment:\n");      // DEBUG

      LPTSTR envp = envbuf;
      int total = 0;
      jsize i;
      for(i=0; i<len; i++) {
        jstring s = (jstring) env->GetObjectArrayElement(jenvp, i);
        const char* keyval = env->GetStringUTFChars(s, NULL);

        printf("  %s\n", keyval);

        if(lstrcpy(envp, TEXT(keyval)) == NULL) {
          env->ReleaseStringUTFChars(jdir, dir);
          delete[] cmdline;

          env->ThrowNew(IOException, "failed to copy environment");
          return -1;
        }

        env->ReleaseStringUTFChars(s, keyval);

        int size = (lstrlen(envp) + 1) * sizeof(TCHAR);
        total += size;

        if(total > 32768) {
          env->ReleaseStringUTFChars(jdir, dir);
          delete[] cmdline;

          env->ThrowNew(IOException, "environment exceeds 32K limit on Windows!");
          return -1; 
        }

        envp += size;
      }
      *envp = '\0';
    }
  }
  
  /* create pipes to communicate with the child process */ 
  HANDLE child_stdin, child_stdout, child_stderr;
  HANDLE parent_stdin, parent_stdout, parent_stderr; 
  {
    /* security attributes which allow handles to be inherited by the child process */ 
    SECURITY_ATTRIBUTES saAttr; 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 
 
    /* create a pipe to the child's STDIN */
    if(!CreatePipe(&child_stdin, &parent_stdin, &saAttr, 0)) {
      env->ReleaseStringUTFChars(jdir, dir);
      delete[] cmdline;        

      env->ThrowNew(IOException, "unable to create the STDIN pipe!"); 
      return -1;
    }

    /* create a pipe to the child's STDOUT */
    if(!CreatePipe(&parent_stdout, &child_stdout, &saAttr, 0)) {
      env->ReleaseStringUTFChars(jdir, dir);
      delete[] cmdline;
      CloseHandle(child_stdin);

      env->ThrowNew(IOException, "unable to create the STDOUT pipe!"); 
      return -1;
    }

    /* create a pipe to the child's STDERR */
    if(!CreatePipe(&parent_stderr, &child_stderr, &saAttr, 0)) {
      env->ReleaseStringUTFChars(jdir, dir);
      delete[] cmdline;
      CloseHandle(child_stdin);
      CloseHandle(child_stdout);

      env->ThrowNew(IOException, "unable to create the STDERR pipe!"); 
      return -1;
    }  
    
    /* make sure parent side of STDIN STDOUT and STDERR pipes are not inherited */ 
    SetHandleInformation(parent_stdin, HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(parent_stdout, HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(parent_stderr, HANDLE_FLAG_INHERIT, 0);
  }
  
  /* create the child process */ 
  DWORD exitCode; 
  {
    PROCESS_INFORMATION procInfo; 
    STARTUPINFO startInfo;

    ZeroMemory(&procInfo, sizeof(PROCESS_INFORMATION));
 
    ZeroMemory(&startInfo, sizeof(STARTUPINFO));
    startInfo.cb = sizeof(STARTUPINFO); 
    startInfo.hStdError  = child_stderr;
    startInfo.hStdOutput = child_stdout; 
    startInfo.hStdInput  = child_stdin;
    startInfo.dwFlags |= STARTF_USESTDHANDLES;
 
    if(CreateProcess(NULL, TEXT(cmdline), NULL, NULL, TRUE, 0, 
                     (LPVOID) envbuf, TEXT(dir), &startInfo, &procInfo) == 0)  {
      env->ReleaseStringUTFChars(jdir, dir);
      delete[] cmdline;       
      CloseHandle(child_stdin);
      CloseHandle(child_stdout);
      CloseHandle(child_stderr);
      
      throwWindowsIOException(env, IOException, "CreateProcessAsUser"); 
      return -1;
    }
    env->ReleaseStringUTFChars(jdir, dir);
    delete[] cmdline;
                    
    printf("Created Process\n");     // DEBUG

    /* set the process ID */ 
    jint pid = (jint) procInfo.dwProcessId;
    env->CallVoidMethod(obj, setPid, pid);

    /* set IO fields for the parent ends of the pipes */ 
    env->SetIntField(obj, pStdInFileDesc, (jint) parent_stdin);
    env->SetIntField(obj, pStdOutFileDesc, (jint) parent_stdout);
    env->SetIntField(obj, pStdErrFileDesc, (jint) parent_stderr);

    /* let Java know that the process is running */ 
    env->CallVoidMethod(obj, setIsRunning, true);
      
    printf("Wating on PID (%d)...\n", pid);     // DEBUG

    /* wait on the process to exit */ 
    if(WaitForSingleObject(procInfo.hProcess, INFINITE) == WAIT_FAILED) {
      CloseHandle(child_stdin);
      CloseHandle(child_stdout);
      CloseHandle(child_stderr);

      env->ThrowNew(IOException, "failed to wait on subprocess!"); 
      return -1;
    }

    printf("Done Wating!\n");     // DEBUG

    /* let Java know that the process has exited */ 
    env->CallVoidMethod(obj, setIsRunning, false);
        
    /* get the exit code */ 
    if(!GetExitCodeProcess(procInfo.hProcess, &exitCode)) {
      CloseHandle(child_stdin);
      CloseHandle(child_stdout);
      CloseHandle(child_stderr);

      env->ThrowNew(IOException, "failed to get subprocess exit code!"); 
      return -1;
    }

    printf("Exit Code = %d\n", exitCode);       // DEBUG

    /* close the child side of the STDIN pipe */ 
    if(!CloseHandle(child_stdin)) {
      CloseHandle(child_stdout);
      CloseHandle(child_stderr);

      env->ThrowNew(IOException, "unable to close the child side of the STDIN pipe!"); 
      return -1;
    }

    /* close the child side of the STDOUT pipe */ 
    if(!CloseHandle(child_stdout)) {
      env->ThrowNew(IOException, "unable to close the child side of the STDOUT pipe!"); 
      return -1;
    }
    
    /* close the child side of the STDERR pipe */ 
    if(!CloseHandle(child_stderr)) {
      env->ThrowNew(IOException, "unable to close the child side of the STDERR pipe!"); 
      return -1;
    }

    /* get usage statistics */
    {
      FILETIME createTime, exitTime, sysTime, userTime; 
      if(!GetProcessTimes(procInfo.hProcess, &createTime, &exitTime, &sysTime, &userTime)) {
        env->ThrowNew(IOException, "failed to get subprocess timing statistics!"); 
        return -1;
      }

      /* 64-bit times returned by GetProcessTime are in 100ns (100/10^9), 
         while the times reported to Java are in jiffies (1/100) of a second */   
      jlong denom = 100000L;

      { 
        ULARGE_INTEGER li;
        memcpy(&li, &userTime, sizeof(FILETIME));
        env->SetLongField(obj, pUTime, li.QuadPart / denom);  

        printf("User Time = %I64u (100-ns)  %I64u (jiffies)\n", 
               li.QuadPart, li.QuadPart / denom); 
      }                                   

      { 
        ULARGE_INTEGER li;
        memcpy(&li, &sysTime, sizeof(FILETIME));
        env->SetLongField(obj, pSTime, li.QuadPart / denom);

        printf("System Time = %I64u (100-ns)  %I64u (jiffies)\n", 
               li.QuadPart, li.QuadPart / denom); 
      }

      /* get process memory usage statistics */ 
      {
        PROCESS_MEMORY_COUNTERS pmc;
        if(!GetProcessMemoryInfo(procInfo.hProcess, &pmc, sizeof(pmc))) {
          env->ThrowNew(IOException, "failed to get subprocess memory usage statistics!"); 
          return -1;
        }

        // DEBUG
        printf("PageFaults = %I64d\n", (jlong) pmc.PageFaultCount);
        printf("PeakWorking Set Size = %I64d\n", (jlong) pmc.PeakWorkingSetSize);
        printf("PeakPagefileUsage = %I64d\n", (jlong) pmc.PeakPagefileUsage);
        printf("QuotaPeakPagedPoolUsage = %I64d\n", (jlong) pmc.QuotaPeakPagedPoolUsage);
        // DEBUG

        env->SetLongField(obj, pPageFaults,   (jlong) pmc.PageFaultCount);
        env->SetLongField(obj, pResidentSize, (jlong) pmc.PeakWorkingSetSize); 
        env->SetLongField(obj, pVirtualSize,  (jlong) pmc.PeakPagefileUsage); 
        env->SetLongField(obj, pSwappedSize,  (jlong) pmc.QuotaPeakPagedPoolUsage);
      } 
    }

    /* cleanup process/thread handles */ 
    CloseHandle(procInfo.hProcess);
    CloseHandle(procInfo.hThread);
  }

  return ((jint) exitCode);
}
Example #13
0
BOOL LogServer::CreateLogPipe()
{
    logme("LogServer::CreateLogPipe: cmd=%s", GetExternalCmd());
    m_fpLog = _popen(GetExternalCmd(), "wb");
    if (m_fpLog == NULL)
    {
        fprintf(stderr, "LogServer: failed to open pipe (%s). err=%d\n", GetExternalCmd(), GetLastError());
        return FALSE;
    }
    return TRUE;

#if 0
    // Create the program
    HANDLE hProgStdinRd, hProgStdinWr;
    SECURITY_ATTRIBUTES saAttr;

    // Set the bInheritHandle flag so pipe handles are inherited.
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    // Create a pipe for the child process's STDIN.
    if (! CreatePipe(&hProgStdinRd, &hProgStdinWr, &saAttr, 0))
    {
        printf("JaxerLogger: Create Stdin pipe failed.\n");
        return FALSE;
    }

    // Ensure that the write handle to the child process's pipe for STDIN is not inherited.
    SetHandleInformation( hProgStdinWr, HANDLE_FLAG_INHERIT, 0);

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION) );

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO) );
    si.cb = sizeof(STARTUPINFO);
    si.hStdInput = hProgStdinRd;
    si.dwFlags |= STARTF_USESTDHANDLES;

    logme("JaxerLog: pipe cmd=%s", GetExternalCmd());
    BOOL rc = CreateProcess(NULL,
                            (TCHAR*)GetExternalCmd(),
                            NULL,  /* default process security descriptor */
                            NULL,  /* default thread security descriptor */
                            TRUE,  /* inherit handles */
                            CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB,
                            NULL,  /* inherit environment */
                            NULL,  /* inherit current directory */
                            &si,
                            &pi);

    if (!rc)
    {
        char s[256];
        sprintf(s,"JaxerLogger: Create process (%s) failed. err=%d\n", GetExternalCmd(),
                GetLastError());
        char *t = s;
        logme(s);
        return FALSE;
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    m_fdLog = hProgStdinWr;
}
Example #14
0
static boolean runcmdshell (Handle hshell, Handle hcommand, HANDLE *hprocess, HANDLE *hout, HANDLE *herr) {

	/*
	2006-03-09 aradke: launch the command shell as a child process.
		we consume hshell, but caller is responsible for closing hout if we return true.
	*/
	
	Handle hcmdline = nil;
	SECURITY_ATTRIBUTES securityinfo;
	STARTUPINFO startupinfo;
	PROCESS_INFORMATION processinfo;
	HANDLE houtread = nil;
	HANDLE houtwrite = nil;
	HANDLE herrread = nil;
	HANDLE herrwrite = nil;
	boolean fl;
	
	*hprocess = nil;
	
	/*create pipes for reading from command shell*/

	clearbytes (&securityinfo, sizeof (securityinfo));
	securityinfo.nLength				= sizeof (securityinfo);
	securityinfo.lpSecurityDescriptor	= nil;
	securityinfo.bInheritHandle			= true;
	
	if (hout) { /*caller interested in stdout*/
	
		if (!CreatePipe (&houtread, &houtwrite, &securityinfo, nil))
			goto error;
		
		if (!SetHandleInformation (houtread, HANDLE_FLAG_INHERIT, 0))
			goto error;
		}
	else
		houtwrite = GetStdHandle (STD_OUTPUT_HANDLE);

	if (herr) { /*caller interested in stderr*/

		if (!CreatePipe (&herrread, &herrwrite, &securityinfo, nil))
			goto error;
		
		if (!SetHandleInformation (herrread, HANDLE_FLAG_INHERIT, 0))
			goto error;
		}
	else
		herrwrite = GetStdHandle (STD_ERROR_HANDLE);
		
	/*init structs for creating process*/
	
	clearbytes (&startupinfo, sizeof (startupinfo));
	startupinfo.cb = sizeof (startupinfo);
	startupinfo.dwFlags		= STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	startupinfo.hStdInput	= GetStdHandle (STD_INPUT_HANDLE);
	startupinfo.hStdOutput	= houtwrite;
	startupinfo.hStdError	= herrwrite;
	startupinfo.wShowWindow	= SW_HIDE;
	
	clearbytes (&processinfo, sizeof (processinfo));
	
	/*synthesize command string*/
	
	if (!inserttextinhandle (hcommand, 0, "\x04" " /c "))
		goto exit;
	
	if (!concathandles (hshell, hcommand, &hcmdline))
		goto exit;
	
	if (!pushcharhandle (CHNULL, hshell))
		goto exit;

	if (!pushcharhandle (CHNULL, hcmdline))
		goto exit;
	
	/*check whether command shell can be accessed*/
	
	if (!cmdshellexists (hshell)) {
		if (!searchcmdpath (&hshell))	/*do a search path lookup, sets error*/
			goto exit;
		}
		
	/*create command shell process*/
	
	lockhandle (hshell);
	lockhandle (hcmdline);
	
	fl = CreateProcess (
			*hshell,		/*IN LPCSTR lpApplicationName*/
			*hcmdline,		/*IN LPSTR lpCommandLine*/
			nil,			/*IN LPSECURITY_ATTRIBUTES lpProcessAttributes*/
			nil,			/*IN LPSECURITY_ATTRIBUTES lpThreadAttributes*/
			true,			/*IN BOOL bInheritHandles*/
			0,				/*IN DWORD dwCreationFlags*/
			nil,			/*IN LPVOID lpEnvironment: use parent's*/
			nil,			/*IN LPCSTR lpCurrentDirectory: use parent's*/
			&startupinfo,	/*IN LPSTARTUPINFOA lpStartupInfo*/
			&processinfo);	/*OUT LPPROCESS_INFORMATION lpProcessInformation*/
	
	unlockhandle (hshell);
	unlockhandle (hcmdline);
	
	/*handle result*/
	
	if (!fl)
		goto error;
	
	CloseHandle (houtwrite);	/*now inherited by child process*/
	CloseHandle (herrwrite);
	
	CloseHandle (processinfo.hThread);
	
	disposehandle (hcmdline);
	disposehandle (hshell);
	
	*hprocess = processinfo.hProcess;
	
	if (hout)
		*hout = houtread;
	
	if (herr)
		*herr = herrread;
	
	return (true);

error:
	winerror (); /*note fall through*/
		
exit:	/*error is already set*/
	if (hout && !houtread)
		CloseHandle (houtread);
	
	if (hout && !houtwrite)
		CloseHandle (houtwrite);
	
	if (herr && !herrread)
		CloseHandle (herrread);
	
	if (herr && !herrwrite)
		CloseHandle (herrwrite);

	disposehandle (hcmdline);
	disposehandle (hshell);
	
	return (false);	
	} /*runcmdshell*/
Example #15
0
Socket platform_new_connection(SockAddr addr, char *hostname,
			       int port, int privport,
			       int oobinline, int nodelay, int keepalive,
			       Plug plug, Conf *conf)
{
    char *cmd;
    HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us;
    SECURITY_ATTRIBUTES sa;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
	return NULL;

    cmd = format_telnet_command(addr, port, conf);

    /* We are responsible for this and don't need it any more */
    sk_addr_free(addr);

    {
	char *msg = dupprintf("Starting local proxy command: %s", cmd);
	/* We're allowed to pass NULL here, because we're part of the Windows
	 * front end so we know logevent doesn't expect any data. */
	logevent(NULL, msg);
	sfree(msg);
    }

    /*
     * Create the pipes to the proxy command, and spawn the proxy
     * command process.
     */
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = NULL;    /* default */
    sa.bInheritHandle = TRUE;
    if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
	Socket ret =
            new_error_socket("Unable to create pipes for proxy command", plug);
        sfree(cmd);
	return ret;
    }

    if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
	Socket ret =
            new_error_socket("Unable to create pipes for proxy command", plug);
        sfree(cmd);
	CloseHandle(us_from_cmd);
	CloseHandle(cmd_to_us);
	return ret;
    }

    SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0);
    SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0);

    si.cb = sizeof(si);
    si.lpReserved = NULL;
    si.lpDesktop = NULL;
    si.lpTitle = NULL;
    si.dwFlags = STARTF_USESTDHANDLES;
    si.cbReserved2 = 0;
    si.lpReserved2 = NULL;
    si.hStdInput = cmd_from_us;
    si.hStdOutput = cmd_to_us;
    si.hStdError = NULL;
    CreateProcess(NULL, cmd, NULL, NULL, TRUE,
		  CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
		  NULL, NULL, &si, &pi);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    sfree(cmd);

    CloseHandle(cmd_from_us);
    CloseHandle(cmd_to_us);

    return make_handle_socket(us_to_cmd, us_from_cmd, plug, FALSE);
}
Example #16
0
extern "C" JNIEXPORT void JNICALL 
Java_java_lang_Runtime_exec(JNIEnv* e, jclass, 
                            jobjectArray command, jlongArray process)
{
#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  int size = 0;
  for (int i = 0; i < e->GetArrayLength(command); ++i){
    jstring element = (jstring) e->GetObjectArrayElement(command, i);
    if(element) {
      // worst case, assuming every character is '"', and we escape all of them
      size += 2 * e->GetStringUTFLength(element) + 3;
    } else {
      throwNew(e, "java/lang/NullPointerException", strdup("null string array element"));
    }
  }
   
  RUNTIME_ARRAY(char, line, size);
  char* linep = RUNTIME_ARRAY_BODY(line);
  for (int i = 0; i < e->GetArrayLength(command); ++i) {
    if (i) *(linep++) = _T(' ');
    jstring element = (jstring) e->GetObjectArrayElement(command, i);
    const char* s =  e->GetStringUTFChars(element, 0);

    copyAndEscape(&linep, s, e->GetStringUTFLength(element));

    e->ReleaseStringUTFChars(element, s);
  }
  *(linep++) = _T('\0');
 
  HANDLE in[] = { 0, 0 };
  HANDLE out[] = { 0, 0 };
  HANDLE err[] = { 0, 0 };
  
  makePipe(e, in);
  SetHandleInformation(in[0], HANDLE_FLAG_INHERIT, 0);
  jlong inDescriptor = static_cast<jlong>(descriptor(e, in[0]));
  if(e->ExceptionCheck()) return;
  e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
  makePipe(e, out);
  SetHandleInformation(out[1], HANDLE_FLAG_INHERIT, 0);
  jlong outDescriptor = static_cast<jlong>(descriptor(e, out[1]));
  if(e->ExceptionCheck()) return;
  e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
  makePipe(e, err);
  SetHandleInformation(err[0], HANDLE_FLAG_INHERIT, 0);
  jlong errDescriptor = static_cast<jlong>(descriptor(e, err[0]));
  if(e->ExceptionCheck()) return;
  e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
  
  PROCESS_INFORMATION pi;
  ZeroMemory(&pi, sizeof(pi));
 
  STARTUPINFO si;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  si.dwFlags = STARTF_USESTDHANDLES;
  si.hStdOutput = in[1];
  si.hStdInput = out[0];
  si.hStdError = err[1];
 
  BOOL success = CreateProcess(0, (LPSTR) RUNTIME_ARRAY_BODY(line), 0, 0, 1,
                               CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,
                               0, 0, &si, &pi);

  CloseHandle(in[1]);
  CloseHandle(out[0]);
  CloseHandle(err[1]);
  
  if (not success) {
    throwNew(e, "java/io/IOException", getErrorStr(GetLastError()));
    return;
  }
  
  jlong pid = reinterpret_cast<jlong>(pi.hProcess);
  e->SetLongArrayRegion(process, 0, 1, &pid);
  jlong tid = reinterpret_cast<jlong>(pi.hThread);  
  e->SetLongArrayRegion(process, 1, 1, &tid);
#else
  throwNew(e, "java/io/Exception", strdup("Not supported on WinRT/WinPhone8"));
#endif
}
Example #17
0
static int _execIO( UThread* ut, char* cmd, UCell* res,
                    const UBuffer* in, UBuffer* out, UBuffer* err )
{
    HANDLE childStdInR;
    HANDLE childStdInW;
    HANDLE childStdOutR;
    HANDLE childStdOutW;
    HANDLE childStdErrR;
    HANDLE childStdErrW;
    SECURITY_ATTRIBUTES sec;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DWORD flags = 0;


    sec.nLength              = sizeof(SECURITY_ATTRIBUTES); 
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle       = TRUE; 

    childStdOutR = childStdErrR = INVALID_HANDLE_VALUE;

    if( in )
    {
        if( ! CreatePipe( &childStdInR, &childStdInW, &sec, 0 ) ) 
        {
fail0:
            return ur_error( ut, UR_ERR_INTERNAL, "CreatePipe failed\n" );
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdInW, HANDLE_FLAG_INHERIT, 0 );
    }

    if( out )
    {
        if( ! CreatePipe( &childStdOutR, &childStdOutW, &sec, 0 ) ) 
        {
fail1:
            if( in )
                _closePipe( childStdInR, childStdInW );
            goto fail0;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdOutR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    if( err )
    {
        if( ! CreatePipe( &childStdErrR, &childStdErrW, &sec, 0 ) ) 
        {
            if( out )
                _closePipe( childStdOutR, childStdOutW );
            goto fail1;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdErrR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    if( in || out || err )
    {
        si.hStdInput  = in  ? childStdInR  : NULL;
        si.hStdOutput = out ? childStdOutW : GetStdHandle( STD_OUTPUT_HANDLE );
        si.hStdError  = err ? childStdErrW : GetStdHandle( STD_ERROR_HANDLE );
        si.dwFlags    = STARTF_USESTDHANDLES;
    }

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( ! CreateProcess( NULL,   // No module name (use command line). 
        TEXT(cmd),        // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        TRUE,             // Handle inheritance. 
        flags,            // Creation flags.
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    )
    {
        if( in )
            _closePipe( childStdInR, childStdInW );
        if( out )
            _closePipe( childStdOutR, childStdOutW );
        if( err )
            _closePipe( childStdErrR, childStdErrW );
        return ur_error( ut, UR_ERR_INTERNAL,
                         "CreateProcess failed (%d).\n", GetLastError() );
    }

    if( in )
    {
        DWORD nw;
        CloseHandle( childStdInR );
        WriteFile( childStdInW, in->ptr.v,
                   (in->type == UT_STRING) ? in->used * in->elemSize : in->used,
                   &nw, NULL );
        CloseHandle( childStdInW );
    }

    if( out || err )
    {
        if( out )
            CloseHandle( childStdOutW );
        if( err )
            CloseHandle( childStdErrW );
        _readPipes( childStdOutR, out, childStdErrR, err );
        if( out )
            CloseHandle( childStdOutR );
        if( err )
            CloseHandle( childStdErrR );
    }

    {
    DWORD code;

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    if( GetExitCodeProcess( pi.hProcess, &code ) )
    {
        ur_setId(res, UT_INT);
        ur_int(res) = code;
    }
    else
    {
        ur_setId(res, UT_NONE);
    }
    }

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return UR_OK;
}
Example #18
0
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
  (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels) 
{
	HANDLE stdHandles[3];
    PROCESS_INFORMATION pi = {0}, *piCopy;
    STARTUPINFOW si;
	DWORD flags = 0;
    const wchar_t  * cwd = NULL;
	LPVOID envBlk = NULL;
    int ret = 0;
    int nCmdLineLength= 0;
	wchar_t * szCmdLine= 0;
	int nBlkSize = MAX_ENV_SIZE; 
	wchar_t * szEnvBlock = NULL;
	jsize nCmdTokens = 0;
	jsize nEnvVars = 0;
	int i;
	DWORD pid = GetCurrentProcessId();
	int nPos;
	pProcInfo_t pCurProcInfo;

	// This needs to be big enough to contain the name of the event used when calling CreateEventW bellow. 
	// It is made of a prefix (7 characters max) plus the value of a pointer that gets output in characters.
	// This will be bigger in the case of 64 bit.
	static const int MAX_EVENT_NAME_LENGTH = 50;
	wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventWaitName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventTerminateName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventKillName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventCtrlcName[MAX_EVENT_NAME_LENGTH];
#ifdef DEBUG_MONITOR
	wchar_t buffer[4000];
#endif
	int nLocalCounter;
	wchar_t inPipeName[PIPE_NAME_LENGTH];
	wchar_t outPipeName[PIPE_NAME_LENGTH];
	wchar_t errPipeName[PIPE_NAME_LENGTH];

    nCmdLineLength= MAX_CMD_SIZE;
    szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t));
    szCmdLine[0]= _T('\0');
	if((HIBYTE(LOWORD(GetVersion()))) & 0x80)
		{
		ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me");
		return 0;
		}

    if (cmdarray == 0) 
		{
		ThrowByName(env, "java/lang/NullPointerException", "No command line specified");
		return 0;
		}

   ZeroMemory(stdHandles, sizeof(stdHandles));

	// Create pipe names
   EnterCriticalSection(&cs);
   swprintf(inPipeName,  L"\\\\.\\pipe\\stdin%08i%010i",  pid, nCounter); 
   swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", pid, nCounter); 
   swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", pid, nCounter); 
   nLocalCounter = nCounter;
   ++nCounter;
   LeaveCriticalSection(&cs);

   if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipeW(inPipeName, PIPE_ACCESS_OUTBOUND,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
	   (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipeW(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
	   (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipeW(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))))		{
		CloseHandle(stdHandles[0]);
        CloseHandle(stdHandles[1]);
        CloseHandle(stdHandles[2]);
		ThrowByName(env, "java/io/IOException", "CreatePipe");
		return 0;
   } 

#ifdef DEBUG_MONITOR
	swprintf(buffer, _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
	OutputDebugStringW(buffer);
#endif
	

	nCmdTokens = env->GetArrayLength(cmdarray);
    nEnvVars   = env->GetArrayLength(envp);

	pCurProcInfo = createProcInfo();

	if(NULL == pCurProcInfo)
		{
		ThrowByName(env, "java/io/IOException", "Too many processes");
		return 0;
		}

	// Construct starter's command line
	swprintf(eventBreakName, L"SABreak%04x%08x", pid, nLocalCounter);
	swprintf(eventWaitName, L"SAWait%004x%08x", pid, nLocalCounter);
	swprintf(eventTerminateName, L"SATerm%004x%08x", pid, nLocalCounter);
	swprintf(eventKillName, L"SAKill%04x%08x", pid, nLocalCounter);
	swprintf(eventCtrlcName, L"SACtrlc%04x%08x", pid, nLocalCounter);

	pCurProcInfo->eventBreak     = CreateEventW(NULL, FALSE, FALSE, eventBreakName);
    if(NULL == pCurProcInfo->eventBreak || GetLastError() == ERROR_ALREADY_EXISTS)
        {
        ThrowByName(env, "java/io/IOException", "Cannot create event");
        return 0;
        }
	pCurProcInfo->eventWait      = CreateEventW(NULL, TRUE,  FALSE, eventWaitName);
	pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName);
	pCurProcInfo->eventKill      = CreateEventW(NULL, FALSE, FALSE, eventKillName);
	pCurProcInfo->eventCtrlc     = CreateEventW(NULL, FALSE, FALSE, eventCtrlcName);

	swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName, eventKillName, eventCtrlcName);
	nPos = wcslen(szCmdLine);

	// Prepare command line
	for(i = 0; i < nCmdTokens; ++i) 
    	{
		jstring item = (jstring)env->GetObjectArrayElement(cmdarray, i);
		jsize    len = env->GetStringLength(item);
		int nCpyLen;
		const wchar_t *  str = (const wchar_t *)env->GetStringChars(item, 0);	
		if(NULL != str) 
			{
			int requiredSize= nPos+len+2;
			if (requiredSize > 32*1024) {
				ThrowByName(env, "java/io/IOException", "Command line too long");
				return 0;
			}				
			ensureSize(&szCmdLine, &nCmdLineLength, requiredSize);
			if (NULL == szCmdLine) {
				ThrowByName(env, "java/io/IOException", "Not enough memory");
				return 0;
			}
			    
			if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, nCmdLineLength - nPos)))
                {
				ThrowByName(env, "java/io/IOException", "Command line too long");
				return 0;
			}
			nPos += nCpyLen;
			szCmdLine[nPos] = _T(' ');
			++nPos;
			env->ReleaseStringChars(item, (const jchar *)str);
		}
	}
	szCmdLine[nPos] = _T('\0');

#ifdef DEBUG_MONITOR
	swprintf(buffer, _T("There are %i environment variables \n"), nEnvVars);
	OutputDebugStringW(buffer);
#endif
	// Prepare environment block
    if (nEnvVars > 0) 
		{
		nPos = 0;
		szEnvBlock = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t));
		for(i = 0; i < nEnvVars; ++i) 
			{
			jstring item = (jstring)env->GetObjectArrayElement(envp, i);
			jsize    len = env->GetStringLength(item);
			const wchar_t *  str = (const wchar_t *)env->GetStringChars(item, 0);	
			if(NULL != str)
				{
				while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0'
					{
					nBlkSize += MAX_ENV_SIZE;
					szEnvBlock = (wchar_t *)realloc(szEnvBlock, nBlkSize * sizeof(wchar_t));
					if(NULL == szEnvBlock) 
						{
						ThrowByName(env, "java/io/IOException", "Not enough memory");
						return 0;
						}
#ifdef DEBUG_MONITOR
					swprintf(buffer, _T("Realloc environment block; new length is  %i \n"), nBlkSize);
					OutputDebugStringW(buffer);
#endif

					}
#ifdef DEBUG_MONITOR
				swprintf(buffer, _T("%s\n"), str);
				OutputDebugStringW(buffer);
#endif
				wcsncpy(szEnvBlock + nPos, str, len);
				nPos += len;
				szEnvBlock[nPos] = _T('\0');
				++nPos;
				env->ReleaseStringChars(item, (const jchar *)str);
				}
			}
			szEnvBlock[nPos] = _T('\0');
		}



    if (dir != 0) 
		{ 
		const wchar_t * str = (const wchar_t *)env->GetStringChars(dir, 0);
		if(NULL != str)
			{
			cwd = wcsdup(str);
			env->ReleaseStringChars(dir, (const jchar *)str);
			}
		}


    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags |= STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;  // Processes in the Process Group are hidden



    SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE);
    SetHandleInformation(stdHandles[1],  HANDLE_FLAG_INHERIT, FALSE);
    SetHandleInformation(stdHandles[2],  HANDLE_FLAG_INHERIT, FALSE);

	flags = CREATE_NEW_CONSOLE;
	flags |= CREATE_NO_WINDOW;
	flags |= CREATE_UNICODE_ENVIRONMENT;

#ifdef DEBUG_MONITOR
	OutputDebugStringW(szCmdLine);
#endif
	// launches starter; we need it to create another console group to correctly process 
	// emulation of SYSint signal (Ctrl-C)
    ret = CreateProcessW(0,                /* executable name */
                        szCmdLine,        /* command line */
                        0,                /* process security attribute */
                        0,                /* thread security attribute */
                        FALSE,            /* inherits system handles */
                        flags,            /* normal attached process */
                        szEnvBlock,		  /* environment block */
                        cwd,              /* change to the new current directory */
                        &si,              /* (in)  startup information */
                        &pi);             /* (out) process information */

	if(NULL != cwd)
		free((void *)cwd);

	if(NULL != szEnvBlock)
		free(szEnvBlock);

    if(NULL != szCmdLine) 
        free(szCmdLine);
      
    if (!ret) // Launching error
		{
		char * lpMsgBuf;	    
		CloseHandle(stdHandles[0]);
		CloseHandle(stdHandles[1]);
		CloseHandle(stdHandles[2]); 
		FormatMessageA( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(char *)&lpMsgBuf,
			0,
			NULL 
		);
		ThrowByName(env, "java/io/IOException", lpMsgBuf);
		// Free the buffer.
		LocalFree( lpMsgBuf );
		cleanUpProcBlock(pCurProcInfo);
		ret = -1;
		}
    else
		{
    	int file_handles[3];
		HANDLE h[2];
		int what;

		EnterCriticalSection(&cs);

		pCurProcInfo -> pid = pi.dwProcessId;
        h[0] = pCurProcInfo -> eventWait;
		h[1] = pi.hProcess;
		
		what = WaitForMultipleObjects(2, h, FALSE, INFINITE); 
		if(what != WAIT_OBJECT_0) // CreateProcess failed
			{
#ifdef DEBUG_MONITOR
			swprintf(buffer, _T("Process %i failed\n"), pi.dwProcessId);
			OutputDebugStringW(buffer);
#endif
			cleanUpProcBlock(pCurProcInfo);
			ThrowByName(env, "java/io/IOException", "Launching failed");
#ifdef DEBUG_MONITOR
			OutputDebugStringW(_T("Process failed\n"));
#endif
			}
		else 
			{
			ret = (long)(pCurProcInfo -> uid);
			
			// Prepare stream handlers to return to java program
			file_handles[0] = (int)stdHandles[0];
			file_handles[1] = (int)stdHandles[1];
			file_handles[2] = (int)stdHandles[2];
			env->SetIntArrayRegion(channels, 0, 3, (jint *)file_handles);

			// do the cleanup so launch the according thread
			// create a copy of the PROCESS_INFORMATION as this might get destroyed
			piCopy = (PROCESS_INFORMATION *)malloc(sizeof(PROCESS_INFORMATION));
			memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION));
			_beginthread(waitProcTermination, 0, (void *)piCopy);

#ifdef DEBUG_MONITOR
			OutputDebugStringW(_T("Process started\n"));
#endif
			}				
		LeaveCriticalSection(&cs);

		}

	CloseHandle(pi.hThread);

    return ret;

}
Example #19
-1
//
// Tries to call where.exe to find the location of dotnet.exe.
// Will check that the bitness of dotnet matches the current
// worker process bitness.
// Returns true if a valid dotnet was found, else false.R
//
std::optional<fs::path>
HOSTFXR_UTILITY::InvokeWhereToFindDotnet()
{
    HRESULT             hr = S_OK;
    // Arguments to call where.exe
    STARTUPINFOW        startupInfo = { 0 };
    PROCESS_INFORMATION processInformation = { 0 };
    SECURITY_ATTRIBUTES securityAttributes;

    CHAR                pzFileContents[READ_BUFFER_SIZE];
    HandleWrapper<InvalidHandleTraits>     hStdOutReadPipe;
    HandleWrapper<InvalidHandleTraits>     hStdOutWritePipe;
    HandleWrapper<InvalidHandleTraits>     hProcess;
    HandleWrapper<InvalidHandleTraits>     hThread;
    CComBSTR            pwzDotnetName = NULL;
    DWORD               dwFilePointer;
    BOOL                fIsWow64Process;
    BOOL                fIsCurrentProcess64Bit;
    DWORD               dwExitCode;
    STRU                struDotnetSubstring;
    STRU                struDotnetLocationsString;
    DWORD               dwNumBytesRead;
    DWORD               dwBinaryType;
    INT                 index = 0;
    INT                 prevIndex = 0;
    std::optional<fs::path> result;

    // Set the security attributes for the read/write pipe
    securityAttributes.nLength = sizeof(securityAttributes);
    securityAttributes.lpSecurityDescriptor = NULL;
    securityAttributes.bInheritHandle = TRUE;

    LOG_INFO(L"Invoking where.exe to find dotnet.exe");

    // Create a read/write pipe that will be used for reading the result of where.exe
    FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0));
    FINISHED_LAST_ERROR_IF(!SetHandleInformation(hStdOutReadPipe, HANDLE_FLAG_INHERIT, 0));

    // Set the stdout and err pipe to the write pipes.
    startupInfo.cb = sizeof(startupInfo);
    startupInfo.dwFlags |= STARTF_USESTDHANDLES;
    startupInfo.hStdOutput = hStdOutWritePipe;
    startupInfo.hStdError = hStdOutWritePipe;

    // CreateProcess requires a mutable string to be passed to commandline
    // See https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083/
    pwzDotnetName = L"\"where.exe\" dotnet.exe";

    // Create a process to invoke where.exe
    FINISHED_LAST_ERROR_IF(!CreateProcessW(NULL,
        pwzDotnetName,
        NULL,
        NULL,
        TRUE,
        CREATE_NO_WINDOW,
        NULL,
        NULL,
        &startupInfo,
        &processInformation
    ));

    // Store handles into wrapper so they get closed automatically
    hProcess = processInformation.hProcess;
    hThread = processInformation.hThread;

    // Wait for where.exe to return
    WaitForSingleObject(processInformation.hProcess, INFINITE);

    //
    // where.exe will return 0 on success, 1 if the file is not found
    // and 2 if there was an error. Check if the exit code is 1 and set
    // a new hr result saying it couldn't find dotnet.exe
    //
    FINISHED_LAST_ERROR_IF (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode));

    //
    // In this block, if anything fails, we will goto our fallback of
    // looking in C:/Program Files/
    //
    if (dwExitCode != 0)
    {
        FINISHED_IF_FAILED(E_FAIL);
    }

    // Where succeeded.
    // Reset file pointer to the beginning of the file.
    dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN);
    if (dwFilePointer == INVALID_SET_FILE_POINTER)
    {
        FINISHED_IF_FAILED(E_FAIL);
    }

    //
    // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang.
    // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block.
    //
    FINISHED_LAST_ERROR_IF (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL));

    if (dwNumBytesRead >= READ_BUFFER_SIZE)
    {
        // This shouldn't ever be this large. We could continue to call ReadFile in a loop,
        // however if someone had this many dotnet.exes on their machine.
        FINISHED_IF_FAILED(E_FAIL);
    }

    FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead));

    LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr());

    // Check the bitness of the currently running process
    // matches the dotnet.exe found.
    FINISHED_LAST_ERROR_IF (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process));

    if (fIsWow64Process)
    {
        // 32 bit mode
        fIsCurrentProcess64Bit = FALSE;
    }
    else
    {
        // Check the SystemInfo to see if we are currently 32 or 64 bit.
        SYSTEM_INFO systemInfo;
        GetNativeSystemInfo(&systemInfo);
        fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
    }

    LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit);

    while (TRUE)
    {
        index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex);
        if (index == -1)
        {
            break;
        }

        FINISHED_IF_FAILED(struDotnetSubstring.Copy(&struDotnetLocationsString.QueryStr()[prevIndex], index - prevIndex));
        // \r\n is two wchars, so add 2 here.
        prevIndex = index + 2;

        LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr());

        if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType)))
        {
            continue;
        }

        LOG_INFOF(L"Binary type %d", dwBinaryType);

        if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY))
        {
            // The bitness of dotnet matched with the current worker process bitness.
            return std::make_optional(struDotnetSubstring.QueryStr());
        }
    }

    Finished:
    return result;
}