VirtualBox

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

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

Biggest check-in ever. New source code headers for all (C) innotek files.

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