VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp@ 2676

Last change on this file since 2676 was 2653, checked in by vboxsync, 17 years ago

tag.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.1 KB
Line 
1/** @file
2 *
3 * VBox host drivers - Ring-0 support drivers - Win32 host:
4 * Win32 host driver code
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23
24
25/*******************************************************************************
26* Header Files *
27*******************************************************************************/
28#include "SUPDRV.h"
29#include <excpt.h>
30#include <iprt/assert.h>
31#include <iprt/process.h>
32
33
34/*******************************************************************************
35* Defined Constants And Macros *
36*******************************************************************************/
37/** The support service name. */
38#define SERVICE_NAME "VBoxDrv"
39/** Win32 Device name. */
40#define DEVICE_NAME "\\\\.\\VBoxDrv"
41/** NT Device name. */
42#define DEVICE_NAME_NT L"\\Device\\VBoxDrv"
43/** Win Symlink name. */
44#define DEVICE_NAME_DOS L"\\DosDevices\\VBoxDrv"
45/** The Pool tag (VBox). */
46#define SUPDRV_NT_POOL_TAG 'xoBV'
47
48
49/*******************************************************************************
50* Structures and Typedefs *
51*******************************************************************************/
52#if 0 //def __AMD64__
53typedef struct SUPDRVEXECMEM
54{
55 PMDL pMdl;
56 void *pvMapping;
57 void *pvAllocation;
58} SUPDRVEXECMEM, *PSUPDRVEXECMEM;
59#endif
60
61
62/*******************************************************************************
63* Internal Functions *
64*******************************************************************************/
65static void _stdcall VBoxSupDrvUnload(PDRIVER_OBJECT pDrvObj);
66static NTSTATUS _stdcall VBoxSupDrvCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
67static NTSTATUS _stdcall VBoxSupDrvClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
68static NTSTATUS _stdcall VBoxSupDrvDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
69static int VBoxSupDrvDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack);
70static NTSTATUS _stdcall VBoxSupDrvNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
71static NTSTATUS VBoxSupDrvErr2NtStatus(int rc);
72static NTSTATUS VBoxSupDrvGipInit(PSUPDRVDEVEXT pDevExt);
73static void VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt);
74static void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
75static void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
76
77
78/*******************************************************************************
79* Exported Functions *
80*******************************************************************************/
81__BEGIN_DECLS
82ULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
83__END_DECLS
84
85
86/**
87 * Driver entry point.
88 *
89 * @returns appropriate status code.
90 * @param pDrvObj Pointer to driver object.
91 * @param pRegPath Registry base path.
92 */
93ULONG _stdcall DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
94{
95 NTSTATUS rc;
96 dprintf(("VBoxDrv::DriverEntry\n"));
97
98 /*
99 * Create device.
100 * (That means creating a device object and a symbolic link so the DOS
101 * subsystems (OS/2, win32, ++) can access the device.)
102 */
103 UNICODE_STRING DevName;
104 RtlInitUnicodeString(&DevName, DEVICE_NAME_NT);
105 PDEVICE_OBJECT pDevObj;
106 rc = IoCreateDevice(pDrvObj, sizeof(SUPDRVDEVEXT), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
107 if (NT_SUCCESS(rc))
108 {
109 UNICODE_STRING DosName;
110 RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
111 rc = IoCreateSymbolicLink(&DosName, &DevName);
112 if (NT_SUCCESS(rc))
113 {
114 /*
115 * Initialize the device extension.
116 */
117 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
118 memset(pDevExt, 0, sizeof(*pDevExt));
119 int vrc = supdrvInitDevExt(pDevExt);
120 if (!vrc)
121 {
122 /*
123 * Inititalize the GIP.
124 */
125 rc = VBoxSupDrvGipInit(pDevExt);
126 if (NT_SUCCESS(rc))
127 {
128 /*
129 * Setup the driver entry points in pDrvObj.
130 */
131 pDrvObj->DriverUnload = VBoxSupDrvUnload;
132 pDrvObj->MajorFunction[IRP_MJ_CREATE] = VBoxSupDrvCreate;
133 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = VBoxSupDrvClose;
134 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VBoxSupDrvDeviceControl;
135 pDrvObj->MajorFunction[IRP_MJ_READ] = VBoxSupDrvNotSupportedStub;
136 pDrvObj->MajorFunction[IRP_MJ_WRITE] = VBoxSupDrvNotSupportedStub;
137 /* more? */
138 dprintf(("VBoxDrv::DriverEntry returning STATUS_SUCCESS\n"));
139 return STATUS_SUCCESS;
140 }
141 dprintf(("VBoxSupDrvGipInit failed with rc=%#x!\n", rc));
142
143 supdrvDeleteDevExt(pDevExt);
144 }
145 else
146 {
147 dprintf(("supdrvInitDevExit failed with vrc=%d!\n", vrc));
148 rc = VBoxSupDrvErr2NtStatus(vrc);
149 }
150
151 IoDeleteSymbolicLink(&DosName);
152 }
153 else
154 dprintf(("IoCreateSymbolicLink failed with rc=%#x!\n", rc));
155
156 IoDeleteDevice(pDevObj);
157 }
158 else
159 dprintf(("IoCreateDevice failed with rc=%#x!\n", rc));
160
161 if (NT_SUCCESS(rc))
162 rc = STATUS_INVALID_PARAMETER;
163 dprintf(("VBoxDrv::DriverEntry returning %#x\n", rc));
164 return rc;
165}
166
167
168/**
169 * Unload the driver.
170 *
171 * @param pDrvObj Driver object.
172 */
173void _stdcall VBoxSupDrvUnload(PDRIVER_OBJECT pDrvObj)
174{
175 dprintf(("VBoxSupDrvUnload\n"));
176 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDrvObj->DeviceObject->DeviceExtension;
177
178 /*
179 * We ASSUME that it's not possible to unload a driver with open handles.
180 * Start by deleting the symbolic link
181 */
182 UNICODE_STRING DosName;
183 RtlInitUnicodeString(&DosName, DEVICE_NAME_DOS);
184 NTSTATUS rc = IoDeleteSymbolicLink(&DosName);
185
186 /*
187 * Terminate the GIP page and delete the device extension.
188 */
189 VBoxSupDrvGipTerm(pDevExt);
190 supdrvDeleteDevExt(pDevExt);
191 IoDeleteDevice(pDrvObj->DeviceObject);
192}
193
194
195/**
196 * Create (i.e. Open) file entry point.
197 *
198 * @param pDevObj Device object.
199 * @param pIrp Request packet.
200 */
201NTSTATUS _stdcall VBoxSupDrvCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
202{
203 dprintf(("VBoxSupDrvCreate\n"));
204 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
205 PFILE_OBJECT pFileObj = pStack->FileObject;
206 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
207
208 /*
209 * We are not remotely similar to a directory...
210 * (But this is possible.)
211 */
212 if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
213 {
214 pIrp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
215 pIrp->IoStatus.Information = 0;
216 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
217 return STATUS_NOT_A_DIRECTORY;
218 }
219
220 /*
221 * Call common code for the rest.
222 */
223 pFileObj->FsContext = NULL;
224 PSUPDRVSESSION pSession;
225 int rc = supdrvCreateSession(pDevExt, &pSession);
226 if (!rc)
227 {
228 pSession->Uid = NIL_RTUID;
229 pSession->Gid = NIL_RTGID;
230 pSession->Process = RTProcSelf();
231 pSession->R0Process = RTR0ProcHandleSelf();
232 pFileObj->FsContext = pSession;
233 }
234
235 NTSTATUS rcNt = pIrp->IoStatus.Status = VBoxSupDrvErr2NtStatus(rc);
236 pIrp->IoStatus.Information = 0;
237 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
238
239 return rcNt;
240}
241
242
243/**
244 * Close file entry point.
245 *
246 * @param pDevObj Device object.
247 * @param pIrp Request packet.
248 */
249NTSTATUS _stdcall VBoxSupDrvClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
250{
251 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
252 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
253 PFILE_OBJECT pFileObj = pStack->FileObject;
254 dprintf(("VBoxSupDrvClose: pDevExt=%p pFileObj=%p pSession=%p\n",
255 pDevExt, pFileObj, pFileObj->FsContext));
256 supdrvCloseSession(pDevExt, (PSUPDRVSESSION)pFileObj->FsContext);
257 pFileObj->FsContext = NULL;
258 pIrp->IoStatus.Information = 0;
259 pIrp->IoStatus.Status = STATUS_SUCCESS;
260 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
261
262 return STATUS_SUCCESS;
263}
264
265
266/**
267 * Device I/O Control entry point.
268 *
269 * @param pDevObj Device object.
270 * @param pIrp Request packet.
271 */
272NTSTATUS _stdcall VBoxSupDrvDeviceControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
273{
274 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pDevObj->DeviceExtension;
275 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
276 PSUPDRVSESSION pSession = (PSUPDRVSESSION)pStack->FileObject->FsContext;
277
278#ifdef VBOX_WITHOUT_IDT_PATCHING
279 /*
280 * Deal with the two high-speed IOCtl that takes it's arguments from
281 * the session and iCmd, and only returns a VBox status code.
282 */
283 ULONG ulCmd = pStack->Parameters.DeviceIoControl.IoControlCode;
284 if ( ulCmd == SUP_IOCTL_FAST_DO_RAW_RUN
285 || ulCmd == SUP_IOCTL_FAST_DO_HWACC_RUN
286 || ulCmd == SUP_IOCTL_FAST_DO_NOP)
287 {
288 int rc = supdrvIOCtlFast(ulCmd, pDevExt, pSession);
289
290 /* Complete the I/O request. */
291 NTSTATUS rcNt = pIrp->IoStatus.Status = STATUS_SUCCESS;
292 pIrp->IoStatus.Information = sizeof(rc);
293 __try
294 {
295 *(int *)pIrp->UserBuffer = rc;
296 }
297 __except(EXCEPTION_EXECUTE_HANDLER)
298 {
299 rcNt = pIrp->IoStatus.Status = GetExceptionCode();
300 dprintf(("VBoxSupDrvDeviceContorl: Exception Code %#x\n", rcNt));
301 }
302 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
303 return rcNt;
304 }
305#endif /* VBOX_WITHOUT_IDT_PATCHING */
306
307 return VBoxSupDrvDeviceControlSlow(pDevExt, pSession, pIrp, pStack);
308}
309
310
311/**
312 * Worker for VBoxSupDrvDeviceControl that takes the slow IOCtl functions.
313 *
314 * @returns NT status code.
315 *
316 * @param pDevObj Device object.
317 * @param pSession The session.
318 * @param pIrp Request packet.
319 * @param pStack The stack location containing the DeviceControl parameters.
320 */
321static int VBoxSupDrvDeviceControlSlow(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PIRP pIrp, PIO_STACK_LOCATION pStack)
322{
323 NTSTATUS rcNt = STATUS_NOT_SUPPORTED;
324 unsigned cbOut = 0;
325 int rc = 0;
326 dprintf2(("VBoxSupDrvDeviceControlSlow(%p,%p): ioctl=%#x pBuf=%p cbIn=%#x cbOut=%#x pSession=%p\n",
327 pDevObj, pIrp, pStack->Parameters.DeviceIoControl.IoControlCode,
328 pBuf, pStack->Parameters.DeviceIoControl.InputBufferLength,
329 pStack->Parameters.DeviceIoControl.OutputBufferLength, pSession));
330
331#ifdef __AMD64__
332 /* Don't allow 32-bit processes to do any I/O controls. */
333 if (!IoIs32bitProcess(pIrp))
334#endif
335 {
336 /* Verify that it's a buffered CTL. */
337 if ((pStack->Parameters.DeviceIoControl.IoControlCode & 0x3) == METHOD_BUFFERED)
338 {
339 char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer;
340
341 /*
342 * Do the job.
343 */
344 rc = supdrvIOCtl(pStack->Parameters.DeviceIoControl.IoControlCode, pDevExt, pSession,
345 pBuf, pStack->Parameters.DeviceIoControl.InputBufferLength,
346 pBuf, pStack->Parameters.DeviceIoControl.OutputBufferLength,
347 &cbOut);
348 rcNt = VBoxSupDrvErr2NtStatus(rc);
349
350 /* sanity check. */
351 AssertMsg(cbOut <= pStack->Parameters.DeviceIoControl.OutputBufferLength,
352 ("cbOut is too large! cbOut=%d max=%d! ioctl=%#x\n",
353 cbOut, pStack->Parameters.DeviceIoControl.OutputBufferLength,
354 pStack->Parameters.DeviceIoControl.IoControlCode));
355 if (cbOut > pStack->Parameters.DeviceIoControl.OutputBufferLength)
356 cbOut = pStack->Parameters.DeviceIoControl.OutputBufferLength;
357 dprintf2(("VBoxSupDrvDeviceControlSlow: returns %#x cbOut=%d rc=%#x\n", rcNt, cbOut, rc));
358 }
359 else
360 dprintf(("VBoxSupDrvDeviceControlSlow: not buffered request (%#x) - not supported\n",
361 pStack->Parameters.DeviceIoControl.IoControlCode));
362 }
363#ifdef __AMD64__
364 else
365 dprintf(("VBoxSupDrvDeviceControlSlow: WOW64 req - not supported\n"));
366#endif
367
368 /* complete the request. */
369 pIrp->IoStatus.Status = rcNt;
370 pIrp->IoStatus.Information = NT_SUCCESS(rcNt) ? cbOut : rc; /* does this rc passing actually work?!? */
371 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
372 return rcNt;
373}
374
375
376/**
377 * Stub function for functions we don't implemented.
378 *
379 * @returns STATUS_NOT_SUPPORTED
380 * @param pDevObj Device object.
381 * @param pIrp IRP.
382 */
383NTSTATUS _stdcall VBoxSupDrvNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
384{
385 dprintf(("VBoxSupDrvNotSupportedStub\n"));
386 pDevObj = pDevObj;
387
388 pIrp->IoStatus.Information = 0;
389 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
390 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
391
392 return STATUS_NOT_SUPPORTED;
393}
394
395
396/**
397 * Initializes any OS specific object creator fields.
398 */
399void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
400{
401 NOREF(pObj);
402 NOREF(pSession);
403}
404
405
406/**
407 * Checks if the session can access the object.
408 *
409 * @returns true if a decision has been made.
410 * @returns false if the default access policy should be applied.
411 *
412 * @param pObj The object in question.
413 * @param pSession The session wanting to access the object.
414 * @param pszObjName The object name, can be NULL.
415 * @param prc Where to store the result when returning true.
416 */
417bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
418{
419 NOREF(pObj);
420 NOREF(pSession);
421 NOREF(pszObjName);
422 NOREF(prc);
423 return false;
424}
425
426
427/**
428 * OS Specific code for locking down memory.
429 *
430 * @returns 0 on success.
431 * @returns SUPDRV_ERR_* on failure.
432 * @param pMem Pointer to memory.
433 * This is not linked in anywhere.
434 * @param paPages Array which should be filled with the address of the physical pages.
435 */
436int VBOXCALL supdrvOSLockMemOne(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
437{
438 /* paranoia */
439 if (!pMem->cb)
440 {
441 AssertMsgFailed(("Fool! No memory to lock!\n"));
442 return SUPDRV_ERR_INVALID_PARAM;
443 }
444 Assert(RT_ALIGN(pMem->cb, PAGE_SIZE) == pMem->cb);
445
446 /*
447 * Calc the number of MDLs we need to allocate.
448 */
449 unsigned cMdls = pMem->cb / MAX_LOCK_MEM_SIZE;
450 if ((pMem->cb % MAX_LOCK_MEM_SIZE) > 0)
451 cMdls++;
452
453 /*
454 * Allocate memory for the MDL pointer array.
455 */
456 pMem->u.locked.papMdl = (PMDL *)ExAllocatePoolWithTag(NonPagedPool, sizeof(*pMem->u.locked.papMdl) * cMdls, SUPDRV_NT_POOL_TAG);
457 if (!pMem->u.locked.papMdl)
458 {
459 AssertMsgFailed(("shit, couldn't allocated %d bytes for the mdl pointer array!\n", sizeof(*pMem->u.locked.papMdl) * cMdls));
460 return SUPDRV_ERR_NO_MEMORY;
461 }
462
463 /*
464 * Loop locking down the sub parts of the memory.
465 */
466 PSUPPAGE pPage = paPages;
467 unsigned cbTotal = 0;
468 uint8_t *pu8 = (uint8_t *)pMem->pvR3;
469 for (unsigned i = 0; i < cMdls; i++)
470 {
471 /*
472 * Calc the number of bytes to lock this time.
473 */
474 unsigned cbCur = pMem->cb - cbTotal;
475 if (cbCur > MAX_LOCK_MEM_SIZE)
476 cbCur = MAX_LOCK_MEM_SIZE;
477
478 if (cbCur == 0)
479 AssertMsgFailed(("cbCur: 0!\n"));
480
481 /*
482 * Allocate pMdl.
483 */
484 PMDL pMdl = IoAllocateMdl(pu8, cbCur, FALSE, FALSE, NULL);
485 if (!pMdl)
486 {
487 AssertMsgFailed(("Ops! IoAllocateMdl failed for pu8=%p and cb=%d\n", pu8, cbCur));
488 return SUPDRV_ERR_NO_MEMORY;
489 }
490
491 /*
492 * Lock the pages.
493 */
494 NTSTATUS rc = STATUS_SUCCESS;
495 __try
496 {
497 MmProbeAndLockPages(pMdl, UserMode, IoModifyAccess);
498 }
499 __except(EXCEPTION_EXECUTE_HANDLER)
500 {
501 rc = GetExceptionCode();
502 dprintf(("supdrvOSLockMemOne: Exception Code %#x\n", rc));
503 }
504
505 if (!NT_SUCCESS(rc))
506 {
507 /*
508 * Cleanup and fail.
509 */
510 IoFreeMdl(pMdl);
511 while (i-- > 0)
512 {
513 MmUnlockPages(pMem->u.locked.papMdl[i]);
514 IoFreeMdl(pMem->u.locked.papMdl[i]);
515 }
516 ExFreePool(pMem->u.locked.papMdl);
517 pMem->u.locked.papMdl = NULL;
518 return SUPDRV_ERR_LOCK_FAILED;
519 }
520
521 /*
522 * Add MDL to array and update the pages.
523 */
524 pMem->u.locked.papMdl[i] = pMdl;
525
526 const uintptr_t *pauPFNs = (uintptr_t *)(pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
527 for (unsigned iPage = 0, cPages = cbCur >> PAGE_SHIFT; iPage < cPages; iPage++)
528 {
529 pPage->Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
530 pPage->uReserved = 0;
531 pPage++;
532 }
533
534 /* next */
535 cbTotal += cbCur;
536 pu8 += cbCur;
537 }
538
539 /*
540 * Finish structure and return succesfully.
541 */
542 pMem->u.locked.cMdls = cMdls;
543
544 dprintf2(("supdrvOSLockMemOne: pvR3=%p cb=%d cMdls=%d\n",
545 pMem->pvR3, pMem->cb, cMdls));
546 return 0;
547}
548
549
550/**
551 * Unlocks the memory pointed to by pv.
552 *
553 * @param pv Memory to unlock.
554 * @param cb Size of the memory (debug).
555 */
556void VBOXCALL supdrvOSUnlockMemOne(PSUPDRVMEMREF pMem)
557{
558 dprintf2(("supdrvOSUnlockMemOne: pvR3=%p cb=%d cMdl=%p papMdl=%p\n",
559 pMem->pvR3, pMem->cb, pMem->u.locked.cMdls, pMem->u.locked.papMdl));
560
561 for (unsigned i = 0; i < pMem->u.locked.cMdls; i++)
562 {
563 MmUnlockPages(pMem->u.locked.papMdl[i]);
564 IoFreeMdl(pMem->u.locked.papMdl[i]);
565 }
566
567 ExFreePool(pMem->u.locked.papMdl);
568 pMem->u.locked.papMdl = NULL;
569}
570
571
572/**
573 * OS Specific code for allocating page aligned memory with continuous fixed
574 * physical paged backing.
575 *
576 * @returns 0 on success.
577 * @returns SUPDRV_ERR_* on failure.
578 * @param pMem Memory reference record of the memory to be allocated.
579 * (This is not linked in anywhere.)
580 * @param ppvR0 Where to store the virtual address of the ring-0 mapping. (optional)
581 * @param ppvR3 Where to store the virtual address of the ring-3 mapping.
582 * @param pHCPhys Where to store the physical address.
583 */
584int VBOXCALL supdrvOSContAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys)
585{
586 Assert(ppvR3);
587 Assert(pHCPhys);
588
589 /*
590 * Try allocate the memory.
591 */
592 PHYSICAL_ADDRESS Phys;
593 Phys.HighPart = 0;
594 Phys.LowPart = ~0;
595 unsigned cbAligned = RT_ALIGN(pMem->cb, PAGE_SIZE);
596 pMem->pvR0 = MmAllocateContiguousMemory(cbAligned, Phys);
597 if (!pMem->pvR0)
598 return SUPDRV_ERR_NO_MEMORY;
599
600 /*
601 * Map into user space.
602 */
603 int rc = SUPDRV_ERR_NO_MEMORY;
604 pMem->u.cont.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
605 if (pMem->u.cont.pMdl)
606 {
607 MmBuildMdlForNonPagedPool(pMem->u.cont.pMdl);
608 __try
609 {
610 pMem->pvR3 = (RTR3PTR)MmMapLockedPages(pMem->u.cont.pMdl, UserMode);
611 if (pMem->pvR3)
612 {
613 /*
614 * Done, setup pMem and return values.
615 */
616#ifdef __AMD64__
617 MmProtectMdlSystemAddress(pMem->u.cont.pMdl, PAGE_EXECUTE_READWRITE);
618#endif
619 *ppvR3 = pMem->pvR3;
620 if (ppvR0)
621 *ppvR0 = pMem->pvR0;
622 const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.cont.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK4 doesn't have ULONG_PTR. */
623 *pHCPhys = (RTHCPHYS)pauPFNs[0] << PAGE_SHIFT;
624 dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p *pHCPhys=%VHp\n",
625 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl, *pHCPhys));
626 return 0;
627 }
628 }
629 __except(EXCEPTION_EXECUTE_HANDLER)
630 {
631 NTSTATUS rc = GetExceptionCode();
632 dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
633 }
634 IoFreeMdl(pMem->u.cont.pMdl);
635 rc = SUPDRV_ERR_LOCK_FAILED;
636 }
637 MmFreeContiguousMemory(pMem->pvR0);
638 pMem->pvR0 = NULL;
639 return rc;
640}
641
642
643/**
644 * Frees contiguous memory.
645 *
646 * @param pMem Memory reference record of the memory to be freed.
647 */
648void VBOXCALL supdrvOSContFreeOne(PSUPDRVMEMREF pMem)
649{
650 __try
651 {
652 dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
653 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.cont.pMdl));
654 if (pMem->pvR3)
655 {
656 MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.cont.pMdl);
657 dprintf2(("MmUnmapLockedPages ok!\n"));
658 pMem->pvR3 = NULL;
659 }
660
661 IoFreeMdl(pMem->u.cont.pMdl);
662 dprintf2(("IoFreeMdl ok!\n"));
663 pMem->u.cont.pMdl = NULL;
664
665 MmFreeContiguousMemory(pMem->pvR0);
666 dprintf2(("MmFreeContiguousMemory ok!\n"));
667 pMem->pvR0 = NULL;
668 }
669 __except(EXCEPTION_EXECUTE_HANDLER)
670 {
671 NTSTATUS rc = GetExceptionCode();
672 dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
673 }
674}
675
676
677/**
678 * Allocates memory which mapped into both kernel and user space.
679 * The returned memory is page aligned and so is the allocation.
680 *
681 * @returns 0 on success.
682 * @returns SUPDRV_ERR_* on failure.
683 * @param pMem Memory reference record of the memory to be allocated.
684 * (This is not linked in anywhere.)
685 * @param ppvR0 Where to store the address of the Ring-0 mapping.
686 * @param ppvR3 Where to store the address of the Ring-3 mapping.
687 */
688int VBOXCALL supdrvOSMemAllocOne(PSUPDRVMEMREF pMem, PRTR0PTR ppvR0, PRTR3PTR ppvR3)
689{
690 Assert(ppvR0);
691 Assert(ppvR3);
692
693 /*
694 * Try allocate the memory.
695 */
696 unsigned cbAligned = RT_ALIGN(RT_MAX(pMem->cb, PAGE_SIZE * 2), PAGE_SIZE);
697 pMem->pvR0 = ExAllocatePoolWithTag(NonPagedPool, cbAligned, SUPDRV_NT_POOL_TAG);
698 if (!pMem->pvR0)
699 return SUPDRV_ERR_NO_MEMORY;
700
701 /*
702 * Map into user space.
703 */
704 int rc = SUPDRV_ERR_NO_MEMORY;
705 pMem->u.mem.pMdl = IoAllocateMdl(pMem->pvR0, cbAligned, FALSE, FALSE, NULL);
706 if (pMem->u.mem.pMdl)
707 {
708 MmBuildMdlForNonPagedPool(pMem->u.mem.pMdl);
709 __try
710 {
711 pMem->pvR3 = (RTR3PTR)MmMapLockedPages(pMem->u.mem.pMdl, UserMode);
712 if (pMem->pvR3)
713 {
714 /*
715 * Done, setup pMem and return values.
716 */
717 *ppvR3 = pMem->pvR3;
718 *ppvR0 = pMem->pvR0;
719 dprintf2(("supdrvOSContAllocOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
720 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
721 return 0;
722 }
723 }
724 __except(EXCEPTION_EXECUTE_HANDLER)
725 {
726 NTSTATUS rc = GetExceptionCode();
727 dprintf(("supdrvOSContAllocOne: Exception Code %#x\n", rc));
728 }
729 rc = SUPDRV_ERR_LOCK_FAILED;
730
731 IoFreeMdl(pMem->u.mem.pMdl);
732 pMem->u.mem.pMdl = NULL;
733 pMem->pvR3 = NULL;
734 }
735
736 MmFreeContiguousMemory(pMem->pvR0);
737 pMem->pvR0 = NULL;
738 return rc;
739}
740
741
742/**
743 * Get the physical addresses of the pages in the allocation.
744 * This is called while inside bundle the spinlock.
745 *
746 * @param pMem Memory reference record of the memory.
747 * @param paPages Where to store the page addresses.
748 */
749void VBOXCALL supdrvOSMemGetPages(PSUPDRVMEMREF pMem, PSUPPAGE paPages)
750{
751 const unsigned cPages = RT_ALIGN(pMem->cb, PAGE_SIZE) >> PAGE_SHIFT;
752 const uintptr_t *pauPFNs = (const uintptr_t *)(pMem->u.mem.pMdl + 1); /* ASSUMES ULONG_PTR == uintptr_t, NTDDK doesn't have ULONG_PTR. */
753 for (unsigned iPage = 0; iPage < cPages; iPage++)
754 {
755 paPages[iPage].Phys = (RTHCPHYS)pauPFNs[iPage] << PAGE_SHIFT;
756 paPages[iPage].uReserved = 0;
757 }
758}
759
760
761/**
762 * Frees memory allocated by supdrvOSMemAllocOne().
763 *
764 * @param pMem Memory reference record of the memory to be free.
765 */
766void VBOXCALL supdrvOSMemFreeOne(PSUPDRVMEMREF pMem)
767{
768 __try
769 {
770 dprintf2(("supdrvOSContFreeOne: pvR0=%p pvR3=%p cb=%d pMdl=%p\n",
771 pMem->pvR0, pMem->pvR3, pMem->cb, pMem->u.mem.pMdl));
772 if (pMem->pvR3)
773 {
774 MmUnmapLockedPages((void *)pMem->pvR3, pMem->u.mem.pMdl);
775 pMem->pvR3 = NULL;
776 dprintf2(("MmUnmapLockedPages ok!\n"));
777 }
778
779 IoFreeMdl(pMem->u.mem.pMdl);
780 pMem->u.mem.pMdl = NULL;
781 dprintf2(("IoFreeMdl ok!\n"));
782
783 ExFreePool(pMem->pvR0);
784 pMem->pvR0 = NULL;
785 dprintf2(("MmFreeContiguousMemory ok!\n"));
786 }
787 __except(EXCEPTION_EXECUTE_HANDLER)
788 {
789 NTSTATUS rc = GetExceptionCode();
790 dprintf(("supdrvOSContFreeOne: Exception Code %#x\n", rc));
791 }
792}
793
794
795/**
796 * Gets the monotone timestamp (nano seconds).
797 * @returns NanoTS.
798 */
799static inline uint64_t supdrvOSMonotime(void)
800{
801 return (uint64_t)KeQueryInterruptTime() * 100;
802}
803
804
805/**
806 * Initializes the GIP.
807 *
808 * @returns NT status code.
809 * @param pDevExt Instance data. GIP stuff may be updated.
810 */
811static NTSTATUS VBoxSupDrvGipInit(PSUPDRVDEVEXT pDevExt)
812{
813 dprintf2(("VBoxSupDrvTermGip:\n"));
814
815 /*
816 * Try allocate the memory.
817 * Make sure it's below 4GB for 32-bit GC support
818 */
819 NTSTATUS rc;
820 PHYSICAL_ADDRESS Phys;
821 Phys.HighPart = 0;
822 Phys.LowPart = ~0;
823 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)MmAllocateContiguousMemory(PAGE_SIZE, Phys);
824 if (pGip)
825 {
826 if (!((uintptr_t)pGip & (PAGE_SIZE - 1)))
827 {
828 pDevExt->pGipMdl = IoAllocateMdl(pGip, PAGE_SIZE, FALSE, FALSE, NULL);
829 if (pDevExt->pGipMdl)
830 {
831 MmBuildMdlForNonPagedPool(pDevExt->pGipMdl);
832
833 /*
834 * Figure the timer interval and frequency.
835 * It turns out trying 1023Hz doesn't work. So, we'll set the max Hz at 128 for now.
836 */
837 ExSetTimerResolution(156250, TRUE);
838 ULONG ulClockIntervalActual = ExSetTimerResolution(0, FALSE);
839 ULONG ulClockInterval = RT_MAX(ulClockIntervalActual, 78125); /* 1/128 */
840 ULONG ulClockFreq = 10000000 / ulClockInterval;
841 pDevExt->ulGipTimerInterval = ulClockInterval / 10000; /* ms */
842
843 /*
844 * Call common initialization routine.
845 */
846 Phys = MmGetPhysicalAddress(pGip); /* could perhaps use the Mdl, not that it looks much better */
847 supdrvGipInit(pDevExt, pGip, (RTHCPHYS)Phys.QuadPart, supdrvOSMonotime(), ulClockFreq);
848
849 /*
850 * Initialize the timer.
851 */
852 KeInitializeTimerEx(&pDevExt->GipTimer, SynchronizationTimer);
853 KeInitializeDpc(&pDevExt->GipDpc, VBoxSupDrvGipTimer, pDevExt);
854
855 /*
856 * Initialize the DPCs we're using to update the per-cpu GIP data.
857 * (Not sure if we need to be this careful with KeSetTargetProcessorDpc...)
858 */
859 UNICODE_STRING RoutineName;
860 RtlInitUnicodeString(&RoutineName, L"KeSetTargetProcessorDpc");
861 VOID (*pfnKeSetTargetProcessorDpc)(IN PRKDPC, IN CCHAR) = (VOID (*)(IN PRKDPC, IN CCHAR))MmGetSystemRoutineAddress(&RoutineName);
862
863 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
864 {
865 KeInitializeDpc(&pDevExt->aGipCpuDpcs[i], VBoxSupDrvGipPerCpuDpc, pGip);
866 KeSetImportanceDpc(&pDevExt->aGipCpuDpcs[i], HighImportance);
867 if (pfnKeSetTargetProcessorDpc)
868 pfnKeSetTargetProcessorDpc(&pDevExt->aGipCpuDpcs[i], i);
869 }
870
871 dprintf(("VBoxSupDrvGipInit: ulClockFreq=%ld ulClockInterval=%ld ulClockIntervalActual=%ld Phys=%x%08x\n",
872 ulClockFreq, ulClockInterval, ulClockIntervalActual, Phys.HighPart, Phys.LowPart));
873 return STATUS_SUCCESS;
874 }
875
876 dprintf(("VBoxSupDrvInitGip: IoAllocateMdl failed for %p/PAGE_SIZE\n", pGip));
877 rc = STATUS_NO_MEMORY;
878 }
879 else
880 {
881 dprintf(("VBoxSupDrvInitGip: GIP memory is not page aligned! pGip=%p\n", pGip));
882 rc = STATUS_INVALID_ADDRESS;
883 }
884 MmFreeContiguousMemory(pGip);
885 }
886 else
887 {
888 dprintf(("VBoxSupDrvInitGip: no cont memory.\n"));
889 rc = STATUS_NO_MEMORY;
890 }
891 return rc;
892}
893
894
895/**
896 * Terminates the GIP.
897 *
898 * @returns negative errno.
899 * @param pDevExt Instance data. GIP stuff may be updated.
900 */
901static void VBoxSupDrvGipTerm(PSUPDRVDEVEXT pDevExt)
902{
903 dprintf(("VBoxSupDrvTermGip:\n"));
904 PSUPGLOBALINFOPAGE pGip;
905
906 /*
907 * Cancel the timer and wait on DPCs if it was still pending.
908 */
909 if (KeCancelTimer(&pDevExt->GipTimer))
910 {
911 UNICODE_STRING RoutineName;
912 RtlInitUnicodeString(&RoutineName, L"KeFlushQueuedDpcs");
913 VOID (*pfnKeFlushQueuedDpcs)(VOID) = (VOID (*)(VOID))MmGetSystemRoutineAddress(&RoutineName);
914 if (pfnKeFlushQueuedDpcs)
915 pfnKeFlushQueuedDpcs();
916 }
917
918 /*
919 * Uninitialize the content.
920 */
921 pGip = pDevExt->pGip;
922 pDevExt->pGip = NULL;
923 if (pGip)
924 {
925 supdrvGipTerm(pGip);
926
927 /*
928 * Free the page.
929 */
930 if (pDevExt->pGipMdl)
931 {
932 IoFreeMdl(pDevExt->pGipMdl);
933 pDevExt->pGipMdl = NULL;
934 }
935 MmFreeContiguousMemory(pGip);
936 }
937}
938
939
940/**
941 * Timer callback function.
942 * The pvUser parameter is the pDevExt pointer.
943 */
944static void _stdcall VBoxSupDrvGipTimer(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
945{
946 PSUPDRVDEVEXT pDevExt = (PSUPDRVDEVEXT)pvUser;
947 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip;
948 if (pGip)
949 {
950 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
951 supdrvGipUpdate(pGip, supdrvOSMonotime());
952 else
953 {
954 RTCCUINTREG xFL = ASMGetFlags();
955 ASMIntDisable();
956
957 /*
958 * We cannot do other than assume a 1:1 relation ship between the
959 * affinity mask and the process despite the warnings in the docs.
960 * If someone knows a better way to get this done, please let bird know.
961 */
962 unsigned iSelf = KeGetCurrentProcessorNumber();
963 KAFFINITY Mask = KeQueryActiveProcessors();
964
965 for (unsigned i = 0; i < RT_ELEMENTS(pDevExt->aGipCpuDpcs); i++)
966 {
967 if ( i != iSelf
968 && (Mask & RT_BIT_64(i)))
969 KeInsertQueueDpc(&pDevExt->aGipCpuDpcs[i], 0, 0);
970 }
971
972 /* Run the normal update. */
973 supdrvGipUpdate(pGip, supdrvOSMonotime());
974
975 ASMSetFlags(xFL);
976 }
977 }
978}
979
980
981/**
982 * Per cpu callback callback function.
983 * The pvUser parameter is the pGip pointer.
984 */
985static void _stdcall VBoxSupDrvGipPerCpuDpc(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
986{
987 PSUPGLOBALINFOPAGE pGip = (PSUPGLOBALINFOPAGE)pvUser;
988 supdrvGipUpdatePerCpu(pGip, supdrvOSMonotime(), ASMGetApicId());
989}
990
991
992/**
993 * Maps the GIP into user space.
994 *
995 * @returns negative errno.
996 * @param pDevExt Instance data.
997 */
998int VBOXCALL supdrvOSGipMap(PSUPDRVDEVEXT pDevExt, PCSUPGLOBALINFOPAGE *ppGip)
999{
1000 dprintf2(("supdrvOSGipMap: ppGip=%p (pDevExt->pGipMdl=%p)\n", ppGip, pDevExt->pGipMdl));
1001
1002 /*
1003 * Map into user space.
1004 */
1005 int rc = 0;
1006 void *pv = NULL;
1007 __try
1008 {
1009 *ppGip = (PCSUPGLOBALINFOPAGE)MmMapLockedPages(pDevExt->pGipMdl, UserMode);
1010 }
1011 __except(EXCEPTION_EXECUTE_HANDLER)
1012 {
1013 NTSTATUS rcNt = GetExceptionCode();
1014 dprintf(("supdrvOsGipMap: Exception Code %#x\n", rcNt));
1015 rc = SUPDRV_ERR_LOCK_FAILED;
1016 }
1017
1018 dprintf2(("supdrvOSGipMap: returns %d, *ppGip=%p\n", rc, *ppGip));
1019 return 0;
1020}
1021
1022
1023/**
1024 * Maps the GIP into user space.
1025 *
1026 * @returns negative errno.
1027 * @param pDevExt Instance data.
1028 */
1029int VBOXCALL supdrvOSGipUnmap(PSUPDRVDEVEXT pDevExt, PCSUPGLOBALINFOPAGE pGip)
1030{
1031 dprintf2(("supdrvOSGipUnmap: pGip=%p (pGipMdl=%p)\n", pGip, pDevExt->pGipMdl));
1032
1033 int rc = 0;
1034 __try
1035 {
1036 MmUnmapLockedPages((void *)pGip, pDevExt->pGipMdl);
1037 }
1038 __except(EXCEPTION_EXECUTE_HANDLER)
1039 {
1040 NTSTATUS rcNt = GetExceptionCode();
1041 dprintf(("supdrvOSGipUnmap: Exception Code %#x\n", rcNt));
1042 rc = SUPDRV_ERR_GENERAL_FAILURE;
1043 }
1044 dprintf2(("supdrvOSGipUnmap: returns %d\n", rc));
1045 return rc;
1046}
1047
1048
1049/**
1050 * Resumes the GIP updating.
1051 *
1052 * @param pDevExt Instance data.
1053 */
1054void VBOXCALL supdrvOSGipResume(PSUPDRVDEVEXT pDevExt)
1055{
1056 dprintf2(("supdrvOSGipResume:\n"));
1057 LARGE_INTEGER DueTime;
1058 DueTime.QuadPart = -10000; /* 1ms, relative */
1059 KeSetTimerEx(&pDevExt->GipTimer, DueTime, pDevExt->ulGipTimerInterval, &pDevExt->GipDpc);
1060}
1061
1062
1063/**
1064 * Suspends the GIP updating.
1065 *
1066 * @param pDevExt Instance data.
1067 */
1068void VBOXCALL supdrvOSGipSuspend(PSUPDRVDEVEXT pDevExt)
1069{
1070 dprintf2(("supdrvOSGipSuspend:\n"));
1071 KeCancelTimer(&pDevExt->GipTimer);
1072#ifdef __AMD64__
1073 ExSetTimerResolution(0, FALSE);
1074#endif
1075}
1076
1077
1078/**
1079 * Allocate small amounts of memory which is does not have the NX bit set.
1080 *
1081 * @returns Pointer to the allocated memory
1082 * @returns NULL if out of memory.
1083 * @param cb Size of the memory block.
1084 */
1085void *VBOXCALL supdrvOSExecAlloc(size_t cb)
1086{
1087#if 0 //def __AMD64__
1088 cb = RT_ALIGN_Z(cb, PAGE_SIZE);
1089 void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
1090 if (pv)
1091 {
1092 /*
1093 * Create a kernel mapping which we make PAGE_EXECUTE_READWRITE using
1094 * the MmProtectMdlSystemAddress API.
1095 */
1096 int rc = SUPDRV_ERR_NO_MEMORY;
1097 PMDL pMdl = IoAllocateMdl(pv, cb, FALSE, FALSE, NULL);
1098 if (pMdl)
1099 {
1100 MmBuildMdlForNonPagedPool(pMdl);
1101 __try
1102 {
1103 void *pvMapping = MmMapLockedPages(pMdl, KernelMode);
1104 if (pvMapping)
1105 {
1106 NTSTATUS rc = MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
1107 if (NT_SUCCESS(rc))
1108 {
1109 /*
1110 * Create tracking structure and insert it into the list.
1111 */
1112
1113
1114 return pvMapping;
1115 }
1116
1117 MmUnmapLockedPages(pvMapping, pMdl);
1118 }
1119 }
1120 __except(EXCEPTION_EXECUTE_HANDLER)
1121 {
1122 NTSTATUS rc = GetExceptionCode();
1123 dprintf(("supdrvOSExecAlloc: Exception Code %#x\n", rc));
1124 }
1125 IoFreeMdl(pMem->u.mem.pMdl);
1126 }
1127 ExFreePool(pv);
1128 }
1129 dprintf2(("supdrvOSExecAlloc(%d): returns NULL\n", cb));
1130 return NULL;
1131#else
1132 void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, SUPDRV_NT_POOL_TAG);
1133 dprintf2(("supdrvOSExecAlloc(%d): returns %p\n", cb, pv));
1134 return pv;
1135#endif
1136}
1137
1138
1139/**
1140 * Get the current CPU count.
1141 * @returns Number of cpus.
1142 */
1143unsigned VBOXCALL supdrvOSGetCPUCount(void)
1144{
1145 KAFFINITY Mask = KeQueryActiveProcessors();
1146 unsigned cCpus = 0;
1147 unsigned iBit;
1148 for (iBit = 0; iBit < sizeof(Mask) * 8; iBit++)
1149 if (Mask & RT_BIT_64(iBit))
1150 cCpus++;
1151 if (cCpus == 0) /* paranoia */
1152 cCpus = 1;
1153 return cCpus;
1154}
1155
1156
1157/**
1158 * Force async tsc mode (stub).
1159 */
1160bool VBOXCALL supdrvOSGetForcedAsyncTscMode(void)
1161{
1162 return false;
1163}
1164
1165
1166/**
1167 * Converts a supdrv error code to an nt status code.
1168 *
1169 * @returns corresponding nt status code.
1170 * @param rc supdrv error code (SUPDRV_ERR_* defines).
1171 */
1172static NTSTATUS VBoxSupDrvErr2NtStatus(int rc)
1173{
1174 switch (rc)
1175 {
1176 case 0: return STATUS_SUCCESS;
1177 case SUPDRV_ERR_GENERAL_FAILURE: return STATUS_NOT_SUPPORTED;
1178 case SUPDRV_ERR_INVALID_PARAM: return STATUS_INVALID_PARAMETER;
1179 case SUPDRV_ERR_INVALID_MAGIC: return STATUS_UNKNOWN_REVISION;
1180 case SUPDRV_ERR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
1181 case SUPDRV_ERR_INVALID_POINTER: return STATUS_INVALID_ADDRESS;
1182 case SUPDRV_ERR_LOCK_FAILED: return STATUS_NOT_LOCKED;
1183 case SUPDRV_ERR_ALREADY_LOADED: return STATUS_IMAGE_ALREADY_LOADED;
1184 case SUPDRV_ERR_PERMISSION_DENIED: return STATUS_ACCESS_DENIED;
1185 case SUPDRV_ERR_VERSION_MISMATCH: return STATUS_REVISION_MISMATCH;
1186 }
1187
1188 return STATUS_UNSUCCESSFUL;
1189}
1190
1191
1192/** Runtime assert implementation for Native Win32 Ring-0. */
1193RTDECL(void) AssertMsg1(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction)
1194{
1195 DbgPrint("\n!!Assertion Failed!!\n"
1196 "Expression: %s\n"
1197 "Location : %s(%d) %s\n",
1198 pszExpr, pszFile, uLine, pszFunction);
1199}
1200
1201int VBOXCALL mymemcmp(const void *pv1, const void *pv2, size_t cb)
1202{
1203 const uint8_t *pb1 = (const uint8_t *)pv1;
1204 const uint8_t *pb2 = (const uint8_t *)pv2;
1205 for (; cb > 0; cb--, pb1++, pb2++)
1206 if (*pb1 != *pb2)
1207 return *pb1 - *pb2;
1208 return 0;
1209}
1210
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use