VirtualBox

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

Last change on this file since 53002 was 53002, checked in by vboxsync, 10 years ago

VBoxDrv-win.cpp: Keep the error info string from failed VBoxDrv and VBoxDrvStub open operations so userland can give us better messages to work on. Fixeds a couple of odd bugs.

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