VirtualBox

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

Last change on this file since 67954 was 67493, checked in by vboxsync, 7 years ago

HostDrivers/Support/win: translate the error when the VBoxDrv module cannot be unloaded to VERR_RESOURCE_BUSY

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

© 2023 Oracle
ContactPrivacy policyTerms of Use