VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/process-win.cpp@ 25240

Last change on this file since 25240 was 22497, checked in by vboxsync, 15 years ago

Spaces.

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