VirtualBox

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

Last change on this file since 87593 was 85129, checked in by vboxsync, 4 years ago

SUPLib: Make the suplibOs* hidden. bugref:9794

  • 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 85129 2020-07-09 00:05:45Z vboxsync $ */
2/** @file
3 * VirtualBox Support Library - Windows NT specific parts.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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
94DECLHIDDEN(int) 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
111DECLHIDDEN(int) suplibOsHardenedVerifyTerm(void)
112{
113 /** @todo free resources... */
114 return VINF_SUCCESS;
115}
116
117
118DECLHIDDEN(int) 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 if (RTErrIsKnown(rc))
250 cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%Rrc): ", rcNt, rc);
251 else
252 cchPrefix = RTStrPrintf(pErrInfo->pszMsg, pErrInfo->cbMsg / 2, "Integrity error (%#x/%d): ", rcNt, rc);
253
254 /* Get error info. */
255 supR3HardenedWinReadErrorInfoDevice(pErrInfo->pszMsg + cchPrefix, pErrInfo->cbMsg - cchPrefix, "");
256 if (pErrInfo->pszMsg[cchPrefix] != '\0')
257 {
258 pErrInfo->fFlags |= RTERRINFO_FLAGS_SET;
259 pErrInfo->rc = rc;
260 *penmWhat = kSupInitOp_Integrity;
261 }
262 else
263 pErrInfo->pszMsg[0] = '\0';
264 }
265#else
266 RT_NOREF1(penmWhat);
267#endif
268 return rc;
269 }
270}
271
272
273#ifndef IN_SUP_HARDENED_R3
274
275DECLHIDDEN(int) suplibOsInstall(void)
276{
277 int rc = suplibOsCreateService();
278 if (RT_SUCCESS(rc))
279 {
280 int rc2 = suplibOsStartService();
281 if (rc2 != VINF_SUCCESS)
282 rc = rc2;
283 }
284 return rc;
285}
286
287
288DECLHIDDEN(int) suplibOsUninstall(void)
289{
290 int rc = suplibOsStopService();
291 if (RT_SUCCESS(rc))
292 rc = suplibOsDeleteService();
293 return rc;
294}
295
296
297/**
298 * Creates the service.
299 *
300 * @returns VBox status code.
301 * @retval VWRN_ALREADY_EXISTS if it already exists.
302 */
303static int suplibOsCreateService(void)
304{
305 /*
306 * Assume it didn't exist, so we'll create the service.
307 */
308 int rc;
309 SC_HANDLE hSMgrCreate = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
310 DWORD dwErr = GetLastError();
311 AssertMsg(hSMgrCreate, ("OpenSCManager(,,create) failed dwErr=%d\n", dwErr));
312 if (hSMgrCreate != NULL)
313 {
314 char szDriver[RTPATH_MAX];
315 rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
316 if (RT_SUCCESS(rc))
317 {
318 strcat(szDriver, "\\VBoxDrv.sys");
319 SC_HANDLE hService = CreateService(hSMgrCreate,
320 SERVICE_NAME,
321 "VBox Support Driver",
322 SERVICE_QUERY_STATUS,
323 SERVICE_KERNEL_DRIVER,
324 SERVICE_DEMAND_START,
325 SERVICE_ERROR_NORMAL,
326 szDriver,
327 NULL, NULL, NULL, NULL, NULL);
328 dwErr = GetLastError();
329 if (hService)
330 {
331 CloseServiceHandle(hService);
332 rc = VINF_SUCCESS;
333 }
334 else if (dwErr == ERROR_SERVICE_EXISTS)
335 rc = VWRN_ALREADY_EXISTS;
336 else
337 {
338 AssertMsgFailed(("CreateService failed! dwErr=%Rwa szDriver=%s\n", dwErr, szDriver));
339 rc = RTErrConvertFromWin32(dwErr);
340 }
341 }
342 CloseServiceHandle(hSMgrCreate);
343 }
344 else
345 rc = RTErrConvertFromWin32(GetLastError());
346 return rc;
347}
348
349
350/**
351 * Stops a possibly running service.
352 *
353 * @returns VBox status code.
354 */
355static int suplibOsStopService(void)
356{
357 /*
358 * Assume it didn't exist, so we'll create the service.
359 */
360 int rc;
361 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_STOP | SERVICE_QUERY_STATUS);
362 DWORD dwErr = GetLastError();
363 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed dwErr=%d\n", dwErr));
364 if (hSMgr)
365 {
366 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS);
367 if (hService)
368 {
369 /*
370 * Stop the service.
371 */
372 SERVICE_STATUS Status;
373 QueryServiceStatus(hService, &Status);
374 if (Status.dwCurrentState == SERVICE_STOPPED)
375 rc = VINF_SUCCESS;
376 else if (ControlService(hService, SERVICE_CONTROL_STOP, &Status))
377 {
378 int iWait = 100;
379 while (Status.dwCurrentState == SERVICE_STOP_PENDING && iWait-- > 0)
380 {
381 Sleep(100);
382 QueryServiceStatus(hService, &Status);
383 }
384 if (Status.dwCurrentState == SERVICE_STOPPED)
385 rc = VINF_SUCCESS;
386 else
387 {
388 AssertMsgFailed(("Failed to stop service. status=%d\n", Status.dwCurrentState));
389 rc = VERR_GENERAL_FAILURE;
390 }
391 }
392 else
393 {
394 dwErr = GetLastError();
395 if ( Status.dwCurrentState == SERVICE_STOP_PENDING
396 && dwErr == ERROR_SERVICE_CANNOT_ACCEPT_CTRL)
397 rc = VERR_RESOURCE_BUSY; /* better than VERR_GENERAL_FAILURE */
398 else
399 {
400 AssertMsgFailed(("ControlService failed with dwErr=%Rwa. status=%d\n", dwErr, Status.dwCurrentState));
401 rc = RTErrConvertFromWin32(dwErr);
402 }
403 }
404 CloseServiceHandle(hService);
405 }
406 else
407 {
408 dwErr = GetLastError();
409 if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
410 rc = VINF_SUCCESS;
411 else
412 {
413 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
414 rc = RTErrConvertFromWin32(dwErr);
415 }
416 }
417 CloseServiceHandle(hSMgr);
418 }
419 else
420 rc = RTErrConvertFromWin32(dwErr);
421 return rc;
422}
423
424
425/**
426 * Deletes the service.
427 *
428 * @returns VBox status code.
429 */
430int suplibOsDeleteService(void)
431{
432 /*
433 * Assume it didn't exist, so we'll create the service.
434 */
435 int rc;
436 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
437 DWORD dwErr = GetLastError();
438 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", dwErr));
439 if (hSMgr)
440 {
441 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, DELETE);
442 if (hService)
443 {
444 /*
445 * Delete the service.
446 */
447 if (DeleteService(hService))
448 rc = VINF_SUCCESS;
449 else
450 {
451 dwErr = GetLastError();
452 AssertMsgFailed(("DeleteService failed dwErr=%Rwa\n", dwErr));
453 rc = RTErrConvertFromWin32(dwErr);
454 }
455 CloseServiceHandle(hService);
456 }
457 else
458 {
459 dwErr = GetLastError();
460 if (dwErr == ERROR_SERVICE_DOES_NOT_EXIST)
461 rc = VINF_SUCCESS;
462 else
463 {
464 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
465 rc = RTErrConvertFromWin32(dwErr);
466 }
467 }
468 CloseServiceHandle(hSMgr);
469 }
470 else
471 rc = RTErrConvertFromWin32(dwErr);
472 return rc;
473}
474
475#if 0
476/**
477 * Creates the service.
478 *
479 * @returns 0 on success.
480 * @returns -1 on failure.
481 */
482static int suplibOsUpdateService(void)
483{
484 /*
485 * Assume it didn't exist, so we'll create the service.
486 */
487 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
488 DWORD LastError = GetLastError(); NOREF(LastError);
489 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed LastError=%Rwa\n", LastError));
490 if (hSMgr)
491 {
492 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_CHANGE_CONFIG);
493 if (hService)
494 {
495 char szDriver[RTPATH_MAX];
496 int rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
497 if (RT_SUCCESS(rc))
498 {
499 strcat(szDriver, "\\VBoxDrv.sys");
500
501 SC_LOCK hLock = LockServiceDatabase(hSMgr);
502 if (ChangeServiceConfig(hService,
503 SERVICE_KERNEL_DRIVER,
504 SERVICE_DEMAND_START,
505 SERVICE_ERROR_NORMAL,
506 szDriver,
507 NULL, NULL, NULL, NULL, NULL, NULL))
508 {
509
510 UnlockServiceDatabase(hLock);
511 CloseServiceHandle(hService);
512 CloseServiceHandle(hSMgr);
513 return 0;
514 }
515 else
516 {
517 DWORD LastError = GetLastError(); NOREF(LastError);
518 AssertMsgFailed(("ChangeServiceConfig failed LastError=%Rwa\n", LastError));
519 }
520 }
521 UnlockServiceDatabase(hLock);
522 CloseServiceHandle(hService);
523 }
524 else
525 {
526 DWORD LastError = GetLastError(); NOREF(LastError);
527 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
528 }
529 CloseServiceHandle(hSMgr);
530 }
531 return -1;
532}
533#endif
534
535
536/**
537 * Attempts to start the service, creating it if necessary.
538 *
539 * @returns VBox status code.
540 */
541static int suplibOsStartService(void)
542{
543 /*
544 * Check if the driver service is there.
545 */
546 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
547 if (hSMgr == NULL)
548 {
549 DWORD dwErr = GetLastError();
550 AssertMsgFailed(("couldn't open service manager in SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS mode! (dwErr=%d)\n", dwErr));
551 return RTErrConvertFromWin32(dwErr);
552 }
553
554 /*
555 * Try open our service to check it's status.
556 */
557 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
558 if (!hService)
559 {
560 /*
561 * Create the service.
562 */
563 int rc = suplibOsCreateService();
564 if (RT_FAILURE(rc))
565 return rc;
566
567 /*
568 * Try open the service.
569 */
570 hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
571 }
572
573 /*
574 * Check if open and on demand create succeeded.
575 */
576 int rc;
577 if (hService)
578 {
579
580 /*
581 * Query service status to see if we need to start it or not.
582 */
583 SERVICE_STATUS Status;
584 BOOL fRc = QueryServiceStatus(hService, &Status);
585 Assert(fRc); NOREF(fRc);
586 if (Status.dwCurrentState == SERVICE_RUNNING)
587 rc = VINF_ALREADY_INITIALIZED;
588 else
589 {
590 if (Status.dwCurrentState == SERVICE_START_PENDING)
591 rc = VINF_SUCCESS;
592 else
593 {
594 /*
595 * Start it.
596 */
597 if (StartService(hService, 0, NULL))
598 rc = VINF_SUCCESS;
599 else
600 {
601 DWORD dwErr = GetLastError();
602 AssertMsg(fRc, ("StartService failed with dwErr=%Rwa\n", dwErr));
603 rc = RTErrConvertFromWin32(dwErr);
604 }
605 }
606
607 /*
608 * Wait for the service to finish starting.
609 * We'll wait for 10 seconds then we'll give up.
610 */
611 QueryServiceStatus(hService, &Status);
612 if (Status.dwCurrentState == SERVICE_START_PENDING)
613 {
614 int iWait;
615 for (iWait = 100; iWait > 0 && Status.dwCurrentState == SERVICE_START_PENDING; iWait--)
616 {
617 Sleep(100);
618 QueryServiceStatus(hService, &Status);
619 }
620 DWORD dwErr = GetLastError(); NOREF(dwErr);
621 AssertMsg(Status.dwCurrentState != SERVICE_RUNNING,
622 ("Failed to start. dwErr=%Rwa iWait=%d status=%d\n", dwErr, iWait, Status.dwCurrentState));
623 }
624
625 if (Status.dwCurrentState == SERVICE_RUNNING)
626 rc = VINF_SUCCESS;
627 else if (RT_SUCCESS_NP(rc))
628 rc = VERR_GENERAL_FAILURE;
629 }
630
631 /*
632 * Close open handles.
633 */
634 CloseServiceHandle(hService);
635 }
636 else
637 {
638 DWORD dwErr = GetLastError();
639 AssertMsgFailed(("OpenService failed! LastError=%Rwa\n", dwErr));
640 rc = RTErrConvertFromWin32(dwErr);
641 }
642 if (!CloseServiceHandle(hSMgr))
643 AssertFailed();
644
645 return rc;
646}
647#endif /* !IN_SUP_HARDENED_R3 */
648
649
650DECLHIDDEN(int) suplibOsTerm(PSUPLIBDATA pThis)
651{
652 /*
653 * Check if we're inited at all.
654 */
655 if (pThis->hDevice != NULL)
656 {
657 NTSTATUS rcNt = NtClose((HANDLE)pThis->hDevice);
658 Assert(NT_SUCCESS(rcNt)); RT_NOREF(rcNt);
659 pThis->hDevice = NIL_RTFILE; /* yes, that's right */
660 }
661
662 return VINF_SUCCESS;
663}
664
665
666#ifndef IN_SUP_HARDENED_R3
667
668DECLHIDDEN(int) suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq)
669{
670 RT_NOREF1(cbReq);
671
672 /*
673 * Issue the device I/O control.
674 */
675 PSUPREQHDR pHdr = (PSUPREQHDR)pvReq;
676 Assert(cbReq == RT_MAX(pHdr->cbIn, pHdr->cbOut));
677# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
678 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
679 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
680 (ULONG)uFunction,
681 pvReq /*pvInput */, pHdr->cbIn /* cbInput */,
682 pvReq /*pvOutput*/, pHdr->cbOut /* cbOutput */);
683 if (NT_SUCCESS(rcNt))
684 {
685 if (NT_SUCCESS(Ios.Status))
686 return VINF_SUCCESS;
687 rcNt = Ios.Status;
688 }
689 return suplibConvertNtStatus(rcNt);
690
691# else
692 DWORD cbReturned = (ULONG)pHdr->cbOut;
693 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, pvReq, pHdr->cbIn, pvReq, cbReturned, &cbReturned, NULL))
694 return 0;
695 return suplibConvertWin32Err(GetLastError());
696# endif
697}
698
699
700DECLHIDDEN(int) suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu)
701{
702 /*
703 * Issue device I/O control.
704 */
705# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
706 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
707 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
708 (ULONG)uFunction,
709 NULL /*pvInput */, 0 /* cbInput */,
710 (PVOID)idCpu /*pvOutput*/, 0 /* cbOutput */);
711 if (NT_SUCCESS(rcNt))
712 {
713 if (NT_SUCCESS(Ios.Status))
714 return VINF_SUCCESS;
715 rcNt = Ios.Status;
716 }
717 return suplibConvertNtStatus(rcNt);
718# else
719 DWORD cbReturned = 0;
720 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, NULL, 0, (LPVOID)idCpu, 0, &cbReturned, NULL))
721 return VINF_SUCCESS;
722 return suplibConvertWin32Err(GetLastError());
723# endif
724}
725
726
727DECLHIDDEN(int) suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages)
728{
729 NOREF(pThis);
730 *ppvPages = VirtualAlloc(NULL, (size_t)cPages << PAGE_SHIFT, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
731 if (*ppvPages)
732 return VINF_SUCCESS;
733 return RTErrConvertFromWin32(GetLastError());
734}
735
736
737DECLHIDDEN(int) suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t /* cPages */)
738{
739 NOREF(pThis);
740 if (VirtualFree(pvPages, 0, MEM_RELEASE))
741 return VINF_SUCCESS;
742 return RTErrConvertFromWin32(GetLastError());
743}
744
745
746DECLHIDDEN(bool) suplibOsIsNemSupportedWhenNoVtxOrAmdV(void)
747{
748# if ARCH_BITS == 64
749 /*
750 * Check that we're in a VM.
751 */
752 if (!ASMHasCpuId())
753 return false;
754 if (!ASMIsValidStdRange(ASMCpuId_EAX(0)))
755 return false;
756 if (!(ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_HVP))
757 return false;
758
759 /*
760 * Try load WinHvPlatform and resolve API for checking.
761 * Note! The two size_t arguments and the ssize_t one are all too big, but who cares.
762 */
763 RTLDRMOD hLdrMod = NIL_RTLDRMOD;
764 int rc = RTLdrLoadSystem("WinHvPlatform.dll", false, &hLdrMod);
765 if (RT_FAILURE(rc))
766 return false;
767
768 bool fRet = false;
769 typedef HRESULT (WINAPI *PFNWHVGETCAPABILITY)(ssize_t, void *, size_t, size_t *);
770 PFNWHVGETCAPABILITY pfnWHvGetCapability = (PFNWHVGETCAPABILITY)RTLdrGetFunction(hLdrMod, "WHvGetCapability");
771 if (pfnWHvGetCapability)
772 {
773 /*
774 * Query the API.
775 */
776 union
777 {
778 BOOL fHypervisorPresent;
779 uint64_t u64Padding;
780 } Caps;
781 RT_ZERO(Caps);
782 size_t cbRetIgn = 0;
783 HRESULT hrc = pfnWHvGetCapability(0 /*WHvCapabilityCodeHypervisorPresent*/, &Caps, sizeof(Caps), &cbRetIgn);
784 if (SUCCEEDED(hrc) && Caps.fHypervisorPresent)
785 fRet = true;
786 }
787
788 RTLdrClose(hLdrMod);
789 return fRet;
790# else
791 return false;
792#endif
793}
794
795
796# ifndef USE_NT_DEVICE_IO_CONTROL_FILE
797/**
798 * Converts a supdrv win32 error code to an IPRT status code.
799 *
800 * @returns corresponding IPRT error code.
801 * @param rc Win32 error code.
802 */
803static int suplibConvertWin32Err(int rc)
804{
805 /* Conversion program (link with ntdll.lib from ddk):
806 #define _WIN32_WINNT 0x0501
807 #include <iprt/win/windows.h>
808 #include <ntstatus.h>
809 #include <winternl.h>
810 #include <stdio.h>
811
812 int main()
813 {
814 #define CONVERT(a) printf(#a " %#x -> %d\n", a, RtlNtStatusToDosError((a)))
815 CONVERT(STATUS_SUCCESS);
816 CONVERT(STATUS_NOT_SUPPORTED);
817 CONVERT(STATUS_INVALID_PARAMETER);
818 CONVERT(STATUS_UNKNOWN_REVISION);
819 CONVERT(STATUS_INVALID_HANDLE);
820 CONVERT(STATUS_INVALID_ADDRESS);
821 CONVERT(STATUS_NOT_LOCKED);
822 CONVERT(STATUS_IMAGE_ALREADY_LOADED);
823 CONVERT(STATUS_ACCESS_DENIED);
824 CONVERT(STATUS_REVISION_MISMATCH);
825
826 return 0;
827 }
828 */
829
830 switch (rc)
831 {
832 //case 0: return STATUS_SUCCESS;
833 case 0: return VINF_SUCCESS;
834 case ERROR_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
835 case ERROR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
836 case ERROR_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
837 case ERROR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
838 case ERROR_UNEXP_NET_ERR: return VERR_INVALID_POINTER;
839 case ERROR_NOT_LOCKED: return VERR_LOCK_FAILED;
840 case ERROR_SERVICE_ALREADY_RUNNING: return VERR_ALREADY_LOADED;
841 case ERROR_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
842 case ERROR_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
843 }
844
845 /* fall back on the default conversion. */
846 return RTErrConvertFromWin32(rc);
847}
848# else
849/**
850 * Reverse of VBoxDrvNtErr2NtStatus
851 * returns VBox status code.
852 * @param rcNt NT status code.
853 */
854static int suplibConvertNtStatus(NTSTATUS rcNt)
855{
856 switch (rcNt)
857 {
858 case STATUS_SUCCESS: return VINF_SUCCESS;
859 case STATUS_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
860 case STATUS_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
861 case STATUS_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
862 case STATUS_INVALID_HANDLE: return VERR_INVALID_HANDLE;
863 case STATUS_INVALID_ADDRESS: return VERR_INVALID_POINTER;
864 case STATUS_NOT_LOCKED: return VERR_LOCK_FAILED;
865 case STATUS_IMAGE_ALREADY_LOADED: return VERR_ALREADY_LOADED;
866 case STATUS_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
867 case STATUS_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
868 }
869
870 /* See VBoxDrvNtErr2NtStatus. */
871 if (SUP_NT_STATUS_IS_VBOX(rcNt))
872 return SUP_NT_STATUS_TO_VBOX(rcNt);
873
874 /* Fall back on IPRT for the rest. */
875 return RTErrConvertFromNtStatus(rcNt);
876}
877# endif
878
879#endif /* !IN_SUP_HARDENED_R3 */
880
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