VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/win/SUPLib-win.cpp@ 46861

Last change on this file since 46861 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.5 KB
Line 
1/* $Id: SUPLib-win.cpp 44528 2013-02-04 14:27:54Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Windows NT specific parts.
4 */
5
6/*
7 * Copyright (C) 2006-2012 Oracle Corporation
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
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#define LOG_GROUP LOG_GROUP_SUP
31#ifdef IN_SUP_HARDENED_R3
32# undef DEBUG /* Warning: disables RT_STRICT */
33# define LOG_DISABLED
34 /** @todo RTLOGREL_DISABLED */
35# include <iprt/log.h>
36# undef LogRelIt
37# define LogRelIt(pvInst, fFlags, iGroup, fmtargs) do { } while (0)
38#endif
39
40#include <Windows.h>
41
42#include <VBox/sup.h>
43#include <VBox/types.h>
44#include <VBox/err.h>
45#include <VBox/param.h>
46#include <VBox/log.h>
47#include <iprt/assert.h>
48#include <iprt/path.h>
49#include <iprt/string.h>
50#include "../SUPLibInternal.h"
51#include "../SUPDrvIOC.h"
52
53
54/*******************************************************************************
55* Defined Constants And Macros *
56*******************************************************************************/
57/** The support service name. */
58#define SERVICE_NAME "VBoxDrv"
59/** Win32 Device name - system. */
60#define DEVICE_NAME_SYS "\\\\.\\VBoxDrv"
61/** Win32 Device name - user. */
62#define DEVICE_NAME_USR "\\\\.\\VBoxDrvU"
63/** NT Device name. */
64#define DEVICE_NAME_NT L"\\Device\\VBoxDrv"
65/** Win32 Symlink name. */
66#define DEVICE_NAME_DOS L"\\DosDevices\\VBoxDrv"
67
68
69/*******************************************************************************
70* Internal Functions *
71*******************************************************************************/
72static int suplibOsCreateService(void);
73//unused: static int suplibOsUpdateService(void);
74static int suplibOsDeleteService(void);
75static int suplibOsStartService(void);
76static int suplibOsStopService(void);
77static int suplibConvertWin32Err(int);
78
79
80
81
82int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted)
83{
84 /*
85 * Nothing to do if pre-inited.
86 */
87 if (fPreInited)
88 return VINF_SUCCESS;
89
90 /*
91 * Try open the device.
92 */
93 HANDLE hDevice = CreateFile(fUnrestricted ? DEVICE_NAME_SYS : DEVICE_NAME_USR,
94 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
95 NULL,
96 OPEN_EXISTING,
97 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
98 NULL);
99 if (hDevice == INVALID_HANDLE_VALUE)
100 {
101#ifndef IN_SUP_HARDENED_R3
102 /*
103 * Try start the service and retry opening it.
104 */
105 suplibOsStartService();
106
107 hDevice = CreateFile(fUnrestricted ? DEVICE_NAME_SYS : DEVICE_NAME_USR,
108 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
109 NULL,
110 OPEN_EXISTING,
111 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
112 NULL);
113 if (hDevice == INVALID_HANDLE_VALUE)
114#endif /* !IN_SUP_HARDENED_R3 */
115 {
116 int rc = GetLastError();
117 switch (rc)
118 {
119 /** @todo someone must test what is actually returned. */
120 case ERROR_DEV_NOT_EXIST:
121 case ERROR_DEVICE_NOT_CONNECTED:
122 case ERROR_BAD_DEVICE:
123 case ERROR_DEVICE_REMOVED:
124 case ERROR_DEVICE_NOT_AVAILABLE:
125 return VERR_VM_DRIVER_LOAD_ERROR;
126 case ERROR_PATH_NOT_FOUND:
127 case ERROR_FILE_NOT_FOUND:
128 return VERR_VM_DRIVER_NOT_INSTALLED;
129 case ERROR_ACCESS_DENIED:
130 case ERROR_SHARING_VIOLATION:
131 return VERR_VM_DRIVER_NOT_ACCESSIBLE;
132 default:
133 return VERR_VM_DRIVER_OPEN_ERROR;
134 }
135
136 return -1 /** @todo define proper error codes for suplibOsInit failure. */;
137 }
138 }
139
140 /*
141 * We're done.
142 */
143 pThis->hDevice = hDevice;
144 pThis->fUnrestricted = fUnrestricted;
145 return VINF_SUCCESS;
146}
147
148
149#ifndef IN_SUP_HARDENED_R3
150
151int suplibOsInstall(void)
152{
153 return suplibOsCreateService();
154}
155
156
157int suplibOsUninstall(void)
158{
159 int rc = suplibOsStopService();
160 if (!rc)
161 rc = suplibOsDeleteService();
162 return rc;
163}
164
165
166/**
167 * Creates the service.
168 *
169 * @returns 0 on success.
170 * @returns -1 on failure.
171 */
172static int suplibOsCreateService(void)
173{
174 /*
175 * Assume it didn't exist, so we'll create the service.
176 */
177 SC_HANDLE hSMgrCreate = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
178 DWORD LastError = GetLastError(); NOREF(LastError);
179 AssertMsg(hSMgrCreate, ("OpenSCManager(,,create) failed rc=%d\n", LastError));
180 if (hSMgrCreate)
181 {
182 char szDriver[RTPATH_MAX];
183 int rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
184 if (RT_SUCCESS(rc))
185 {
186 strcat(szDriver, "\\VBoxDrv.sys");
187 SC_HANDLE hService = CreateService(hSMgrCreate,
188 SERVICE_NAME,
189 "VBox Support Driver",
190 SERVICE_QUERY_STATUS,
191 SERVICE_KERNEL_DRIVER,
192 SERVICE_DEMAND_START,
193 SERVICE_ERROR_NORMAL,
194 szDriver,
195 NULL, NULL, NULL, NULL, NULL);
196 DWORD LastError = GetLastError(); NOREF(LastError);
197 AssertMsg(hService, ("CreateService failed! LastError=%Rwa szDriver=%s\n", LastError, szDriver));
198 CloseServiceHandle(hService);
199 CloseServiceHandle(hSMgrCreate);
200 return hService ? 0 : -1;
201 }
202 CloseServiceHandle(hSMgrCreate);
203 return rc;
204 }
205 return -1;
206}
207
208
209/**
210 * Stops a possibly running service.
211 *
212 * @returns 0 on success.
213 * @returns -1 on failure.
214 */
215static int suplibOsStopService(void)
216{
217 /*
218 * Assume it didn't exist, so we'll create the service.
219 */
220 int rc = -1;
221 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_STOP | SERVICE_QUERY_STATUS);
222 DWORD LastError = GetLastError(); NOREF(LastError);
223 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", LastError));
224 if (hSMgr)
225 {
226 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS);
227 if (hService)
228 {
229 /*
230 * Stop the service.
231 */
232 SERVICE_STATUS Status;
233 QueryServiceStatus(hService, &Status);
234 if (Status.dwCurrentState == SERVICE_STOPPED)
235 rc = 0;
236 else if (ControlService(hService, SERVICE_CONTROL_STOP, &Status))
237 {
238 int iWait = 100;
239 while (Status.dwCurrentState == SERVICE_STOP_PENDING && iWait-- > 0)
240 {
241 Sleep(100);
242 QueryServiceStatus(hService, &Status);
243 }
244 if (Status.dwCurrentState == SERVICE_STOPPED)
245 rc = 0;
246 else
247 AssertMsgFailed(("Failed to stop service. status=%d\n", Status.dwCurrentState));
248 }
249 else
250 {
251 DWORD LastError = GetLastError(); NOREF(LastError);
252 AssertMsgFailed(("ControlService failed with LastError=%Rwa. status=%d\n", LastError, Status.dwCurrentState));
253 }
254 CloseServiceHandle(hService);
255 }
256 else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
257 rc = 0;
258 else
259 {
260 DWORD LastError = GetLastError(); NOREF(LastError);
261 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
262 }
263 CloseServiceHandle(hSMgr);
264 }
265 return rc;
266}
267
268
269/**
270 * Deletes the service.
271 *
272 * @returns 0 on success.
273 * @returns -1 on failure.
274 */
275int suplibOsDeleteService(void)
276{
277 /*
278 * Assume it didn't exist, so we'll create the service.
279 */
280 int rc = -1;
281 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
282 DWORD LastError = GetLastError(); NOREF(LastError);
283 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", LastError));
284 if (hSMgr)
285 {
286 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, DELETE);
287 if (hService)
288 {
289 /*
290 * Delete the service.
291 */
292 if (DeleteService(hService))
293 rc = 0;
294 else
295 {
296 DWORD LastError = GetLastError(); NOREF(LastError);
297 AssertMsgFailed(("DeleteService failed LastError=%Rwa\n", LastError));
298 }
299 CloseServiceHandle(hService);
300 }
301 else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
302 rc = 0;
303 else
304 {
305 DWORD LastError = GetLastError(); NOREF(LastError);
306 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
307 }
308 CloseServiceHandle(hSMgr);
309 }
310 return rc;
311}
312
313#if 0
314/**
315 * Creates the service.
316 *
317 * @returns 0 on success.
318 * @returns -1 on failure.
319 */
320static int suplibOsUpdateService(void)
321{
322 /*
323 * Assume it didn't exist, so we'll create the service.
324 */
325 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
326 DWORD LastError = GetLastError(); NOREF(LastError);
327 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed LastError=%Rwa\n", LastError));
328 if (hSMgr)
329 {
330 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_CHANGE_CONFIG);
331 if (hService)
332 {
333 char szDriver[RTPATH_MAX];
334 int rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
335 if (RT_SUCCESS(rc))
336 {
337 strcat(szDriver, "\\VBoxDrv.sys");
338
339 SC_LOCK hLock = LockServiceDatabase(hSMgr);
340 if (ChangeServiceConfig(hService,
341 SERVICE_KERNEL_DRIVER,
342 SERVICE_DEMAND_START,
343 SERVICE_ERROR_NORMAL,
344 szDriver,
345 NULL, NULL, NULL, NULL, NULL, NULL))
346 {
347
348 UnlockServiceDatabase(hLock);
349 CloseServiceHandle(hService);
350 CloseServiceHandle(hSMgr);
351 return 0;
352 }
353 else
354 {
355 DWORD LastError = GetLastError(); NOREF(LastError);
356 AssertMsgFailed(("ChangeServiceConfig failed LastError=%Rwa\n", LastError));
357 }
358 }
359 UnlockServiceDatabase(hLock);
360 CloseServiceHandle(hService);
361 }
362 else
363 {
364 DWORD LastError = GetLastError(); NOREF(LastError);
365 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
366 }
367 CloseServiceHandle(hSMgr);
368 }
369 return -1;
370}
371#endif
372
373
374/**
375 * Attempts to start the service, creating it if necessary.
376 *
377 * @returns 0 on success.
378 * @returns -1 on failure.
379 * @param fRetry Indicates retry call.
380 */
381static int suplibOsStartService(void)
382{
383 /*
384 * Check if the driver service is there.
385 */
386 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
387 if (hSMgr == NULL)
388 {
389 AssertMsgFailed(("couldn't open service manager in SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS mode!\n"));
390 return -1;
391 }
392
393 /*
394 * Try open our service to check it's status.
395 */
396 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
397 if (!hService)
398 {
399 /*
400 * Create the service.
401 */
402 int rc = suplibOsCreateService();
403 if (rc)
404 return rc;
405
406 /*
407 * Try open the service.
408 */
409 hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
410 }
411
412 /*
413 * Check if open and on demand create succeeded.
414 */
415 int rc = -1;
416 if (hService)
417 {
418
419 /*
420 * Query service status to see if we need to start it or not.
421 */
422 SERVICE_STATUS Status;
423 BOOL fRc = QueryServiceStatus(hService, &Status);
424 Assert(fRc);
425 if ( Status.dwCurrentState != SERVICE_RUNNING
426 && Status.dwCurrentState != SERVICE_START_PENDING)
427 {
428 /*
429 * Start it.
430 */
431 fRc = StartService(hService, 0, NULL);
432 DWORD LastError = GetLastError(); NOREF(LastError);
433 AssertMsg(fRc, ("StartService failed with LastError=%Rwa\n", LastError));
434 }
435
436 /*
437 * Wait for the service to finish starting.
438 * We'll wait for 10 seconds then we'll give up.
439 */
440 QueryServiceStatus(hService, &Status);
441 if (Status.dwCurrentState == SERVICE_START_PENDING)
442 {
443 int iWait;
444 for (iWait = 100; iWait > 0 && Status.dwCurrentState == SERVICE_START_PENDING; iWait--)
445 {
446 Sleep(100);
447 QueryServiceStatus(hService, &Status);
448 }
449 DWORD LastError = GetLastError(); NOREF(LastError);
450 AssertMsg(Status.dwCurrentState != SERVICE_RUNNING,
451 ("Failed to start. LastError=%Rwa iWait=%d status=%d\n",
452 LastError, iWait, Status.dwCurrentState));
453 }
454
455 if (Status.dwCurrentState == SERVICE_RUNNING)
456 rc = 0;
457
458 /*
459 * Close open handles.
460 */
461 CloseServiceHandle(hService);
462 }
463 else
464 {
465 DWORD LastError = GetLastError(); NOREF(LastError);
466 AssertMsgFailed(("OpenService failed! LastError=%Rwa\n", LastError));
467 }
468 if (!CloseServiceHandle(hSMgr))
469 AssertFailed();
470
471 return rc;
472}
473
474
475int suplibOsTerm(PSUPLIBDATA pThis)
476{
477 /*
478 * Check if we're inited at all.
479 */
480 if (pThis->hDevice != NULL)
481 {
482 if (!CloseHandle((HANDLE)pThis->hDevice))
483 AssertFailed();
484 pThis->hDevice = NIL_RTFILE; /* yes, that's right */
485 }
486
487 return VINF_SUCCESS;
488}
489
490
491int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq)
492{
493 /*
494 * Issue the device I/O control.
495 */
496 PSUPREQHDR pHdr = (PSUPREQHDR)pvReq;
497 Assert(cbReq == RT_MAX(pHdr->cbIn, pHdr->cbOut));
498 DWORD cbReturned = (ULONG)pHdr->cbOut;
499 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, pvReq, pHdr->cbIn, pvReq, cbReturned, &cbReturned, NULL))
500 return 0;
501 return suplibConvertWin32Err(GetLastError());
502}
503
504
505int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu)
506{
507 /*
508 * Issue device I/O control.
509 */
510 DWORD cbReturned = 0;
511 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, NULL, 0, (LPVOID)idCpu, 0, &cbReturned, NULL))
512 return VINF_SUCCESS;
513 return suplibConvertWin32Err(GetLastError());
514}
515
516
517int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages)
518{
519 NOREF(pThis);
520 *ppvPages = VirtualAlloc(NULL, (size_t)cPages << PAGE_SHIFT, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
521 if (*ppvPages)
522 return VINF_SUCCESS;
523 return suplibConvertWin32Err(GetLastError());
524}
525
526
527int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t /* cPages */)
528{
529 NOREF(pThis);
530 if (VirtualFree(pvPages, 0, MEM_RELEASE))
531 return VINF_SUCCESS;
532 return suplibConvertWin32Err(GetLastError());
533}
534
535
536/**
537 * Converts a supdrv win32 error code to an IPRT status code.
538 *
539 * @returns corresponding IPRT error code.
540 * @param rc Win32 error code.
541 */
542static int suplibConvertWin32Err(int rc)
543{
544 /* Conversion program (link with ntdll.lib from ddk):
545 #define _WIN32_WINNT 0x0501
546 #include <windows.h>
547 #include <ntstatus.h>
548 #include <winternl.h>
549 #include <stdio.h>
550
551 int main()
552 {
553 #define CONVERT(a) printf(#a " %#x -> %d\n", a, RtlNtStatusToDosError((a)))
554 CONVERT(STATUS_SUCCESS);
555 CONVERT(STATUS_NOT_SUPPORTED);
556 CONVERT(STATUS_INVALID_PARAMETER);
557 CONVERT(STATUS_UNKNOWN_REVISION);
558 CONVERT(STATUS_INVALID_HANDLE);
559 CONVERT(STATUS_INVALID_ADDRESS);
560 CONVERT(STATUS_NOT_LOCKED);
561 CONVERT(STATUS_IMAGE_ALREADY_LOADED);
562 CONVERT(STATUS_ACCESS_DENIED);
563 CONVERT(STATUS_REVISION_MISMATCH);
564
565 return 0;
566 }
567 */
568
569 switch (rc)
570 {
571 //case 0: return STATUS_SUCCESS;
572 case 0: return VINF_SUCCESS;
573 case ERROR_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
574 case ERROR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
575 case ERROR_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
576 case ERROR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
577 case ERROR_UNEXP_NET_ERR: return VERR_INVALID_POINTER;
578 case ERROR_NOT_LOCKED: return VERR_LOCK_FAILED;
579 case ERROR_SERVICE_ALREADY_RUNNING: return VERR_ALREADY_LOADED;
580 case ERROR_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
581 case ERROR_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
582 }
583
584 /* fall back on the default conversion. */
585 return RTErrConvertFromWin32(rc);
586}
587
588#endif /* !IN_SUP_HARDENED_R3 */
589
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