VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win32/process-win32.cpp@ 5285

Last change on this file since 5285 was 4475, checked in by vboxsync, 17 years ago

Some adjustments to RTEnv and RTProcCreate. Should work on darwin now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1/* $Id: process-win32.cpp 4475 2007-09-01 01:21:19Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Process, Win32.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP RTLOGGROUP_PROCESS
23
24#include <Windows.h>
25#include <process.h>
26#include <errno.h>
27
28#include <iprt/process.h>
29#include <iprt/assert.h>
30#include <iprt/err.h>
31#include <iprt/env.h>
32
33
34/*
35 * This is from Winternl.h. It has been copied here
36 * because the header does not define a calling convention for
37 * its prototypes and just assumes that _stdcall is the standard
38 * calling convention.
39 */
40typedef struct _PEB {
41 BYTE Reserved1[2];
42 BYTE BeingDebugged;
43 BYTE Reserved2[229];
44 PVOID Reserved3[59];
45 ULONG SessionId;
46} PEB, *PPEB;
47
48typedef struct _PROCESS_BASIC_INFORMATION {
49 PVOID Reserved1;
50 PPEB PebBaseAddress;
51 PVOID Reserved2[2];
52 ULONG_PTR UniqueProcessId;
53 PVOID Reserved3;
54} PROCESS_BASIC_INFORMATION;
55
56typedef enum _PROCESSINFOCLASS {
57 ProcessBasicInformation = 0,
58 ProcessWow64Information = 26
59} PROCESSINFOCLASS;
60
61extern "C" LONG WINAPI
62NtQueryInformationProcess (
63 IN HANDLE ProcessHandle,
64 IN PROCESSINFOCLASS ProcessInformationClass,
65 OUT PVOID ProcessInformation,
66 IN ULONG ProcessInformationLength,
67 OUT PULONG ReturnLength OPTIONAL
68 );
69
70/** @todo r=michael This function currently does not work correctly if the arguments
71 contain spaces. */
72RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
73{
74 /*
75 * Validate input.
76 */
77 AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
78 AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
79 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
80 AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER);
81 const char * const *papszEnv = RTEnvGetExecEnvP(Env);
82 AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
83 /* later: path searching. */
84
85 /*
86 * Spawn the child.
87 */
88 /** @todo utf-8 considerations! */
89 HANDLE hProcess = (HANDLE)_spawnve(_P_NOWAITO, pszExec, papszArgs, papszEnv);
90 if (hProcess != 0 && hProcess != INVALID_HANDLE_VALUE)
91 {
92 if (pProcess)
93 {
94 /*
95 * GetProcessId requires XP SP1 or later
96 */
97#if defined(RT_ARCH_AMD64)
98 *pProcess = GetProcessId(hProcess);
99#else /* !RT_ARCH_AMD64 */
100 static bool fInitialized = false;
101 static DWORD (WINAPI *pfnGetProcessId)(HANDLE Thread) = NULL;
102 if (!fInitialized)
103 {
104 HMODULE hmodKernel32 = GetModuleHandle("KERNEL32.DLL");
105 if (hmodKernel32)
106 pfnGetProcessId = (DWORD (WINAPI*)(HANDLE))GetProcAddress(hmodKernel32, "GetProcessId");
107 fInitialized = true;
108 }
109 if (pfnGetProcessId)
110 {
111 *pProcess = pfnGetProcessId(hProcess);
112 if (!*pProcess)
113 {
114 int rc = RTErrConvertFromWin32(GetLastError());
115 AssertMsgFailed(("failed to get pid from hProcess=%#x rc=%Vrc\n", hProcess, rc));
116 return rc;
117 }
118 }
119 else
120 {
121 /*
122 * Fall back to the NT api for older versions.
123 */
124 PROCESS_BASIC_INFORMATION ProcInfo = {0};
125 ULONG Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
126 &ProcInfo, sizeof(ProcInfo), NULL);
127 if (Status != 0)
128 {
129 int rc = ERROR_INTERNAL_ERROR; /* (we don't have a valid conversion here, but this shouldn't happen anyway.) */
130 AssertMsgFailed(("failed to get pid from hProcess=%#x rc=%Vrc Status=%#x\n", hProcess, rc, Status));
131 return rc;
132 }
133 *pProcess = ProcInfo.UniqueProcessId;
134 }
135#endif /* !RT_ARCH_AMD64 */
136 }
137 return VINF_SUCCESS;
138 }
139
140 int rc = RTErrConvertFromErrno(errno);
141 AssertMsgFailed(("spawn/exec failed rc=%Vrc\n", rc)); /* this migth be annoying... */
142 return rc;
143}
144
145
146RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
147{
148 AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
149
150 /*
151 * Open the process.
152 */
153 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Process);
154 if (hProcess != NULL)
155 {
156 /*
157 * Wait for it to terminate.
158 */
159 DWORD Millies = fFlags == RTPROCWAIT_FLAGS_BLOCK ? INFINITE : 0;
160 DWORD WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
161 while (WaitRc == WAIT_IO_COMPLETION)
162 WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
163 switch (WaitRc)
164 {
165 /*
166 * It has terminated.
167 */
168 case WAIT_OBJECT_0:
169 {
170 DWORD dwExitCode;
171 if (GetExitCodeProcess(hProcess, &dwExitCode))
172 {
173 if (pProcStatus)
174 {
175 pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
176 pProcStatus->iStatus = (int)dwExitCode;
177 }
178 return VINF_SUCCESS;
179 }
180 break;
181 }
182
183 /*
184 * It hasn't terminated just yet.
185 */
186 case WAIT_TIMEOUT:
187 return VERR_PROCESS_RUNNING;
188
189 /*
190 * Something went wrong...
191 */
192 case WAIT_FAILED:
193 break;
194 case WAIT_ABANDONED:
195 AssertFailed();
196 return VERR_GENERAL_FAILURE;
197 default:
198 AssertMsgFailed(("WaitRc=%RU32\n", WaitRc));
199 return VERR_GENERAL_FAILURE;
200 }
201 }
202 DWORD dwErr = GetLastError();
203 return RTErrConvertFromWin32(dwErr);
204}
205
206
207RTR3DECL(int) RTProcTerminate(RTPROCESS Process)
208{
209 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, Process);
210 if (hProcess != NULL)
211 {
212 BOOL fRc = TerminateProcess(hProcess, 127);
213 CloseHandle(hProcess);
214 if (fRc)
215 return VINF_SUCCESS;
216 }
217 DWORD dwErr = GetLastError();
218 return RTErrConvertFromWin32(dwErr);
219}
220
221
222RTR3DECL(uint64_t) RTProcGetAffinityMask(void)
223{
224 DWORD_PTR dwProcessAffinityMask = 0xffffffff;
225 DWORD_PTR dwSystemAffinityMask;
226
227 BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
228 Assert(fRc);
229
230 return dwProcessAffinityMask;
231}
232
233
234RTR3DECL(char *) RTProcGetExecutableName(char *pszExecName, size_t cchExecName)
235{
236 HMODULE hExe = GetModuleHandle(NULL);
237 if (GetModuleFileName(hExe, pszExecName, cchExecName))
238 return pszExecName;
239 return NULL;
240}
241
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette