VirtualBox

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

Last change on this file since 78351 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.2 KB
Line 
1/* $Id: SUPLib-win.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Windows NT specific parts.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP LOG_GROUP_SUP
32#ifdef IN_SUP_HARDENED_R3
33# undef DEBUG /* Warning: disables RT_STRICT */
34# undef LOG_DISABLED
35# define LOG_DISABLED
36 /** @todo RTLOGREL_DISABLED */
37# include <iprt/log.h>
38# undef LogRelIt
39# define LogRelIt(pvInst, fFlags, iGroup, fmtargs) do { } while (0)
40#endif
41
42#define USE_NT_DEVICE_IO_CONTROL_FILE
43#include <iprt/nt/nt-and-windows.h>
44
45#include <VBox/sup.h>
46#include <VBox/types.h>
47#include <VBox/err.h>
48#include <VBox/param.h>
49#include <VBox/log.h>
50#include <iprt/assert.h>
51#ifndef IN_SUP_HARDENED_R3
52# include <iprt/x86.h>
53# include <iprt/ldr.h>
54#endif
55#include <iprt/path.h>
56#include <iprt/string.h>
57#include "../SUPLibInternal.h"
58#include "../SUPDrvIOC.h"
59#ifdef VBOX_WITH_HARDENING
60# include "win/SUPHardenedVerify-win.h"
61#endif
62
63
64/*********************************************************************************************************************************
65* Defined Constants And Macros *
66*********************************************************************************************************************************/
67/** The support service name. */
68#define SERVICE_NAME "VBoxDrv"
69
70
71/*********************************************************************************************************************************
72* Internal Functions *
73*********************************************************************************************************************************/
74#ifndef IN_SUP_HARDENED_R3
75static int suplibOsCreateService(void);
76//unused: static int suplibOsUpdateService(void);
77static int suplibOsDeleteService(void);
78static int suplibOsStartService(void);
79static int suplibOsStopService(void);
80#endif
81#ifdef USE_NT_DEVICE_IO_CONTROL_FILE
82static int suplibConvertNtStatus(NTSTATUS rcNt);
83#else
84static int suplibConvertWin32Err(int);
85#endif
86
87
88/*********************************************************************************************************************************
89* Global Variables *
90*********************************************************************************************************************************/
91static bool g_fHardenedVerifyInited = false;
92
93
94int suplibOsHardenedVerifyInit(void)
95{
96 if (!g_fHardenedVerifyInited)
97 {
98#if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_HARDENED_R3) && !defined(IN_SUP_R3_STATIC)
99 supR3HardenedWinInitVersion(false /*fEarly*/);
100 int rc = supHardenedWinInitImageVerifier(NULL);
101 if (RT_FAILURE(rc))
102 return rc;
103 supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(NULL);
104#endif
105 g_fHardenedVerifyInited = true;
106 }
107 return VINF_SUCCESS;
108}
109
110
111int suplibOsHardenedVerifyTerm(void)
112{
113 /** @todo free resources... */
114 return VINF_SUCCESS;
115}
116
117
118int suplibOsInit(PSUPLIBDATA pThis, bool fPreInited, bool fUnrestricted, SUPINITOP *penmWhat, PRTERRINFO pErrInfo)
119{
120 /*
121 * Make sure the image verifier is fully initialized.
122 */
123 int rc = suplibOsHardenedVerifyInit();
124 if (RT_FAILURE(rc))
125 return RTErrInfoSetF(pErrInfo, rc, "suplibOsHardenedVerifyInit failed: %Rrc", rc);
126
127 /*
128 * Done if of pre-inited.
129 */
130 if (fPreInited)
131 {
132#if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_HARDENED_R3)
133# ifdef IN_SUP_R3_STATIC
134 return VERR_NOT_SUPPORTED;
135# else
136 return VINF_SUCCESS;
137# endif
138#else
139 return VINF_SUCCESS;
140#endif
141 }
142
143 /*
144 * Try open the device.
145 */
146#ifndef IN_SUP_HARDENED_R3
147 uint32_t cTry = 0;
148#endif
149 HANDLE hDevice;
150 for (;;)
151 {
152 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
153
154 static const WCHAR s_wszName[] = L"\\Device\\VBoxDrvU";
155 UNICODE_STRING NtName;
156 NtName.Buffer = (PWSTR)s_wszName;
157 NtName.Length = sizeof(s_wszName) - sizeof(WCHAR) * (fUnrestricted ? 2 : 1);
158 NtName.MaximumLength = NtName.Length;
159
160 OBJECT_ATTRIBUTES ObjAttr;
161 InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
162
163 hDevice = RTNT_INVALID_HANDLE_VALUE;
164
165 NTSTATUS rcNt = NtCreateFile(&hDevice,
166 GENERIC_READ | GENERIC_WRITE, /* No SYNCHRONIZE. */
167 &ObjAttr,
168 &Ios,
169 NULL /* Allocation Size*/,
170 FILE_ATTRIBUTE_NORMAL,
171 FILE_SHARE_READ | FILE_SHARE_WRITE,
172 FILE_OPEN,
173 FILE_NON_DIRECTORY_FILE, /* No FILE_SYNCHRONOUS_IO_NONALERT! */
174 NULL /*EaBuffer*/,
175 0 /*EaLength*/);
176 if (NT_SUCCESS(rcNt))
177 rcNt = Ios.Status;
178 if (NT_SUCCESS(rcNt))
179 {
180 /*
181 * We're good.
182 */
183 pThis->hDevice = hDevice;
184 pThis->fUnrestricted = fUnrestricted;
185 return VINF_SUCCESS;
186 }
187
188#ifndef IN_SUP_HARDENED_R3
189 /*
190 * Failed to open, try starting the service and reopen the device
191 * exactly once.
192 */
193 if (cTry == 0 && !NT_SUCCESS(rcNt))
194 {
195 cTry++;
196 suplibOsStartService();
197 continue;
198 }
199#endif
200
201 /*
202 * Translate the error code.
203 */
204 switch (rcNt)
205 {
206 /** @todo someone must test what is actually returned. */
207 case STATUS_DEVICE_DOES_NOT_EXIST:
208 case STATUS_DEVICE_NOT_CONNECTED:
209 //case ERROR_BAD_DEVICE:
210 case STATUS_DEVICE_REMOVED:
211 //case ERROR_DEVICE_NOT_AVAILABLE:
212 rc = VERR_VM_DRIVER_LOAD_ERROR;
213 break;
214 case STATUS_OBJECT_PATH_NOT_FOUND:
215 case STATUS_NO_SUCH_DEVICE:
216 case STATUS_NO_SUCH_FILE:
217 case STATUS_OBJECT_NAME_NOT_FOUND:
218 rc = VERR_VM_DRIVER_NOT_INSTALLED;
219 break;
220 case STATUS_ACCESS_DENIED:
221 case STATUS_SHARING_VIOLATION:
222 rc = VERR_VM_DRIVER_NOT_ACCESSIBLE;
223 break;
224 case STATUS_UNSUCCESSFUL:
225 rc = VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0;
226 break;
227 case STATUS_TRUST_FAILURE:
228 rc = VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1;
229 break;
230 case STATUS_TOO_LATE:
231 rc = VERR_SUPDRV_HARDENING_EVIL_HANDLE;
232 break;
233 default:
234 if (SUP_NT_STATUS_IS_VBOX(rcNt)) /* See VBoxDrvNtErr2NtStatus. */
235 rc = SUP_NT_STATUS_TO_VBOX(rcNt);
236 else
237 rc = VERR_VM_DRIVER_OPEN_ERROR;
238 break;
239 }
240
241#ifdef IN_SUP_HARDENED_R3
242 /*
243 * Get more details from VBoxDrvErrorInfo if present.
244 */
245 if (pErrInfo && pErrInfo->cbMsg > 32)
246 {
247 /* Prefix. */
248 size_t cchPrefix;
249 const char *pszDefine = RTErrGetDefine(rc);
250 if (strncmp(pszDefine, RT_STR_TUPLE("Unknown")))
251 cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%s): ", rcNt, pszDefine);
252 else
253 cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%d): ", rcNt, rc);
254
255 /* Get error info. */
256 supR3HardenedWinReadErrorInfoDevice(pErrInfo->pszMsg + cchPrefix, pErrInfo->cbMsg - cchPrefix, "");
257 if (pErrInfo->pszMsg[cchPrefix] != '\0')
258 {
259 pErrInfo->fFlags |= RTERRINFO_FLAGS_SET;
260 pErrInfo->rc = rc;
261 *penmWhat = kSupInitOp_Integrity;
262 }
263 else
264 pErrInfo->pszMsg[0] = '\0';
265 }
266#else
267 RT_NOREF1(penmWhat);
268#endif
269 return rc;
270 }
271}
272
273
274#ifndef IN_SUP_HARDENED_R3
275
276int suplibOsInstall(void)
277{
278 int rc = suplibOsCreateService();
279 if (RT_SUCCESS(rc))
280 {
281 int rc2 = suplibOsStartService();
282 if (rc2 != VINF_SUCCESS)
283 rc = rc2;
284 }
285 return rc;
286}
287
288
289int suplibOsUninstall(void)
290{
291 int rc = suplibOsStopService();
292 if (RT_SUCCESS(rc))
293 rc = suplibOsDeleteService();
294 return rc;
295}
296
297
298/**
299 * Creates the service.
300 *
301 * @returns VBox status code.
302 * @retval VWRN_ALREADY_EXISTS if it already exists.
303 */
304static int suplibOsCreateService(void)
305{
306 /*
307 * Assume it didn't exist, so we'll create the service.
308 */
309 int rc;
310 SC_HANDLE hSMgrCreate = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
311 DWORD dwErr = GetLastError();
312 AssertMsg(hSMgrCreate, ("OpenSCManager(,,create) failed dwErr=%d\n", dwErr));
313 if (hSMgrCreate != NULL)
314 {
315 char szDriver[RTPATH_MAX];
316 rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
317 if (RT_SUCCESS(rc))
318 {
319 strcat(szDriver, "\\VBoxDrv.sys");
320 SC_HANDLE hService = CreateService(hSMgrCreate,
321 SERVICE_NAME,
322 "VBox Support Driver",
323 SERVICE_QUERY_STATUS,
324 SERVICE_KERNEL_DRIVER,
325 SERVICE_DEMAND_START,
326 SERVICE_ERROR_NORMAL,
327 szDriver,
328 NULL, NULL, NULL, NULL, NULL);
329 dwErr = GetLastError();
330 if (hService)
331 {
332 CloseServiceHandle(hService);
333 rc = VINF_SUCCESS;
334 }
335 else if (dwErr == ERROR_SERVICE_EXISTS)
336 rc = VWRN_ALREADY_EXISTS;
337 else
338 {
339 AssertMsgFailed(("CreateService failed! dwErr=%Rwa szDriver=%s\n", dwErr, szDriver));
340 rc = RTErrConvertFromWin32(dwErr);
341 }
342 }
343 CloseServiceHandle(hSMgrCreate);
344 }
345 else
346 rc = RTErrConvertFromWin32(GetLastError());
347 return rc;
348}
349
350
351/**
352 * Stops a possibly running service.
353 *
354 * @returns VBox status code.
355 */
356static int suplibOsStopService(void)
357{
358 /*
359 * Assume it didn't exist, so we'll create the service.
360 */
361 int rc;
362 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_STOP | SERVICE_QUERY_STATUS);
363 DWORD dwErr = GetLastError();
364 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed dwErr=%d\n", dwErr));
365 if (hSMgr)
366 {
367 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS);
368 if (hService)
369 {
370 /*
371 * Stop the service.
372 */
373 SERVICE_STATUS Status;
374 QueryServiceStatus(hService, &Status);
375 if (Status.dwCurrentState == SERVICE_STOPPED)
376 rc = VINF_SUCCESS;
377 else if (ControlService(hService, SERVICE_CONTROL_STOP, &Status))
378 {
379 int iWait = 100;
380 while (Status.dwCurrentState == SERVICE_STOP_PENDING && iWait-- > 0)
381 {
382 Sleep(100);
383 QueryServiceStatus(hService, &Status);
384 }
385 if (Status.dwCurrentState == SERVICE_STOPPED)
386 rc = VINF_SUCCESS;
387 else
388 {
389 AssertMsgFailed(("Failed to stop service. status=%d\n", Status.dwCurrentState));
390 rc = VERR_GENERAL_FAILURE;
391 }
392 }
393 else
394 {
395 dwErr = GetLastError();
396 if ( Status.dwCurrentState == SERVICE_STOP_PENDING
397 && dwErr == ERROR_SERVICE_CANNOT_ACCEPT_CTRL)
398 rc = VERR_RESOURCE_BUSY; /* better than VERR_GENERAL_FAILURE */
399 else
400 {
401 AssertMsgFailed(("ControlService failed with dwErr=%Rwa. status=%d\n", dwErr, Status.dwCurrentState));
402 rc = RTErrConvertFromWin32(dwErr);
403 }
404 }
405 CloseServiceHandle(hService);
406 }
407 else
408 {
409 dwErr = GetLastError();
410 if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
411 rc = VINF_SUCCESS;
412 else
413 {
414 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
415 rc = RTErrConvertFromWin32(dwErr);
416 }
417 }
418 CloseServiceHandle(hSMgr);
419 }
420 else
421 rc = RTErrConvertFromWin32(dwErr);
422 return rc;
423}
424
425
426/**
427 * Deletes the service.
428 *
429 * @returns VBox status code.
430 */
431int suplibOsDeleteService(void)
432{
433 /*
434 * Assume it didn't exist, so we'll create the service.
435 */
436 int rc;
437 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
438 DWORD dwErr = GetLastError();
439 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", dwErr));
440 if (hSMgr)
441 {
442 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, DELETE);
443 if (hService)
444 {
445 /*
446 * Delete the service.
447 */
448 if (DeleteService(hService))
449 rc = VINF_SUCCESS;
450 else
451 {
452 dwErr = GetLastError();
453 AssertMsgFailed(("DeleteService failed dwErr=%Rwa\n", dwErr));
454 rc = RTErrConvertFromWin32(dwErr);
455 }
456 CloseServiceHandle(hService);
457 }
458 else
459 {
460 dwErr = GetLastError();
461 if (dwErr == ERROR_SERVICE_DOES_NOT_EXIST)
462 rc = VINF_SUCCESS;
463 else
464 {
465 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
466 rc = RTErrConvertFromWin32(dwErr);
467 }
468 }
469 CloseServiceHandle(hSMgr);
470 }
471 else
472 rc = RTErrConvertFromWin32(dwErr);
473 return rc;
474}
475
476#if 0
477/**
478 * Creates the service.
479 *
480 * @returns 0 on success.
481 * @returns -1 on failure.
482 */
483static int suplibOsUpdateService(void)
484{
485 /*
486 * Assume it didn't exist, so we'll create the service.
487 */
488 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
489 DWORD LastError = GetLastError(); NOREF(LastError);
490 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed LastError=%Rwa\n", LastError));
491 if (hSMgr)
492 {
493 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_CHANGE_CONFIG);
494 if (hService)
495 {
496 char szDriver[RTPATH_MAX];
497 int rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
498 if (RT_SUCCESS(rc))
499 {
500 strcat(szDriver, "\\VBoxDrv.sys");
501
502 SC_LOCK hLock = LockServiceDatabase(hSMgr);
503 if (ChangeServiceConfig(hService,
504 SERVICE_KERNEL_DRIVER,
505 SERVICE_DEMAND_START,
506 SERVICE_ERROR_NORMAL,
507 szDriver,
508 NULL, NULL, NULL, NULL, NULL, NULL))
509 {
510
511 UnlockServiceDatabase(hLock);
512 CloseServiceHandle(hService);
513 CloseServiceHandle(hSMgr);
514 return 0;
515 }
516 else
517 {
518 DWORD LastError = GetLastError(); NOREF(LastError);
519 AssertMsgFailed(("ChangeServiceConfig failed LastError=%Rwa\n", LastError));
520 }
521 }
522 UnlockServiceDatabase(hLock);
523 CloseServiceHandle(hService);
524 }
525 else
526 {
527 DWORD LastError = GetLastError(); NOREF(LastError);
528 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
529 }
530 CloseServiceHandle(hSMgr);
531 }
532 return -1;
533}
534#endif
535
536
537/**
538 * Attempts to start the service, creating it if necessary.
539 *
540 * @returns VBox status code.
541 */
542static int suplibOsStartService(void)
543{
544 /*
545 * Check if the driver service is there.
546 */
547 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
548 if (hSMgr == NULL)
549 {
550 DWORD dwErr = GetLastError();
551 AssertMsgFailed(("couldn't open service manager in SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS mode! (dwErr=%d)\n", dwErr));
552 return RTErrConvertFromWin32(dwErr);
553 }
554
555 /*
556 * Try open our service to check it's status.
557 */
558 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
559 if (!hService)
560 {
561 /*
562 * Create the service.
563 */
564 int rc = suplibOsCreateService();
565 if (RT_FAILURE(rc))
566 return rc;
567
568 /*
569 * Try open the service.
570 */
571 hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
572 }
573
574 /*
575 * Check if open and on demand create succeeded.
576 */
577 int rc;
578 if (hService)
579 {
580
581 /*
582 * Query service status to see if we need to start it or not.
583 */
584 SERVICE_STATUS Status;
585 BOOL fRc = QueryServiceStatus(hService, &Status);
586 Assert(fRc); NOREF(fRc);
587 if (Status.dwCurrentState == SERVICE_RUNNING)
588 rc = VINF_ALREADY_INITIALIZED;
589 else
590 {
591 if (Status.dwCurrentState == SERVICE_START_PENDING)
592 rc = VINF_SUCCESS;
593 else
594 {
595 /*
596 * Start it.
597 */
598 if (StartService(hService, 0, NULL))
599 rc = VINF_SUCCESS;
600 else
601 {
602 DWORD dwErr = GetLastError();
603 AssertMsg(fRc, ("StartService failed with dwErr=%Rwa\n", dwErr));
604 rc = RTErrConvertFromWin32(dwErr);
605 }
606 }
607
608 /*
609 * Wait for the service to finish starting.
610 * We'll wait for 10 seconds then we'll give up.
611 */
612 QueryServiceStatus(hService, &Status);
613 if (Status.dwCurrentState == SERVICE_START_PENDING)
614 {
615 int iWait;
616 for (iWait = 100; iWait > 0 && Status.dwCurrentState == SERVICE_START_PENDING; iWait--)
617 {
618 Sleep(100);
619 QueryServiceStatus(hService, &Status);
620 }
621 DWORD dwErr = GetLastError(); NOREF(dwErr);
622 AssertMsg(Status.dwCurrentState != SERVICE_RUNNING,
623 ("Failed to start. dwErr=%Rwa iWait=%d status=%d\n", dwErr, iWait, Status.dwCurrentState));
624 }
625
626 if (Status.dwCurrentState == SERVICE_RUNNING)
627 rc = VINF_SUCCESS;
628 else if (RT_SUCCESS_NP(rc))
629 rc = VERR_GENERAL_FAILURE;
630 }
631
632 /*
633 * Close open handles.
634 */
635 CloseServiceHandle(hService);
636 }
637 else
638 {
639 DWORD dwErr = GetLastError();
640 AssertMsgFailed(("OpenService failed! LastError=%Rwa\n", dwErr));
641 rc = RTErrConvertFromWin32(dwErr);
642 }
643 if (!CloseServiceHandle(hSMgr))
644 AssertFailed();
645
646 return rc;
647}
648#endif /* !IN_SUP_HARDENED_R3 */
649
650
651int suplibOsTerm(PSUPLIBDATA pThis)
652{
653 /*
654 * Check if we're inited at all.
655 */
656 if (pThis->hDevice != NULL)
657 {
658 NTSTATUS rcNt = NtClose((HANDLE)pThis->hDevice);
659 Assert(NT_SUCCESS(rcNt)); RT_NOREF(rcNt);
660 pThis->hDevice = NIL_RTFILE; /* yes, that's right */
661 }
662
663 return VINF_SUCCESS;
664}
665
666
667#ifndef IN_SUP_HARDENED_R3
668
669int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq)
670{
671 RT_NOREF1(cbReq);
672
673 /*
674 * Issue the device I/O control.
675 */
676 PSUPREQHDR pHdr = (PSUPREQHDR)pvReq;
677 Assert(cbReq == RT_MAX(pHdr->cbIn, pHdr->cbOut));
678# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
679 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
680 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
681 (ULONG)uFunction,
682 pvReq /*pvInput */, pHdr->cbIn /* cbInput */,
683 pvReq /*pvOutput*/, pHdr->cbOut /* cbOutput */);
684 if (NT_SUCCESS(rcNt))
685 {
686 if (NT_SUCCESS(Ios.Status))
687 return VINF_SUCCESS;
688 rcNt = Ios.Status;
689 }
690 return suplibConvertNtStatus(rcNt);
691
692# else
693 DWORD cbReturned = (ULONG)pHdr->cbOut;
694 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, pvReq, pHdr->cbIn, pvReq, cbReturned, &cbReturned, NULL))
695 return 0;
696 return suplibConvertWin32Err(GetLastError());
697# endif
698}
699
700
701int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu)
702{
703 /*
704 * Issue device I/O control.
705 */
706# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
707 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
708 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
709 (ULONG)uFunction,
710 NULL /*pvInput */, 0 /* cbInput */,
711 (PVOID)idCpu /*pvOutput*/, 0 /* cbOutput */);
712 if (NT_SUCCESS(rcNt))
713 {
714 if (NT_SUCCESS(Ios.Status))
715 return VINF_SUCCESS;
716 rcNt = Ios.Status;
717 }
718 return suplibConvertNtStatus(rcNt);
719# else
720 DWORD cbReturned = 0;
721 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, NULL, 0, (LPVOID)idCpu, 0, &cbReturned, NULL))
722 return VINF_SUCCESS;
723 return suplibConvertWin32Err(GetLastError());
724# endif
725}
726
727
728int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages)
729{
730 NOREF(pThis);
731 *ppvPages = VirtualAlloc(NULL, (size_t)cPages << PAGE_SHIFT, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
732 if (*ppvPages)
733 return VINF_SUCCESS;
734 return RTErrConvertFromWin32(GetLastError());
735}
736
737
738int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t /* cPages */)
739{
740 NOREF(pThis);
741 if (VirtualFree(pvPages, 0, MEM_RELEASE))
742 return VINF_SUCCESS;
743 return RTErrConvertFromWin32(GetLastError());
744}
745
746
747bool suplibOsIsNemSupportedWhenNoVtxOrAmdV(void)
748{
749# if ARCH_BITS == 64
750 /*
751 * Check that we're in a VM.
752 */
753 if (!ASMHasCpuId())
754 return false;
755 if (!ASMIsValidStdRange(ASMCpuId_EAX(0)))
756 return false;
757 if (!(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_HVP))
758 return false;
759
760 /*
761 * Try load WinHvPlatform and resolve API for checking.
762 * Note! The two size_t arguments and the ssize_t one are all too big, but who cares.
763 */
764 RTLDRMOD hLdrMod = NIL_RTLDRMOD;
765 int rc = RTLdrLoadSystem("WinHvPlatform.dll", false, &hLdrMod);
766 if (RT_FAILURE(rc))
767 return false;
768
769 bool fRet = false;
770 typedef HRESULT (WINAPI *PFNWHVGETCAPABILITY)(ssize_t, void *, size_t, size_t *);
771 PFNWHVGETCAPABILITY pfnWHvGetCapability = (PFNWHVGETCAPABILITY)RTLdrGetFunction(hLdrMod, "WHvGetCapability");
772 if (pfnWHvGetCapability)
773 {
774 /*
775 * Query the API.
776 */
777 union
778 {
779 BOOL fHypervisorPresent;
780 uint64_t u64Padding;
781 } Caps;
782 RT_ZERO(Caps);
783 size_t cbRetIgn = 0;
784 HRESULT hrc = pfnWHvGetCapability(0 /*WHvCapabilityCodeHypervisorPresent*/, &Caps, sizeof(Caps), &cbRetIgn);
785 if (SUCCEEDED(hrc) && Caps.fHypervisorPresent)
786 fRet = true;
787 }
788
789 RTLdrClose(hLdrMod);
790 return fRet;
791# else
792 return false;
793#endif
794}
795
796
797# ifndef USE_NT_DEVICE_IO_CONTROL_FILE
798/**
799 * Converts a supdrv win32 error code to an IPRT status code.
800 *
801 * @returns corresponding IPRT error code.
802 * @param rc Win32 error code.
803 */
804static int suplibConvertWin32Err(int rc)
805{
806 /* Conversion program (link with ntdll.lib from ddk):
807 #define _WIN32_WINNT 0x0501
808 #include <iprt/win/windows.h>
809 #include <ntstatus.h>
810 #include <winternl.h>
811 #include <stdio.h>
812
813 int main()
814 {
815 #define CONVERT(a) printf(#a " %#x -> %d\n", a, RtlNtStatusToDosError((a)))
816 CONVERT(STATUS_SUCCESS);
817 CONVERT(STATUS_NOT_SUPPORTED);
818 CONVERT(STATUS_INVALID_PARAMETER);
819 CONVERT(STATUS_UNKNOWN_REVISION);
820 CONVERT(STATUS_INVALID_HANDLE);
821 CONVERT(STATUS_INVALID_ADDRESS);
822 CONVERT(STATUS_NOT_LOCKED);
823 CONVERT(STATUS_IMAGE_ALREADY_LOADED);
824 CONVERT(STATUS_ACCESS_DENIED);
825 CONVERT(STATUS_REVISION_MISMATCH);
826
827 return 0;
828 }
829 */
830
831 switch (rc)
832 {
833 //case 0: return STATUS_SUCCESS;
834 case 0: return VINF_SUCCESS;
835 case ERROR_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
836 case ERROR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
837 case ERROR_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
838 case ERROR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
839 case ERROR_UNEXP_NET_ERR: return VERR_INVALID_POINTER;
840 case ERROR_NOT_LOCKED: return VERR_LOCK_FAILED;
841 case ERROR_SERVICE_ALREADY_RUNNING: return VERR_ALREADY_LOADED;
842 case ERROR_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
843 case ERROR_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
844 }
845
846 /* fall back on the default conversion. */
847 return RTErrConvertFromWin32(rc);
848}
849# else
850/**
851 * Reverse of VBoxDrvNtErr2NtStatus
852 * returns VBox status code.
853 * @param rcNt NT status code.
854 */
855static int suplibConvertNtStatus(NTSTATUS rcNt)
856{
857 switch (rcNt)
858 {
859 case STATUS_SUCCESS: return VINF_SUCCESS;
860 case STATUS_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
861 case STATUS_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
862 case STATUS_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
863 case STATUS_INVALID_HANDLE: return VERR_INVALID_HANDLE;
864 case STATUS_INVALID_ADDRESS: return VERR_INVALID_POINTER;
865 case STATUS_NOT_LOCKED: return VERR_LOCK_FAILED;
866 case STATUS_IMAGE_ALREADY_LOADED: return VERR_ALREADY_LOADED;
867 case STATUS_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
868 case STATUS_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
869 }
870
871 /* See VBoxDrvNtErr2NtStatus. */
872 if (SUP_NT_STATUS_IS_VBOX(rcNt))
873 return SUP_NT_STATUS_TO_VBOX(rcNt);
874
875 /* Fall back on IPRT for the rest. */
876 return RTErrConvertFromNtStatus(rcNt);
877}
878# endif
879
880#endif /* !IN_SUP_HARDENED_R3 */
881
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