VirtualBox

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

Last change on this file since 64281 was 62679, checked in by vboxsync, 8 years ago

Use the iprt/win/windows.h wrapper for Windows.h

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.4 KB
Line 
1/* $Id: SUPLib-win.cpp 62679 2016-07-29 12:52:10Z 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 AssertMsgFailed(("ControlService failed with dwErr=%Rwa. status=%d\n", dwErr, Status.dwCurrentState));
393 rc = RTErrConvertFromWin32(dwErr);
394 }
395 CloseServiceHandle(hService);
396 }
397 else
398 {
399 dwErr = GetLastError();
400 if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
401 rc = VINF_SUCCESS;
402 else
403 {
404 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
405 rc = RTErrConvertFromWin32(dwErr);
406 }
407 }
408 CloseServiceHandle(hSMgr);
409 }
410 else
411 rc = RTErrConvertFromWin32(dwErr);
412 return rc;
413}
414
415
416/**
417 * Deletes the service.
418 *
419 * @returns VBox status code.
420 */
421int suplibOsDeleteService(void)
422{
423 /*
424 * Assume it didn't exist, so we'll create the service.
425 */
426 int rc;
427 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
428 DWORD dwErr = GetLastError();
429 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", dwErr));
430 if (hSMgr)
431 {
432 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, DELETE);
433 if (hService)
434 {
435 /*
436 * Delete the service.
437 */
438 if (DeleteService(hService))
439 rc = VINF_SUCCESS;
440 else
441 {
442 dwErr = GetLastError();
443 AssertMsgFailed(("DeleteService failed dwErr=%Rwa\n", dwErr));
444 rc = RTErrConvertFromWin32(dwErr);
445 }
446 CloseServiceHandle(hService);
447 }
448 else
449 {
450 dwErr = GetLastError();
451 if (dwErr == ERROR_SERVICE_DOES_NOT_EXIST)
452 rc = VINF_SUCCESS;
453 else
454 {
455 AssertMsgFailed(("OpenService failed dwErr=%Rwa\n", dwErr));
456 rc = RTErrConvertFromWin32(dwErr);
457 }
458 }
459 CloseServiceHandle(hSMgr);
460 }
461 else
462 rc = RTErrConvertFromWin32(dwErr);
463 return rc;
464}
465
466#if 0
467/**
468 * Creates the service.
469 *
470 * @returns 0 on success.
471 * @returns -1 on failure.
472 */
473static int suplibOsUpdateService(void)
474{
475 /*
476 * Assume it didn't exist, so we'll create the service.
477 */
478 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG);
479 DWORD LastError = GetLastError(); NOREF(LastError);
480 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed LastError=%Rwa\n", LastError));
481 if (hSMgr)
482 {
483 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_CHANGE_CONFIG);
484 if (hService)
485 {
486 char szDriver[RTPATH_MAX];
487 int rc = RTPathExecDir(szDriver, sizeof(szDriver) - sizeof("\\VBoxDrv.sys"));
488 if (RT_SUCCESS(rc))
489 {
490 strcat(szDriver, "\\VBoxDrv.sys");
491
492 SC_LOCK hLock = LockServiceDatabase(hSMgr);
493 if (ChangeServiceConfig(hService,
494 SERVICE_KERNEL_DRIVER,
495 SERVICE_DEMAND_START,
496 SERVICE_ERROR_NORMAL,
497 szDriver,
498 NULL, NULL, NULL, NULL, NULL, NULL))
499 {
500
501 UnlockServiceDatabase(hLock);
502 CloseServiceHandle(hService);
503 CloseServiceHandle(hSMgr);
504 return 0;
505 }
506 else
507 {
508 DWORD LastError = GetLastError(); NOREF(LastError);
509 AssertMsgFailed(("ChangeServiceConfig failed LastError=%Rwa\n", LastError));
510 }
511 }
512 UnlockServiceDatabase(hLock);
513 CloseServiceHandle(hService);
514 }
515 else
516 {
517 DWORD LastError = GetLastError(); NOREF(LastError);
518 AssertMsgFailed(("OpenService failed LastError=%Rwa\n", LastError));
519 }
520 CloseServiceHandle(hSMgr);
521 }
522 return -1;
523}
524#endif
525
526
527/**
528 * Attempts to start the service, creating it if necessary.
529 *
530 * @returns VBox status code.
531 */
532static int suplibOsStartService(void)
533{
534 /*
535 * Check if the driver service is there.
536 */
537 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
538 if (hSMgr == NULL)
539 {
540 DWORD dwErr = GetLastError();
541 AssertMsgFailed(("couldn't open service manager in SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS mode! (dwErr=%d)\n", dwErr));
542 return RTErrConvertFromWin32(dwErr);
543 }
544
545 /*
546 * Try open our service to check it's status.
547 */
548 SC_HANDLE hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
549 if (!hService)
550 {
551 /*
552 * Create the service.
553 */
554 int rc = suplibOsCreateService();
555 if (RT_FAILURE(rc))
556 return rc;
557
558 /*
559 * Try open the service.
560 */
561 hService = OpenService(hSMgr, SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
562 }
563
564 /*
565 * Check if open and on demand create succeeded.
566 */
567 int rc;
568 if (hService)
569 {
570
571 /*
572 * Query service status to see if we need to start it or not.
573 */
574 SERVICE_STATUS Status;
575 BOOL fRc = QueryServiceStatus(hService, &Status);
576 Assert(fRc); NOREF(fRc);
577 if (Status.dwCurrentState == SERVICE_RUNNING)
578 rc = VINF_ALREADY_INITIALIZED;
579 else
580 {
581 if (Status.dwCurrentState == SERVICE_START_PENDING)
582 rc = VINF_SUCCESS;
583 else
584 {
585 /*
586 * Start it.
587 */
588 if (StartService(hService, 0, NULL))
589 rc = VINF_SUCCESS;
590 else
591 {
592 DWORD dwErr = GetLastError();
593 AssertMsg(fRc, ("StartService failed with dwErr=%Rwa\n", dwErr));
594 rc = RTErrConvertFromWin32(dwErr);
595 }
596 }
597
598 /*
599 * Wait for the service to finish starting.
600 * We'll wait for 10 seconds then we'll give up.
601 */
602 QueryServiceStatus(hService, &Status);
603 if (Status.dwCurrentState == SERVICE_START_PENDING)
604 {
605 int iWait;
606 for (iWait = 100; iWait > 0 && Status.dwCurrentState == SERVICE_START_PENDING; iWait--)
607 {
608 Sleep(100);
609 QueryServiceStatus(hService, &Status);
610 }
611 DWORD dwErr = GetLastError(); NOREF(dwErr);
612 AssertMsg(Status.dwCurrentState != SERVICE_RUNNING,
613 ("Failed to start. dwErr=%Rwa iWait=%d status=%d\n", dwErr, iWait, Status.dwCurrentState));
614 }
615
616 if (Status.dwCurrentState == SERVICE_RUNNING)
617 rc = VINF_SUCCESS;
618 else if (RT_SUCCESS_NP(rc))
619 rc = VERR_GENERAL_FAILURE;
620 }
621
622 /*
623 * Close open handles.
624 */
625 CloseServiceHandle(hService);
626 }
627 else
628 {
629 DWORD dwErr = GetLastError();
630 AssertMsgFailed(("OpenService failed! LastError=%Rwa\n", dwErr));
631 rc = RTErrConvertFromWin32(dwErr);
632 }
633 if (!CloseServiceHandle(hSMgr))
634 AssertFailed();
635
636 return rc;
637}
638
639
640int suplibOsTerm(PSUPLIBDATA pThis)
641{
642 /*
643 * Check if we're inited at all.
644 */
645 if (pThis->hDevice != NULL)
646 {
647 if (!CloseHandle((HANDLE)pThis->hDevice))
648 AssertFailed();
649 pThis->hDevice = NIL_RTFILE; /* yes, that's right */
650 }
651
652 return VINF_SUCCESS;
653}
654
655
656int suplibOsIOCtl(PSUPLIBDATA pThis, uintptr_t uFunction, void *pvReq, size_t cbReq)
657{
658 RT_NOREF1(cbReq);
659
660 /*
661 * Issue the device I/O control.
662 */
663 PSUPREQHDR pHdr = (PSUPREQHDR)pvReq;
664 Assert(cbReq == RT_MAX(pHdr->cbIn, pHdr->cbOut));
665# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
666 IO_STATUS_BLOCK Ios;
667 Ios.Status = -1;
668 Ios.Information = 0;
669 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
670 (ULONG)uFunction,
671 pvReq /*pvInput */, pHdr->cbIn /* cbInput */,
672 pvReq /*pvOutput*/, pHdr->cbOut /* cbOutput */);
673 if (NT_SUCCESS(rcNt))
674 {
675 if (NT_SUCCESS(Ios.Status))
676 return VINF_SUCCESS;
677 rcNt = Ios.Status;
678 }
679 return suplibConvertNtStatus(rcNt);
680
681# else
682 DWORD cbReturned = (ULONG)pHdr->cbOut;
683 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, pvReq, pHdr->cbIn, pvReq, cbReturned, &cbReturned, NULL))
684 return 0;
685 return suplibConvertWin32Err(GetLastError());
686# endif
687}
688
689
690int suplibOsIOCtlFast(PSUPLIBDATA pThis, uintptr_t uFunction, uintptr_t idCpu)
691{
692 /*
693 * Issue device I/O control.
694 */
695# ifdef USE_NT_DEVICE_IO_CONTROL_FILE
696 IO_STATUS_BLOCK Ios;
697 Ios.Status = -1;
698 Ios.Information = 0;
699 NTSTATUS rcNt = NtDeviceIoControlFile((HANDLE)pThis->hDevice, NULL /*hEvent*/, NULL /*pfnApc*/, NULL /*pvApcCtx*/, &Ios,
700 (ULONG)uFunction,
701 NULL /*pvInput */, 0 /* cbInput */,
702 (PVOID)idCpu /*pvOutput*/, 0 /* cbOutput */);
703 if (NT_SUCCESS(rcNt))
704 {
705 if (NT_SUCCESS(Ios.Status))
706 return VINF_SUCCESS;
707 rcNt = Ios.Status;
708 }
709 return suplibConvertNtStatus(rcNt);
710# else
711 DWORD cbReturned = 0;
712 if (DeviceIoControl((HANDLE)pThis->hDevice, uFunction, NULL, 0, (LPVOID)idCpu, 0, &cbReturned, NULL))
713 return VINF_SUCCESS;
714 return suplibConvertWin32Err(GetLastError());
715# endif
716}
717
718
719int suplibOsPageAlloc(PSUPLIBDATA pThis, size_t cPages, void **ppvPages)
720{
721 NOREF(pThis);
722 *ppvPages = VirtualAlloc(NULL, (size_t)cPages << PAGE_SHIFT, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
723 if (*ppvPages)
724 return VINF_SUCCESS;
725 return RTErrConvertFromWin32(GetLastError());
726}
727
728
729int suplibOsPageFree(PSUPLIBDATA pThis, void *pvPages, size_t /* cPages */)
730{
731 NOREF(pThis);
732 if (VirtualFree(pvPages, 0, MEM_RELEASE))
733 return VINF_SUCCESS;
734 return RTErrConvertFromWin32(GetLastError());
735}
736
737
738# ifndef USE_NT_DEVICE_IO_CONTROL_FILE
739/**
740 * Converts a supdrv win32 error code to an IPRT status code.
741 *
742 * @returns corresponding IPRT error code.
743 * @param rc Win32 error code.
744 */
745static int suplibConvertWin32Err(int rc)
746{
747 /* Conversion program (link with ntdll.lib from ddk):
748 #define _WIN32_WINNT 0x0501
749 #include <iprt/win/windows.h>
750 #include <ntstatus.h>
751 #include <winternl.h>
752 #include <stdio.h>
753
754 int main()
755 {
756 #define CONVERT(a) printf(#a " %#x -> %d\n", a, RtlNtStatusToDosError((a)))
757 CONVERT(STATUS_SUCCESS);
758 CONVERT(STATUS_NOT_SUPPORTED);
759 CONVERT(STATUS_INVALID_PARAMETER);
760 CONVERT(STATUS_UNKNOWN_REVISION);
761 CONVERT(STATUS_INVALID_HANDLE);
762 CONVERT(STATUS_INVALID_ADDRESS);
763 CONVERT(STATUS_NOT_LOCKED);
764 CONVERT(STATUS_IMAGE_ALREADY_LOADED);
765 CONVERT(STATUS_ACCESS_DENIED);
766 CONVERT(STATUS_REVISION_MISMATCH);
767
768 return 0;
769 }
770 */
771
772 switch (rc)
773 {
774 //case 0: return STATUS_SUCCESS;
775 case 0: return VINF_SUCCESS;
776 case ERROR_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
777 case ERROR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
778 case ERROR_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
779 case ERROR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
780 case ERROR_UNEXP_NET_ERR: return VERR_INVALID_POINTER;
781 case ERROR_NOT_LOCKED: return VERR_LOCK_FAILED;
782 case ERROR_SERVICE_ALREADY_RUNNING: return VERR_ALREADY_LOADED;
783 case ERROR_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
784 case ERROR_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
785 }
786
787 /* fall back on the default conversion. */
788 return RTErrConvertFromWin32(rc);
789}
790# else
791/**
792 * Reverse of VBoxDrvNtErr2NtStatus
793 * returns VBox status code.
794 * @param rcNt NT status code.
795 */
796static int suplibConvertNtStatus(NTSTATUS rcNt)
797{
798 switch (rcNt)
799 {
800 case STATUS_SUCCESS: return VINF_SUCCESS;
801 case STATUS_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
802 case STATUS_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
803 case STATUS_UNKNOWN_REVISION: return VERR_INVALID_MAGIC;
804 case STATUS_INVALID_HANDLE: return VERR_INVALID_HANDLE;
805 case STATUS_INVALID_ADDRESS: return VERR_INVALID_POINTER;
806 case STATUS_NOT_LOCKED: return VERR_LOCK_FAILED;
807 case STATUS_IMAGE_ALREADY_LOADED: return VERR_ALREADY_LOADED;
808 case STATUS_ACCESS_DENIED: return VERR_PERMISSION_DENIED;
809 case STATUS_REVISION_MISMATCH: return VERR_VERSION_MISMATCH;
810 }
811
812 /* See VBoxDrvNtErr2NtStatus. */
813 if (SUP_NT_STATUS_IS_VBOX(rcNt))
814 return SUP_NT_STATUS_TO_VBOX(rcNt);
815
816 /* Fall back on IPRT for the rest. */
817 return RTErrConvertFromNtStatus(rcNt);
818}
819# endif
820
821#endif /* !IN_SUP_HARDENED_R3 */
822
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use