void limitMem( size_t limit )
{
    static HANDLE hJob = NULL;
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo;

    jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
    jobInfo.ProcessMemoryLimit = limit? limit*MByte : 2*MByte*1024;
    if (NULL == hJob) {
        if (NULL == (hJob = CreateJobObject(NULL, NULL))) {
            REPORT("Can't assign create job object: %ld\n", GetLastError());
            exit(1);
        }
        if (0 == AssignProcessToJobObject(hJob, GetCurrentProcess())) {
            REPORT("Can't assign process to job object: %ld\n", GetLastError());
            exit(1);
        }
    }
    if (0 == SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
                                     &jobInfo, sizeof(jobInfo))) {
        REPORT("Can't set limits: %ld\n", GetLastError());
        exit(1);
    }
}
Beispiel #2
3
BOOL CreateBuilderJob(PCTSTR appName, PTSTR cmdLine, PCTSTR workDir, H2BOperation& op)
{
	BOOL ret = TRUE;
	DWORD err = ERROR_SUCCESS;
	HANDLE job = CreateJobObject(NULL, NULL);

	if( job )
	{
		JOBOBJECT_BASIC_LIMIT_INFORMATION jobLimit = { };

		jobLimit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
		jobLimit.ActiveProcessLimit = 1;

		if( SetInformationJobObject(job, JobObjectBasicLimitInformation, 
			&jobLimit, sizeof(jobLimit)) )
		{
			if( ! CreateBuilderProcess(job, appName, cmdLine, workDir, op) )
				err = GetLastError();
		}

		if( err == ERROR_CANCELLED )
			TerminateJobObject(job, ERROR_CANCELLED);

		CloseHandle(job);
	}

	if( err != ERROR_SUCCESS )
	{
		SetLastError(err);
		ret = FALSE;
	}

	return ret;
}
Beispiel #3
0
bool JobbedProcessManager::spawn() {
	HANDLE handle;
	STARTUPINFO si = {sizeof(STARTUPINFO), 0};
	PROCESS_INFORMATION pi;

	if (!szUsername)
		return false;

	if (!CreatePipe(&si.hStdInput, &handle, nullptr, 0))
		throw WindowsException("CreatePipe stdin");
	hStdin = handle;

	if (!CreatePipe(&handle, &si.hStdOutput, nullptr, 0))
		throw WindowsException("CreatePipe stdout");
	hStdout = handle;

	if (!CreatePipe(&handle, &si.hStdError, nullptr, 0))
		throw WindowsException("CreatePipe stderr");
	hStderr = handle;
	si.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;

	if (!CreateProcessWithLogonW(szUsername, L".", szPassword, 0, szExecutable, szCmdLine,
								 NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB |
								 CREATE_UNICODE_ENVIRONMENT,
								 szEnvBlock, szDirectory, &si, &pi))
		throw WindowsException("CreateProcessWithLogonW");

	CloseHandle(si.hStdInput);
	CloseHandle(si.hStdOutput);
	CloseHandle(si.hStdError);
	hProcess = pi.hProcess;

	if (!(handle = SearchForJobByService(hProcess, L"seclogon")))
		throw WindowsException("Failed to find job", 0);

	hJob = handle;
	if (!SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &extLimits, sizeof extLimits))
		throw WindowsException("SetInformationJobObject JobObjectExtendedLimitInformation");

	if (!SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &uiLimits, sizeof uiLimits))
		throw WindowsException("SetInformationJobObject JobObjectBasicUIRestrictions");

	LARGE_INTEGER liFreq;
	QueryPerformanceFrequency(&liFreq);
	qpc_freq = 1.0 / liFreq.QuadPart;
	QueryPerformanceCounter(&liStart);
	ResumeThread(pi.hThread);
	CloseHandle(pi.hThread);

	if (!(handle = CreateThread(nullptr, 0, s_ShockerProc, this, 0, nullptr)))
		throw WindowsException("CreateThread");
	hShocker = handle;

	return true;
}
JobObject::JobObject(void)
:
	m_hJobObject(NULL)
{
	HANDLE jobObject = CreateJobObject(NULL, NULL);
	if((jobObject != NULL) && (jobObject != INVALID_HANDLE_VALUE))
	{
		JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
		memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
		memset(&jobExtendedLimitInfo.BasicLimitInformation, 0, sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION));
		jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
		if(SetInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
		{
			m_hJobObject = jobObject;
		}
		else
		{
			qWarning("Failed to set job object information!");
			CloseHandle(jobObject);
		}
	}
	else
	{
		qWarning("Failed to create the job object!");
	}
}
Beispiel #5
0
/* This could be interesting to expose in public API */
static void
_g_test_watcher_add_pid (GPid pid)
{
  static gsize started = 0;
  HANDLE job;

  if (g_once_init_enter (&started))
    {
      JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;

      job = CreateJobObjectW (NULL, NULL);
      memset (&info, 0, sizeof (info));
      info.BasicLimitInformation.LimitFlags = 0x2000 /* JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE */;

      if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &info, sizeof (info)))
	g_warning ("Can't enable JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: %s", g_win32_error_message (GetLastError()));

      g_once_init_leave (&started,(gsize)job);
    }

  job = (HANDLE)started;

  if (!AssignProcessToJobObject(job, pid))
    g_warning ("Can't assign process to job: %s", g_win32_error_message (GetLastError()));
}
Beispiel #6
0
void CJobObject::SetExtendedLimit(const JOBOBJECT_EXTENDED_LIMIT_INFORMATION& pLimit) {
   static BOOL bAlreadySet = FALSE;
   BOOL bRet;

   if (bAlreadySet == FALSE) {
      JOBOBJECT_END_OF_JOB_TIME_INFORMATION EndOfJobTimeAction;

      EndOfJobTimeAction.EndOfJobTimeAction = JOB_OBJECT_POST_AT_END_OF_JOB;
      bRet = SetInformationJobObject(GetHandle(), JobObjectEndOfJobTimeInformation,
         (PVOID) &EndOfJobTimeAction, sizeof(JOBOBJECT_END_OF_JOB_TIME_INFORMATION));
   }
   bRet = SetInformationJobObject(GetHandle(), JobObjectExtendedLimitInformation,
      (PVOID) &pLimit, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
   if (bRet == 0) {
      throw CCodineException(CError::GetErrorMessage(GetLastError()), __FILE__, __LINE__);
   }
}
Beispiel #7
0
	//--------------------------------------------------------------------------------
	bool CJob::SetGroupAffinityInfo( nsCodeQOR::CTLRef< CJob::sGroupAffinity > GroupAffinity, unsigned int uiCount )
	{
		_WINQ_FCONTEXT( "CJob::SetGroupAffinityInfo" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectGroupInformationEx, GroupAffinity.operator nsWin32::CJob::sGroupAffinity *(), uiCount * sizeof( sGroupAffinity ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #8
0
	//--------------------------------------------------------------------------------
	bool CJob::SetGroupInfo( nsCodeQOR::CTLRef< unsigned short > GroupInfo, unsigned int uiCount )
	{
		_WINQ_FCONTEXT( "CJob::SetGroupInfo" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectGroupInformation, GroupInfo.operator unsigned short *(), uiCount * sizeof( unsigned short ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #9
0
	//--------------------------------------------------------------------------------
	bool CJob::SetCPURateControlInfo( CJob::sJobObjectCPURateControlInformation& CPURateControlInformation )
	{
		_WINQ_FCONTEXT( "CJob::SetCPURateControlInfo" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectCpuRateControlInformation, &CPURateControlInformation, sizeof( sJobObjectCPURateControlInformation ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #10
0
	//--------------------------------------------------------------------------------
	bool CJob::SetCompletionPortInfo( CJob::sJobObjectAssociateCompletionPort& AssociateCompletionPort )
	{
		_WINQ_FCONTEXT( "CJob::SetCompletionPortInfo" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectAssociateCompletionPortInformation, &AssociateCompletionPort, sizeof( sJobObjectAssociateCompletionPort ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #11
0
	//--------------------------------------------------------------------------------
	bool CJob::SetEndOfJobTimeInfo( CJob::sJobObjectEndOfJobTimeInformation& EndOfJobTimeInformation )
	{
		_WINQ_FCONTEXT( "CJob::SetEndOfJobTimeInfo" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectEndOfJobTimeInformation, &EndOfJobTimeInformation, sizeof( sJobObjectEndOfJobTimeInformation ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #12
0
	//--------------------------------------------------------------------------------
	bool CJob::SetUILimits( CJob::sJobObjectBasicUIRestrictions& UIRestrictions )
	{
		_WINQ_FCONTEXT( "CJob::SetUILimits" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectBasicUIRestrictions, &UIRestrictions, sizeof( sJobObjectBasicUIRestrictions ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #13
0
	//--------------------------------------------------------------------------------
	bool CJob::SetNotificationLimitInformation( nsCodeQOR::CTLRef< CJob::sJobObjectNotificationLimitInformation > NotificationLimitInformation )
	{
		_WINQ_FCONTEXT( "CJob::SetNotificationLimitInformation" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectNotificationLimitInformation, &NotificationLimitInformation, sizeof( sJobObjectNotificationLimitInformation ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #14
0
	//--------------------------------------------------------------------------------
	bool CJob::SetBasicLimitInformation( nsCodeQOR::CTLRef< CJob::sJobObjectBasicLimitInformation > BasicLimitInformation )
	{
		_WINQ_FCONTEXT( "CJob::SetBasicLimitInformation" );
		bool bResult = false;
		__QOR_PROTECT
		{
			bResult = SetInformationJobObject( JobObjectBasicLimitInformation, BasicLimitInformation.operator nsWin32::CJob::sJobObjectBasicLimitInformation *(), sizeof( sJobObjectBasicLimitInformation ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #15
0
/// <summary>
///	Creates a console object and starts the child process </summary>
///
/// <param name="ac">
/// Uninitialized console object </param>
/// <param name="tzClientPath">
/// Path to client, in an inject environment this should not be relative </param>
///
/// <returns>
/// If child could be created </returns>
BOOL ImAllocConsole(OUT IM_CONSOLE* ac, IN const TCHAR* tzClientPath) {
       
    SecureZeroMemory(ac->tzClientPipe, MAX_NAME);

    // generate a random name (tmpnam has a forward slash and is not necessarily alphanumeric)
    for (register size_t i = 0; i < rand() % MAX_NAME; ++i) {
        ac->tzClientPipe[i] = rand() % 26 + 'A'; // make random letter
        ac->tzClientPipe[i] ^= rand() % 1 << 5;  // randomly toggle 0x20 (upper/lowercase)
    }
        
    { // create job object and set information
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION joELI;

        ac->hJob = CreateJobObject(NULL, ac->tzClientPipe);
        if (ac->hJob == NULL)
            return FALSE;

	    joELI.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	    if(!SetInformationJobObject(ac->hJob, JobObjectExtendedLimitInformation, &joELI, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))) {
            CloseHandle(ac->hJob), ac->hJob = NULL;
            return FALSE;
        }
    }

    { // create child process
        SECURITY_ATTRIBUTES sa = {0};

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

        if (!CreatePipe(&ac->hRead, &ac->hWrite, &sa, BUFSIZ)) {
            CloseHandle(ac->hJob), ac->hJob = NULL;
            return FALSE;
        }

        STARTUPINFO siCon = {0};
        PROCESS_INFORMATION piCon = {0};

        siCon.cb = sizeof(siCon);
        siCon.hStdInput = ac->hRead;
        siCon.dwFlags |= STARTF_USESTDHANDLES;

        if (!CreateProcess(tzClientPath, NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE | CREATE_BREAKAWAY_FROM_JOB | CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &siCon, &piCon)) {
            CloseHandle(ac->hJob), ac->hJob = NULL;
            return FALSE;
        }

        DuplicateHandle(GetCurrentProcess(), piCon.hProcess, GetCurrentProcess(), &ac->hChildProcess, 0, FALSE, DUPLICATE_SAME_ACCESS);
        CloseHandle(piCon.hThread);
        CloseHandle(piCon.hProcess);
    }

    return AssignProcessToJobObject(ac->hJob, ac->hChildProcess);
}
Beispiel #16
0
Datei: Job.cpp Projekt: stden/IJE
void Job::applyRestrictions()
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION limits;
    memset(&limits,0,sizeof limits);
    limits.BasicLimitInformation.LimitFlags =
        JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
        /*
        Not supported by Windows 2000
        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE |
        */
        JOB_OBJECT_LIMIT_PRIORITY_CLASS;
    limits.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
    if (processesLimit) {
        limits.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
        limits.BasicLimitInformation.ActiveProcessLimit = 1;
    }
    if (timeLimit > 0) {
        limits.BasicLimitInformation.LimitFlags |=
            JOB_OBJECT_LIMIT_PROCESS_TIME;
        limits.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart =
            timeLimit;
    }
    if (memoryLimit > 0) {
        limits.BasicLimitInformation.LimitFlags |=
            JOB_OBJECT_LIMIT_PROCESS_MEMORY;
        limits.ProcessMemoryLimit = memoryLimit;
    }
    tryApi(_T("SetInformationJobObject"),
        SetInformationJobObject(hJob,JobObjectExtendedLimitInformation,&limits,sizeof limits) != 0);

    JOBOBJECT_BASIC_UI_RESTRICTIONS ui;
    ui.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP |
        JOB_OBJECT_UILIMIT_DISPLAYSETTINGS |
        JOB_OBJECT_UILIMIT_EXITWINDOWS |
        JOB_OBJECT_UILIMIT_GLOBALATOMS |
        JOB_OBJECT_UILIMIT_HANDLES |
        JOB_OBJECT_UILIMIT_READCLIPBOARD |
        JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS |
        JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
    tryApi(_T("SetInformationJobObject"),
        SetInformationJobObject(hJob,JobObjectBasicUIRestrictions,&ui,sizeof ui) != 0);
}
Beispiel #17
0
void CJobObject::AssignCompletionPort() {
   CMutex::CEnter MutexEnter(m_Mutex);
   BOOL bRet;
   JOBOBJECT_ASSOCIATE_COMPLETION_PORT ObjectInfo;

   m_pCompletionPort = new CJobIoCompletionPort(this, 0, 0, INFINITE);

   ObjectInfo.CompletionKey = 0;
   ObjectInfo.CompletionPort = m_pCompletionPort->GetHandle();
   bRet = SetInformationJobObject(GetHandle(), JobObjectAssociateCompletionPortInformation, 
      &ObjectInfo, sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT));
   if (bRet == 0) {
      throw CCodineException(CError::GetErrorMessage(GetLastError()), __FILE__, __LINE__);
   }

}
HANDLE EngineProcess::mainJob()
{
	QMutexLocker locker(&s_mutex);
	if (s_job)
		return s_job;

	s_job = CreateJobObject(NULL, NULL);
	JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;

	memset(&jeli, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));

	jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	SetInformationJobObject(s_job, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));

	return s_job;
}
int main( int argc , char* argv[] )
{
#if defined(WIN32) && defined(MAX_MEMORY_GB)
    if( MAX_MEMORY_GB>0 )
    {
        SIZE_T peakMemory = 1;
        peakMemory <<= 30;
        peakMemory *= MAX_MEMORY_GB;
        printf( "Limiting memory usage to %.2f GB\n" , float( peakMemory>>30 ) );
        HANDLE h = CreateJobObject( NULL , NULL );
        AssignProcessToJobObject( h , GetCurrentProcess() );

        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
        jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY;
        jeli.JobMemoryLimit = peakMemory;
        if( !SetInformationJobObject( h , JobObjectExtendedLimitInformation , &jeli , sizeof( jeli ) ) )
            fprintf( stderr , "Failed to set memory limit\n" );
    }
Beispiel #20
0
	//--------------------------------------------------------------------------------
	bool CJob::SetUILimitExitWindows( bool bLimit )
	{
		_WINQ_FCONTEXT( "CJob::SetUILimitExitWindows" );
		bool bResult = false;
		__QOR_PROTECT
		{
			sJobObjectBasicUIRestrictions UILimits = GetUILimits();
			if( bLimit )
			{
				UILimits.UIRestrictionsClass |= eJobObjectUILimit_ExitWindows;
			}
			else
			{
				UILimits.UIRestrictionsClass &= (~eJobObjectUILimit_ExitWindows);
			}
			bResult = SetInformationJobObject( JobObjectBasicUIRestrictions, &UILimits, sizeof( sJobObjectBasicUIRestrictions ) ) ? true : false;
		}__QOR_ENDPROTECT
		return bResult;
	}
Beispiel #21
0
void runner::set_allow_breakaway(bool allow) {
    if (allow_breakaway == allow) {
        return;
    }
    if (main_job_object == handle_default_value) {
        main_job_object = CreateJobObject(NULL, NULL);
        AssignProcessToJobObject(main_job_object, GetCurrentProcess());
    }
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION extended_limit_information;
    memset(&extended_limit_information, 0, sizeof(extended_limit_information));
    if (allow) {
        extended_limit_information.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
    }

    if (!SetInformationJobObject(main_job_object, JobObjectExtendedLimitInformation, &extended_limit_information, sizeof(extended_limit_information))) {
        DWORD le = GetLastError();
        return;
    }
    allow_breakaway = allow;
}
Beispiel #22
0
Datei: Job.cpp Projekt: stden/IJE
Job::Job()
{
    millisecondsIdle = 0;
    processesLimit = false;
    timeLimit = 0;
    memoryLimit = 0;
    cpuUsageIdle = 0;
    idlenessLimit = 0;

    std::_stringstream tmp;
    tmp << JOB_OBJECT_NAME;
    tmp << GetTickCount();
    name = tmp.str();
    qualifiedname = JOB_OBJECT_NAMESPACE;
    qualifiedname.append(name);

    hJob = CreateJobObject(NULL,qualifiedname.c_str());
    tryApi(_T("CreateJobObject"), hJob != NULL);
    JOBOBJECT_ASSOCIATE_COMPLETION_PORT portInfo;
    portInfo.CompletionPort = port.handle();
    portInfo.CompletionKey = NULL;
    tryApi(_T("SetInformationJobObject"),
        SetInformationJobObject(hJob,JobObjectAssociateCompletionPortInformation,&portInfo,sizeof portInfo) != 0);

    processTimeCounter = perfQuery.addCounter(
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_JOB_OBJECT),
        _T(""),name,
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_THIS_PERIOD_MSEC_PROCESSOR)
        );
    elapsedTimeCounter = perfQuery.addCounter(
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_SYSTEM),
        _T(""),_T(""),
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_SYSTEM_UPTIME)
        );
    elapsedTimeCounter.setFormatFlags(elapsedTimeCounter.getFormatFlags() | PDH_FMT_1000);
    memoryUsageCounter = perfQuery.addCounter(
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_JOB_OBJECT_DETAILS),
        name,PerformanceQuery::INSTANCE_TOTAL,
        PerformanceQuery::getPerformanceObjectNameByIndex(PerformanceQuery::INDEX_PAGEFILE_BYTES)
        );
}
Beispiel #23
0
static void uv__init_global_job_handle(void) {
  /* Create a job object and set it up to kill all contained processes when
   * it's closed. Since this handle is made non-inheritable and we're not
   * giving it to anyone, we're the only process holding a reference to it.
   * That means that if this process exits it is closed and all the processes
   * it contains are killed. All processes created with uv_spawn that are not
   * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.
   *
   * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the
   * processes that we explicitly add are affected, and *their* subprocesses
   * are not. This ensures that our child processes are not limited in their
   * ability to use job control on Windows versions that don't deal with
   * nested jobs (prior to Windows 8 / Server 2012). It also lets our child
   * processes created detached processes without explicitly breaking away
   * from job control (which uv_spawn doesn't, either).
   */
  SECURITY_ATTRIBUTES attr;
  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;

  memset(&attr, 0, sizeof attr);
  attr.bInheritHandle = FALSE;

  memset(&info, 0, sizeof info);
  info.BasicLimitInformation.LimitFlags =
      JOB_OBJECT_LIMIT_BREAKAWAY_OK |
      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK |
      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION |
      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
  if (uv_global_job_handle_ == NULL)
    uv_fatal_error(GetLastError(), "CreateJobObjectW");

  if (!SetInformationJobObject(uv_global_job_handle_,
                               JobObjectExtendedLimitInformation,
                               &info,
                               sizeof info))
    uv_fatal_error(GetLastError(), "SetInformationJobObject");
}
ActivePet::ActivePet(wchar_t* user_password,
                     std::wstring petname,
                     FileEventLoop* files) : m_petname(petname),
                                             m_files(files),
                                             m_session(INVALID_HANDLE_VALUE),
                                             m_profile(INVALID_HANDLE_VALUE),
                                             m_job(CreateJobObject(NULL, NULL)),
                                             m_next_editable_name(1),
                                             m_ticks_while_invisible(0)
{
    // Create a new logon session for the pet.
    std::wstring petRegistryPath = Constants::registryPets() + L"\\" + m_petname;
	RegKey petkey = RegKey::HKCU.open(petRegistryPath);
	std::wstring accountName = petkey.getValue(L"accountName");
    std::wstring accountRegistryPath = Constants::registryAccounts() + L"\\" + accountName;
	RegKey accountKey = RegKey::HKCU.open(accountRegistryPath);	
	std::wstring password = accountKey.getValue(L"password");
	if (!LogonUser(accountName.c_str(), NULL, password.c_str(),
				   LOGON32_LOGON_INTERACTIVE,
				   LOGON32_PROVIDER_DEFAULT,
				   &m_session)) {
        printf("LogonUser() failed: %d\n", GetLastError());
        return;
	}

    // Tweak the Winsta0 and desktop ACLs to allow the pet to create windows.
    auto_buffer<PSID> logon_sid = GetLogonSID(m_session.get());
    if (NULL == logon_sid.get()) {
        return;
    }
    auto_close<HWINSTA, &::CloseWindowStation> winsta0(OpenWindowStation(L"winsta0", FALSE, READ_CONTROL | WRITE_DAC));
	if (NULL == winsta0.get()) {
        printf("OpenWindowStation() failed: %d\n", GetLastError());
        return;
	}
	if (!AddAceToWindowStation(winsta0.get(), logon_sid.get())) {
        printf("AddAceToWindowStation() failed: %d", GetLastError());
		return;
	}
    auto_close<HDESK, &::CloseDesktop> desktop(OpenDesktop(L"default", 0, FALSE,
                                                           READ_CONTROL | WRITE_DAC |
                                                           DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS));
	if (NULL == desktop.get()) {
        printf("OpenDesktop() failed: %d\n", GetLastError());
		return;
	}
    if (!AddAceToDesktop(desktop.get(), logon_sid.get())) {
        printf("AddAceToDesktop() failed: %d\n", GetLastError());
		return;
	}

    // Load the pet account's registry hive.
    wchar_t account[128] = {};
    wcsncpy(account, accountName.c_str(), 128);
	PROFILEINFO profile = { sizeof(PROFILEINFO), 0, account };
	if (!LoadUserProfile(m_session.get(), &profile)) {
        printf("LoadUserProfile() failed: %d\n", GetLastError());
		return;
	}
    m_profile = profile.hProfile;

    // Initialize the pet job.
	if (NULL == m_job.get()) {
        printf("CreateJobObject() failed: %d\n", GetLastError());
		return;
	}
    JOBOBJECT_BASIC_UI_RESTRICTIONS buir = { JOB_OBJECT_UILIMIT_HANDLES };
	if (!SetInformationJobObject(m_job.get(), JobObjectBasicUIRestrictions, &buir, sizeof buir)) {
        printf("SetInformationJobObject() failed: %d\n", GetLastError());
	}

    // Some apps fail to launch without access to the desktop window.
	if (!UserHandleGrantAccess(GetDesktopWindow(), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}

    // Give apps access to all the standard cursors.
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_ARROW), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_IBEAM), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_WAIT), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_CROSS), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_UPARROW), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZE), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_ICON), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENWSE), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENESW), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZEWE), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZENS), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_SIZEALL), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_NO), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_HAND), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_APPSTARTING), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}
	if (!UserHandleGrantAccess(LoadCursor(NULL, IDC_HELP), m_job.get(), TRUE)) {
        printf("UserHandleGrantAccess() failed: %d\n", GetLastError());
	}

    // Setup the use records for the printers.
    std::set<std::wstring> servers;
    RegKey printers = RegKey::HKCU.open(L"Printers\\Connections");
    for (int i = 0; true; ++i) {
        RegKey printer = printers.getSubKey(i);
        if (!printer.isGood()) {
            break;
        }
        std::wstring server = printer.getValue(L"Server");
        if (servers.count(server) == 0) {

            std::wstring resource = server + L"\\IPC$";
            auto_array<wchar_t> remote(resource.length() + 1);
            lstrcpy(remote.get(), resource.c_str());

            USE_INFO_2 use = {};
            use.ui2_remote = remote.get();
            use.ui2_domainname = _wgetenv(L"USERDOMAIN");
            use.ui2_username = _wgetenv(L"USERNAME");;
            use.ui2_password = user_password;
            use.ui2_asg_type = USE_WILDCARD;

            auto_impersonation impersonate(m_session.get());

            DWORD arg_error;
            NET_API_STATUS error = NetUseAdd(NULL, 2, (BYTE*)&use, &arg_error);
            if (error) {
                printf("NetUseAdd() failed: %d\n", error);
            } else {
                servers.insert(server);
            }
        }
    }

    // Add the message handlers.
    //m_requestFolderPath = accountKey.getValue(Constants::petDataPathName()) + Constants::requestPath();
    m_requestFolderPath = Constants::requestsPath(Constants::polarisDataPath(Constants::userProfilePath(accountName)));
    m_dispatcher = new MessageDispatcher(m_requestFolderPath);
    m_files->watch(m_requestFolderPath, m_dispatcher);
    m_dispatcher->add("sendmail",makeSendMailHandler());
// TODO    m_dispatcher->add("GetOpenFileNameA", makeGetOpenFileNameAHandler(this));
    m_dispatcher->add("GetOpenFileNameW", makeGetOpenFileNameWHandler(this));
	m_dispatcher->add("GetClipboardData", makeGetClipboardDataHandler());
}
Beispiel #25
0
static intptr_t do_spawnv(rktio_t *rktio,
                          const char *command, int argc, const char * const *argv,
			  int exact_cmdline, intptr_t sin, intptr_t sout, intptr_t serr, int *pid,
			  int new_process_group, int chain_termination_here_to_child,
                          void *env, const char *wd)
{
  intptr_t i, l, len = 0;
  int use_jo;
  intptr_t cr_flag;
  char *cmdline;
  wchar_t *cmdline_w, *wd_w, *command_w;
  STARTUPINFOW startup;
  PROCESS_INFORMATION info;

  if (exact_cmdline) {
    cmdline = (char *)argv[1];
  } else {
    for (i = 0; i < argc; i++) {
      len += strlen(argv[i]) + 1;
    }

    cmdline = malloc(len);

    len = 0;
    for (i = 0; i < argc; i++) {
      l = strlen(argv[i]);
      memcpy(cmdline + len, argv[i], l);
      cmdline[len + l] = ' ';
      len += l + 1;
    }
    --len;
    cmdline[len] = 0;
  }

  memset(&startup, 0, sizeof(startup));
  startup.cb = sizeof(startup);
  startup.dwFlags = STARTF_USESTDHANDLES;
  startup.hStdInput = (HANDLE)sin;
  startup.hStdOutput = (HANDLE)sout;
  startup.hStdError = (HANDLE)serr;

  /* If none of the stdio handles are consoles, specifically
     create the subprocess without a console: */
  if (!rktio_system_fd_is_terminal(rktio, (intptr_t)startup.hStdInput)
      && !rktio_system_fd_is_terminal(rktio, (intptr_t)startup.hStdOutput)
      && !rktio_system_fd_is_terminal(rktio, (intptr_t)startup.hStdError))
    cr_flag = CREATE_NO_WINDOW;
  else
    cr_flag = 0;
  if (new_process_group)
    cr_flag |= CREATE_NEW_PROCESS_GROUP;
  cr_flag |= CREATE_UNICODE_ENVIRONMENT;

  use_jo = chain_termination_here_to_child;
  if (use_jo) {
    /* Use a job object to ensure that the new process will be terminated
       if this process ends for any reason (including a crash) */
    if (!rktio->process_job_object) {
      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;

      rktio->process_job_object = CreateJobObject(NULL, NULL);

      memset(&jeli, 0, sizeof(jeli));
      jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
      SetInformationJobObject(rktio->process_job_object,
			      JobObjectExtendedLimitInformation,
			      &jeli,
			      sizeof(jeli));
    }
  }

  
  cmdline_w = WIDE_PATH_copy(cmdline);
  if (!exact_cmdline)
    free(cmdline);
  wd_w = WIDE_PATH_copy(wd);
  command_w = WIDE_PATH_temp(command);

  if (cmdline_w
      && wd_w
      && command_w
      && CreateProcessW(command_w, cmdline_w, 
                        NULL, NULL, 1 /*inherit*/,
                        cr_flag, env, wd_w,
                        &startup, &info)) {
    if (use_jo)
      AssignProcessToJobObject(rktio->process_job_object, info.hProcess);
    CloseHandle(info.hThread);
    *pid = info.dwProcessId;
    free(cmdline_w);
    free(wd_w);
    return (intptr_t)info.hProcess;
  } else {
    if (cmdline_w) free(cmdline_w);
    if (wd_w) free(wd_w);
    return -1;
  }
}
Beispiel #26
0
BOOL Go(const char *commandLine)
{
	HANDLE stdInRead, stdInWrite;

	if (!CreatePipes(&stdInRead, &stdInWrite)) return FALSE;


	PROCESS_INFORMATION piProcInfo; 
	STARTUPINFO siStartInfo;
	BOOL bSuccess = FALSE; 

	
	ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );

	ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
	siStartInfo.cb = sizeof(STARTUPINFO); 
	siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
	siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	siStartInfo.hStdInput = stdInRead;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

	siStartInfo.wShowWindow = SW_HIDE;
	siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
	// Create the child process. 

	if (!CreateProcess(NULL, 
		const_cast<char *>(commandLine),   // command line 
		NULL,          // process security attributes 
		NULL,          // primary thread security attributes 
		TRUE,          // handles are inherited 
		CREATE_BREAKAWAY_FROM_JOB,             // creation flags 
		NULL,          // use parent's environment 
		NULL,          // use parent's current directory 
		&siStartInfo,  // STARTUPINFO pointer 
		&piProcInfo))  // receives PROCESS_INFORMATION 
	{
		return FALSE;
	}

	HANDLE ghJob = CreateJobObject( NULL, NULL);

	JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
	jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
	if( ghJob == NULL || SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)) == FALSE) {
		std::cerr << "Error initializing close-process job";
		return 1;
	}

	if (!AssignProcessToJobObject( ghJob, piProcInfo.hProcess)) {
		DWORD error = GetLastError();
		std::cerr << "AssignProcessToJobObject failed: " << error << std::endl;
		return FALSE;
	}

	// Close handles to the child process and its primary thread.
	// Some applications might keep these handles to monitor the status
	// of the child process, for example. 

	CloseHandle(piProcInfo.hThread);
	MonitorProcessClose(piProcInfo.hProcess);

	WriteToPipe(stdInWrite, piProcInfo.hProcess);
	
	CloseHandle(piProcInfo.hProcess);
	CloseHandle(stdInRead);
	CloseHandle(stdInWrite);


	return 0;
}
Beispiel #27
0
/* Uninstall NSIS */
MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall )
{
	DWORD rv = ERROR_SUCCESS;
	// lookup the NSISUNINSTALL property value
	LPTSTR cNsisUninstall = _T("NSISUNINSTALL");
	HANDLE hIo = NULL;
	DWORD dwSize = 0;
	LPTSTR strPathUninst = NULL;
	HANDLE hJob = NULL;
	STARTUPINFO sInfo;
	PROCESS_INFORMATION pInfo;

	pInfo.hProcess = NULL;
	pInfo.hThread = NULL;

	rv = MsiGetProperty( hInstall, cNsisUninstall, _T(""), &dwSize );
	if(rv != ERROR_MORE_DATA) goto _cleanup;

	strPathUninst = new TCHAR[ ++dwSize ];

	rv = MsiGetProperty( hInstall, cNsisUninstall, strPathUninst, &dwSize );
	if(rv != ERROR_SUCCESS) goto _cleanup;

	// Create a process for the uninstaller
	sInfo.cb = sizeof(sInfo);
	sInfo.lpReserved = NULL;
	sInfo.lpDesktop = _T("");
	sInfo.lpTitle = _T("Foo");
	sInfo.dwX = 0;
	sInfo.dwY = 0;
	sInfo.dwXSize = 0;
	sInfo.dwYSize = 0;
	sInfo.dwXCountChars = 0;
	sInfo.dwYCountChars = 0;
	sInfo.dwFillAttribute = 0;
	sInfo.dwFlags = 0;
	sInfo.wShowWindow = 0;
	sInfo.cbReserved2 = 0;
	sInfo.lpReserved2 = 0;
	sInfo.hStdInput = 0;
	sInfo.hStdOutput = 0;
	sInfo.hStdError = 0;

	if(!CreateProcess( 
		strPathUninst,
		_T("Uninstall /S"),
		NULL,
		NULL,
		FALSE,
		CREATE_SUSPENDED,
		NULL,
		NULL,
		&sInfo,
		&pInfo)) {
			pInfo.hProcess = NULL;
			pInfo.hThread = NULL;
			rv = 40;
			goto _cleanup;
		};

	// Create a job object to contain the NSIS uninstall process tree

	JOBOBJECT_ASSOCIATE_COMPLETION_PORT acp;

	acp.CompletionKey = 0;

	hJob = CreateJobObject(NULL, _T("NSISUninstallObject"));
	if(!hJob) {
		rv = 41;
		goto _cleanup;
	}

	hIo = CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
	if(!hIo) {
		rv = 42;
		goto _cleanup;
	}

	acp.CompletionPort = hIo;

	SetInformationJobObject( hJob, JobObjectAssociateCompletionPortInformation, &acp, sizeof(acp));

	AssignProcessToJobObject( hJob, pInfo.hProcess );

	ResumeThread( pInfo.hThread );

	DWORD a,b,c;
	for(;;) {
		if(!GetQueuedCompletionStatus(hIo, &a, (PULONG_PTR) &b, (LPOVERLAPPED *) &c, INFINITE)) {
			Sleep(1000);
			continue;
		}
		if(a == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
			break;
		}
	}

	rv = ERROR_SUCCESS;
    
_cleanup:
	if(hIo) CloseHandle(hIo);
	if(pInfo.hProcess)	CloseHandle( pInfo.hProcess );
	if(pInfo.hThread) 	CloseHandle( pInfo.hThread );
	if(hJob) CloseHandle(hJob);
	if(strPathUninst) delete[] strPathUninst;

	if(rv != ERROR_SUCCESS) {
        ShowMsiError( hInstall, ERR_NSS_FAILED, rv );
	}
	return rv;
}
bool WindowsJob::setInformation(JOBOBJECTINFOCLASS infoClass,
                                LPVOID lpInfo,
                                DWORD cbInfoLength)
{
    return !!SetInformationJobObject(jobHandle_, infoClass, lpInfo, cbInfoLength);
}
Beispiel #29
0
bool AI::init(int engine)
{
	bool engine_started = false;
	bool b64bit = isOS64Bit();
	bool jobSuccess = false;

	m_engine = engine;
	memset(m_engine_path, 0, sizeof(m_engine_path));

	// set up the security attributes
	m_sa.bInheritHandle = true;
	m_sa.lpSecurityDescriptor = NULL;
	m_sa.nLength = sizeof(SECURITY_ATTRIBUTES);

	// setup job to kill the child process when calling process terminates
	m_hJob = CreateJobObject(NULL, NULL);
	if(m_hJob != NULL){
		m_jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

		jobSuccess = SetInformationJobObject(m_hJob, JobObjectExtendedLimitInformation, &m_jeli, sizeof(m_jeli));
	}

	// open a pipe to the AI engine
	if(!CreatePipe(&m_child_stdin, &m_hWrite, &m_sa, 0)){
		throw std::runtime_error("CreatePipe - stdin");
		return false;
	}

	if(!CreatePipe(&m_hRead, &m_child_stdout, &m_sa, 0)){
		throw std::runtime_error("CreatePipe - stdout");
		cleanup();
		return false;
	}

	// prepare to launch the process
	GetStartupInfo(&m_si);
	m_si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	m_si.wShowWindow = SW_HIDE;
	m_si.hStdOutput = m_child_stdout;
	m_si.hStdError = m_child_stdout;
	m_si.hStdInput = m_child_stdin;

	for(;!engine_started;){
		switch(m_engine){
			case ENGINE_HOUDINI:
				if(b64bit){
					strcpy(m_engine_path, "Data/Engines/Houdini_x64.exe");
					checkProcess("Houdini_x64.exe");
				}
				else{
					strcpy(m_engine_path, "Data/Engines/Houdini_x86.exe");
					checkProcess("Houdini_x86.exe");
				}
				break;

			case ENGINE_STOCKFISH:
				if(b64bit){
					strcpy(m_engine_path, "Data/Engines/Stockfish_x64.exe");
					checkProcess("Stockfish_x64.exe");
				}
				else{
					strcpy(m_engine_path, "Data/Engines/Stockfish_x86.exe");
					checkProcess("Stockfish_x86.exe");
				}
				break;

			case ENGINE_CRITTER:
				if(b64bit){
					strcpy(m_engine_path, "Data/Engines/Critter_x64.exe");
					checkProcess("Critter_x64.exe");
				}
				else{
					strcpy(m_engine_path, "Data/Engines/Critter_x86.exe");
					checkProcess("Critter_x86.exe");
				}
				break;

			case ENGINE_CUSTOM:
				strcpy(m_engine_path, "Data/Engines/Custom.exe");
				break;

			default:
				throw std::runtime_error("No valid engine found");
				cleanup();
				return false;
		}

		// attempt to launch the process
		engine_started =
			CreateProcess(m_engine_path, 
						  NULL,
						  NULL,
						  NULL,
						  TRUE,
						  0,
						  NULL,
						  NULL,
						  &m_si,
						  &m_pi);

		if(!engine_started){
			if(engine > 0)
				engine = 0;
			else
				++engine;

			continue;
		}

		break;
	}

	// assign the job to the process
	if(jobSuccess){
		jobSuccess = AssignProcessToJobObject(m_hJob, m_pi.hProcess);
	}

	// change states
	//m_active = true;
	//m_thinking = true;
	
	// set process priority to below normal to prevent destruction of the CPU
	SetPriorityClass(m_pi.hProcess, BELOW_NORMAL_PRIORITY_CLASS);

	// set AI to active
	if(engine_started){
		m_active = true;

		// start the state machine thread
		(void)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&InitThread, this, 0, 0);
	}

	return true;
}
Beispiel #30
0
int main(int argc, char** argv) {
	enum {
		 envbufsize = 1024*32
		,exebufsize = 1024
		,cmdbufsize = envbufsize
	};

	char *envbuf, *sep, *resbuf, *cmdbuf;
	DWORD len, exitCode;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	DIE_IF_FALSE(
		(envbuf = malloc(envbufsize))
	);
	DIE_IF_FALSE(
		(cmdbuf = malloc(cmdbufsize))
	);
	*cmdbuf = 0;

	DIE_IF_FALSE(
		GetEnvironmentVariable("PATH", envbuf, envbufsize)
	);
    dbg_printf("env: %s\n", envbuf);

	DIE_IF_FALSE(
		GetModuleFileName(0, cmdbuf, exebufsize)
	);
    dbg_printf("curdir: %s\n", cmdbuf);

	DIE_IF_FALSE(
		(sep = strrchr(cmdbuf, '\\'))
	);
	*(sep+1) = 0;
	strcat(cmdbuf, GDB_TO_PYTHON_REL_DIR);
	dbg_printf("sep: %s\n", cmdbuf);

	len = strlen(envbuf)+strlen(cmdbuf)
		+1  /* for envronment separator */
		+1; /* for zero-terminator */
	
	DIE_IF_FALSE(
		(resbuf = malloc(len))
	);

	DIE_IF_FALSE(
		(snprintf(resbuf, len, "%s;%s", cmdbuf, envbuf) > 0)
	);
    dbg_printf("PATH: %s\n", resbuf);

	DIE_IF_FALSE(
		SetEnvironmentVariable("PATH", resbuf)
	);

	*(sep+1) = 0;
	strcat(cmdbuf, PYTHONHOME_REL_DIR);
	dbg_printf("PYTHONHOME: %s\n", cmdbuf);
	DIE_IF_FALSE(
		SetEnvironmentVariable("PYTHONHOME", cmdbuf)
	);
	
	*(sep+1) = 0;
	strcat(cmdbuf, GDB_EXECUTABLE_ORIG_FILENAME" ");
	
	if ( argc > 1 ) {
		for ( ++argv; *argv; ++argv ) {
			len = strlen(cmdbuf);
			snprintf(cmdbuf+len, cmdbufsize-len, "%s ", *argv);
		}
	}
	dbg_printf("cmd: %s\n", cmdbuf);

	HANDLE ghJob = CreateJobObject(NULL, "Gdb-Wrapper\0"/*NULL*/);
	if ( ghJob == NULL ) {
		dbg_printf("Could not create job object\n");
	} else {
		JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
		// Configure all child processes associated with the job to terminate when the last handle to the job is closed
		jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
		if ( SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)) == 0 ) {
			dbg_printf("Could not SetInformationJobObject\n");
		}
	}

	memset(&si, 0, sizeof(si));
	si.cb = sizeof(si);
	si.dwFlags |= STARTF_USESTDHANDLES;
	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
	si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	si.hStdError = GetStdHandle(STD_ERROR_HANDLE);

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

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

	if ( ghJob != NULL && AssignProcessToJobObject(ghJob, pi.hProcess) == 0 ) {
		dbg_printf("Could not AssignProcessToObject\n");
	}

	// Do not handle Ctrl-C in the wrapper
	SetConsoleCtrlHandler(NULL, TRUE);

	WaitForSingleObject(pi.hProcess, INFINITE);
	
	DIE_IF_FALSE(
		GetExitCodeProcess(pi.hProcess, &exitCode)
	);

	if ( ghJob != NULL )
		CloseHandle(ghJob);
	CloseHandle( pi.hProcess );
	CloseHandle( pi.hThread );

	free(envbuf);
	free(resbuf);
	free(cmdbuf);
	
	dbg_printf("exiting with exitCode %d", exitCode);

	return exitCode;
}