VirtualBox

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

Last change on this file since 16684 was 13837, checked in by vboxsync, 16 years ago

s/%Vr\([acfs]\)/%Rr\1/g - since I'm upsetting everyone anyway, better make the most of it...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1/* $Id: process-win.cpp 13837 2008-11-05 02:54:02Z 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 /* later: path searching. */
97
98 /*
99 * Spawn the child.
100 */
101 /** @todo utf-8 considerations! */
102 HANDLE hProcess = (HANDLE)_spawnve(_P_NOWAITO, pszExec, papszArgs, papszEnv);
103 if (hProcess != 0 && hProcess != INVALID_HANDLE_VALUE)
104 {
105 if (pProcess)
106 {
107 /*
108 * GetProcessId requires XP SP1 or later
109 */
110#if defined(RT_ARCH_AMD64)
111 *pProcess = GetProcessId(hProcess);
112#else /* !RT_ARCH_AMD64 */
113 static bool fInitialized = false;
114 static DWORD (WINAPI *pfnGetProcessId)(HANDLE Thread) = NULL;
115 if (!fInitialized)
116 {
117 HMODULE hmodKernel32 = GetModuleHandle("KERNEL32.DLL");
118 if (hmodKernel32)
119 pfnGetProcessId = (DWORD (WINAPI*)(HANDLE))GetProcAddress(hmodKernel32, "GetProcessId");
120 fInitialized = true;
121 }
122 if (pfnGetProcessId)
123 {
124 *pProcess = pfnGetProcessId(hProcess);
125 if (!*pProcess)
126 {
127 int rc = RTErrConvertFromWin32(GetLastError());
128 AssertMsgFailed(("failed to get pid from hProcess=%#x rc=%Rrc\n", hProcess, rc));
129 return rc;
130 }
131 }
132 else
133 {
134 /*
135 * Fall back to the NT api for older versions.
136 */
137 PROCESS_BASIC_INFORMATION ProcInfo = {0};
138 ULONG Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation,
139 &ProcInfo, sizeof(ProcInfo), NULL);
140 if (Status != 0)
141 {
142 int rc = ERROR_INTERNAL_ERROR; /* (we don't have a valid conversion here, but this shouldn't happen anyway.) */
143 AssertMsgFailed(("failed to get pid from hProcess=%#x rc=%Rrc Status=%#x\n", hProcess, rc, Status));
144 return rc;
145 }
146 *pProcess = ProcInfo.UniqueProcessId;
147 }
148#endif /* !RT_ARCH_AMD64 */
149 }
150 return VINF_SUCCESS;
151 }
152
153 int rc = RTErrConvertFromErrno(errno);
154 AssertMsgFailed(("spawn/exec failed rc=%Rrc\n", rc)); /* this migth be annoying... */
155 return rc;
156}
157
158
159RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
160{
161 AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER);
162
163 /*
164 * Open the process.
165 */
166 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Process);
167 if (hProcess != NULL)
168 {
169 /*
170 * Wait for it to terminate.
171 */
172 DWORD Millies = fFlags == RTPROCWAIT_FLAGS_BLOCK ? INFINITE : 0;
173 DWORD WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
174 while (WaitRc == WAIT_IO_COMPLETION)
175 WaitRc = WaitForSingleObjectEx(hProcess, Millies, TRUE);
176 switch (WaitRc)
177 {
178 /*
179 * It has terminated.
180 */
181 case WAIT_OBJECT_0:
182 {
183 DWORD dwExitCode;
184 if (GetExitCodeProcess(hProcess, &dwExitCode))
185 {
186 if (pProcStatus)
187 {
188 pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
189 pProcStatus->iStatus = (int)dwExitCode;
190 }
191 return VINF_SUCCESS;
192 }
193 break;
194 }
195
196 /*
197 * It hasn't terminated just yet.
198 */
199 case WAIT_TIMEOUT:
200 return VERR_PROCESS_RUNNING;
201
202 /*
203 * Something went wrong...
204 */
205 case WAIT_FAILED:
206 break;
207 case WAIT_ABANDONED:
208 AssertFailed();
209 return VERR_GENERAL_FAILURE;
210 default:
211 AssertMsgFailed(("WaitRc=%RU32\n", WaitRc));
212 return VERR_GENERAL_FAILURE;
213 }
214 }
215 DWORD dwErr = GetLastError();
216 return RTErrConvertFromWin32(dwErr);
217}
218
219
220RTR3DECL(int) RTProcTerminate(RTPROCESS Process)
221{
222 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, Process);
223 if (hProcess != NULL)
224 {
225 BOOL fRc = TerminateProcess(hProcess, 127);
226 CloseHandle(hProcess);
227 if (fRc)
228 return VINF_SUCCESS;
229 }
230 DWORD dwErr = GetLastError();
231 return RTErrConvertFromWin32(dwErr);
232}
233
234
235RTR3DECL(uint64_t) RTProcGetAffinityMask(void)
236{
237 DWORD_PTR dwProcessAffinityMask = 0xffffffff;
238 DWORD_PTR dwSystemAffinityMask;
239
240 BOOL fRc = GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
241 Assert(fRc);
242
243 return dwProcessAffinityMask;
244}
245
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