VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp@ 36060

Last change on this file since 36060 was 36060, checked in by vboxsync, 14 years ago

VBoxGuest-win: PNP cleanup: process only required PNP IRPs according to MSDN.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.1 KB
Line 
1/** @file
2 *
3 * VBoxGuest - Windows specifics.
4 *
5 * Copyright (C) 2010 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15
16/*******************************************************************************
17* Header Files *
18*******************************************************************************/
19#define LOG_GROUP LOG_GROUP_SUP_DRV
20#include "VBoxGuest-win.h"
21#include "VBoxGuestInternal.h"
22
23#include <iprt/asm.h>
24
25#include <VBox/log.h>
26#include <VBox/VBoxGuestLib.h>
27
28#include <VBoxGuestInternal.h>
29
30#ifdef TARGET_NT4
31/*
32 * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist
33 * on NT4, so... The same for ExAllocatePool.
34 */
35#undef ExAllocatePool
36#undef ExFreePool
37#endif
38
39/*******************************************************************************
40* Defined Constants And Macros *
41*******************************************************************************/
42
43
44/*******************************************************************************
45* Entry Points *
46*******************************************************************************/
47RT_C_DECLS_BEGIN
48static NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj);
49static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj);
50static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
51static NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
52static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
53static NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp);
54static NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp);
55static NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp);
56RT_C_DECLS_END
57
58
59/*******************************************************************************
60* Internal Functions *
61*******************************************************************************/
62RT_C_DECLS_BEGIN
63#ifdef DEBUG
64 static void vboxguestwinDoTests(void);
65#endif
66RT_C_DECLS_END
67
68
69/*******************************************************************************
70* Exported Functions *
71*******************************************************************************/
72RT_C_DECLS_BEGIN
73ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath);
74RT_C_DECLS_END
75
76#ifdef ALLOC_PRAGMA
77#pragma alloc_text (INIT, DriverEntry)
78#pragma alloc_text (PAGE, vboxguestwinAddDevice)
79#pragma alloc_text (PAGE, vboxguestwinUnload)
80#pragma alloc_text (PAGE, vboxguestwinCreate)
81#pragma alloc_text (PAGE, vboxguestwinClose)
82#pragma alloc_text (PAGE, vboxguestwinIOCtl)
83#pragma alloc_text (PAGE, vboxguestwinShutdown)
84#pragma alloc_text (PAGE, vboxguestwinNotSupportedStub)
85#pragma alloc_text (PAGE, vboxguestwinScanPCIResourceList)
86#endif
87
88/** The detected Windows version. */
89winVersion_t g_winVersion;
90
91
92/**
93 * Driver entry point.
94 *
95 * @returns appropriate status code.
96 * @param pDrvObj Pointer to driver object.
97 * @param pRegPath Registry base path.
98 */
99ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath)
100{
101 NTSTATUS rc = STATUS_SUCCESS;
102
103 Log(("VBoxGuest::DriverEntry. Driver built: %s %s\n", __DATE__, __TIME__));
104
105 ULONG majorVersion;
106 ULONG minorVersion;
107 ULONG buildNumber;
108 BOOLEAN bCheckedBuild = PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL);
109 Log(("VBoxGuest::DriverEntry: Running on Windows NT version %d.%d, build %d\n", majorVersion, minorVersion, buildNumber));
110 if (bCheckedBuild)
111 Log(("VBoxGuest::DriverEntry: Running on a Windows checked build (debug)!\n"));
112#ifdef DEBUG
113 vboxguestwinDoTests();
114#endif
115 switch (majorVersion)
116 {
117 case 6: /* Windows Vista or Windows 7 (based on minor ver) */
118 switch (minorVersion)
119 {
120 case 0: /* Note: Also could be Windows 2008 Server! */
121 g_winVersion = WINVISTA;
122 break;
123 case 1: /* Note: Also could be Windows 2008 Server R2! */
124 g_winVersion = WIN7;
125 break;
126 default:
127 Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n",
128 majorVersion, minorVersion));
129 rc = STATUS_DRIVER_UNABLE_TO_LOAD;
130 break;
131 }
132 break;
133 case 5:
134 switch (minorVersion)
135 {
136 case 2:
137 g_winVersion = WIN2K3;
138 break;
139 case 1:
140 g_winVersion = WINXP;
141 break;
142 case 0:
143 g_winVersion = WIN2K;
144 break;
145 default:
146 Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n",
147 majorVersion, minorVersion));
148 rc = STATUS_DRIVER_UNABLE_TO_LOAD;
149 }
150 break;
151 case 4:
152 g_winVersion = WINNT4;
153 break;
154 default:
155 Log(("VBoxGuest::DriverEntry: At least Windows NT4 required!\n"));
156 rc = STATUS_DRIVER_UNABLE_TO_LOAD;
157 }
158
159 if (NT_SUCCESS(rc))
160 {
161 /*
162 * Setup the driver entry points in pDrvObj.
163 */
164 pDrvObj->DriverUnload = vboxguestwinUnload;
165 pDrvObj->MajorFunction[IRP_MJ_CREATE] = vboxguestwinCreate;
166 pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vboxguestwinClose;
167 pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vboxguestwinIOCtl;
168 pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vboxguestwinIOCtl;
169 pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vboxguestwinShutdown;
170 pDrvObj->MajorFunction[IRP_MJ_READ] = vboxguestwinNotSupportedStub;
171 pDrvObj->MajorFunction[IRP_MJ_WRITE] = vboxguestwinNotSupportedStub;
172#ifdef TARGET_NT4
173 rc = vboxguestwinnt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath);
174#else
175 pDrvObj->MajorFunction[IRP_MJ_PNP] = vboxguestwinPnP;
176 pDrvObj->MajorFunction[IRP_MJ_POWER] = vboxguestwinPower;
177 pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vboxguestwinSystemControl;
178 pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vboxguestwinAddDevice;
179#endif
180 }
181
182 Log(("VBoxGuest::DriverEntry returning %#x\n", rc));
183 return rc;
184}
185
186
187#ifndef TARGET_NT4
188/**
189 * Handle request from the Plug & Play subsystem.
190 *
191 * @returns NT status code
192 * @param pDrvObj Driver object
193 * @param pDevObj Device object
194 */
195static NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj)
196{
197 NTSTATUS rc;
198 Log(("VBoxGuest::vboxguestwinGuestAddDevice\n"));
199
200 /*
201 * Create device.
202 */
203 PDEVICE_OBJECT pDeviceObject = NULL;
204 PVBOXGUESTDEVEXT pDevExt = NULL;
205 UNICODE_STRING devName;
206 UNICODE_STRING win32Name;
207 RtlInitUnicodeString(&devName, VBOXGUEST_DEVICE_NAME_NT);
208 rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
209 if (NT_SUCCESS(rc))
210 {
211 /*
212 * Create symbolic link (DOS devices).
213 */
214 RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
215 rc = IoCreateSymbolicLink(&win32Name, &devName);
216 if (NT_SUCCESS(rc))
217 {
218 /*
219 * Setup the device extension.
220 */
221 pDevExt = (PVBOXGUESTDEVEXT)pDeviceObject->DeviceExtension;
222 RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT));
223
224 pDevExt->win.s.pDeviceObject = pDeviceObject;
225 pDevExt->win.s.prevDevState = STOPPED;
226 pDevExt->win.s.devState = STOPPED;
227
228 pDevExt->win.s.pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj);
229 if (pDevExt->win.s.pNextLowerDriver == NULL)
230 {
231 Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n"));
232 rc = STATUS_DEVICE_NOT_CONNECTED;
233 }
234 }
235 else
236 Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc));
237 }
238 else
239 Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc));
240
241 if (NT_SUCCESS(rc))
242 {
243 /*
244 * If we reached this point we're fine with the basic driver setup,
245 * so continue to init our own things.
246 */
247#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
248 vboxguestwinBugCheckCallback(pDevExt); /* Ignore failure! */
249#endif
250 /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */
251 pDeviceObject->Flags |= DO_POWER_PAGABLE;
252
253 /* Driver is ready now. */
254 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
255 }
256
257 /* Cleanup on error. */
258 if (NT_ERROR(rc))
259 {
260 if (pDevExt)
261 {
262 if (pDevExt->win.s.pNextLowerDriver)
263 IoDetachDevice(pDevExt->win.s.pNextLowerDriver);
264 }
265 IoDeleteSymbolicLink(&win32Name);
266 if (pDeviceObject)
267 IoDeleteDevice(pDeviceObject);
268 }
269
270 Log(("VBoxGuest::vboxguestwinGuestAddDevice: returning with rc = 0x%x\n", rc));
271 return rc;
272}
273#endif
274
275
276/**
277 * Debug helper to dump a device resource list.
278 *
279 * @param pResourceList list of device resources.
280 */
281static void vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList)
282{
283#ifdef LOG_ENABLED
284 PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = pResourceList->PartialDescriptors;
285 ULONG nres = pResourceList->Count;
286 ULONG i;
287
288 for (i = 0; i < nres; ++i, ++resource)
289 {
290 ULONG uType = resource->Type;
291 static char* aszName[] =
292 {
293 "CmResourceTypeNull",
294 "CmResourceTypePort",
295 "CmResourceTypeInterrupt",
296 "CmResourceTypeMemory",
297 "CmResourceTypeDma",
298 "CmResourceTypeDeviceSpecific",
299 "CmResourceTypeBusNumber",
300 "CmResourceTypeDevicePrivate",
301 "CmResourceTypeAssignedResource",
302 "CmResourceTypeSubAllocateFrom",
303 };
304
305 Log(("VBoxGuest::vboxguestwinShowDeviceResources: Type %s",
306 uType < (sizeof(aszName) / sizeof(aszName[0]))
307 ? aszName[uType] : "Unknown"));
308
309 switch (uType)
310 {
311 case CmResourceTypePort:
312 case CmResourceTypeMemory:
313 Log(("VBoxGuest::vboxguestwinShowDeviceResources: Start %8X%8.8lX length %X\n",
314 resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart,
315 resource->u.Port.Length));
316 break;
317
318 case CmResourceTypeInterrupt:
319 Log(("VBoxGuest::vboxguestwinShowDeviceResources: Level %X, Vector %X, Affinity %X\n",
320 resource->u.Interrupt.Level, resource->u.Interrupt.Vector,
321 resource->u.Interrupt.Affinity));
322 break;
323
324 case CmResourceTypeDma:
325 Log(("VBoxGuest::vboxguestwinShowDeviceResources: Channel %d, Port %X\n",
326 resource->u.Dma.Channel, resource->u.Dma.Port));
327 break;
328
329 default:
330 Log(("\n"));
331 break;
332 }
333 }
334#endif
335}
336
337
338/**
339 * Global initialisation stuff (PnP + NT4 legacy).
340 *
341 * @param pDevObj Device object.
342 * @param pIrp Request packet.
343 */
344#ifndef TARGET_NT4
345NTSTATUS vboxguestwinInit(PDEVICE_OBJECT pDevObj, PIRP pIrp)
346#else
347NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
348#endif
349{
350 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
351#ifndef TARGET_NT4
352 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
353#endif
354
355 Log(("VBoxGuest::vboxguestwinInit\n"));
356
357 int rc = STATUS_SUCCESS;
358#ifdef TARGET_NT4
359 /*
360 * Let's have a look at what our PCI adapter offers.
361 */
362 Log(("VBoxGuest::vboxguestwinInit: Starting to scan PCI resources of VBoxGuest ...\n"));
363
364 /* Assign the PCI resources. */
365 PCM_RESOURCE_LIST pResourceList = NULL;
366 UNICODE_STRING classNameString;
367 RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter");
368 rc = HalAssignSlotResources(pRegPath, &classNameString,
369 pDrvObj, pDevObj,
370 PCIBus, pDevExt->win.s.busNumber, pDevExt->win.s.slotNumber,
371 &pResourceList);
372 if (pResourceList && pResourceList->Count > 0)
373 vboxguestwinShowDeviceResources(&pResourceList->List[0].PartialResourceList);
374 if (NT_SUCCESS(rc))
375 rc = vboxguestwinScanPCIResourceList(pResourceList, pDevExt);
376#else
377 if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0)
378 vboxguestwinShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList);
379 if (NT_SUCCESS(rc))
380 rc = vboxguestwinScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated,
381 pDevExt);
382#endif
383 if (NT_SUCCESS(rc))
384 {
385 /*
386 * Map physical address of VMMDev memory into MMIO region
387 * and init the common device extension bits.
388 */
389 void *pvMMIOBase = NULL;
390 uint32_t cbMMIO = 0;
391 rc = vboxguestwinMapVMMDevMemory(pDevExt,
392 pDevExt->win.s.vmmDevPhysMemoryAddress,
393 pDevExt->win.s.vmmDevPhysMemoryLength,
394 &pvMMIOBase,
395 &cbMMIO);
396 if (NT_SUCCESS(rc))
397 {
398 pDevExt->pVMMDevMemory = (VMMDevMemory *)pvMMIOBase;
399
400 Log(("VBoxGuest::vboxguestwinInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->pVMMDevMemory = 0x%p\n",
401 pvMMIOBase, pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));
402
403 int vrc = VBoxGuestInitDevExt(pDevExt,
404 pDevExt->IOPortBase,
405 pvMMIOBase, cbMMIO,
406 vboxguestwinVersionToOSType(g_winVersion),
407 VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
408 if (RT_FAILURE(vrc))
409 {
410 Log(("VBoxGuest::vboxguestwinInit: Could not init device extension, rc = %Rrc!\n", vrc));
411 rc = STATUS_DEVICE_CONFIGURATION_ERROR;
412 }
413 }
414 else
415 Log(("VBoxGuest::vboxguestwinInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc));
416 }
417
418 if (NT_SUCCESS(rc))
419 {
420 int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->win.s.pPowerStateRequest,
421 sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
422 if (RT_FAILURE(vrc))
423 {
424 Log(("VBoxGuest::vboxguestwinInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc));
425 rc = STATUS_UNSUCCESSFUL;
426 }
427 }
428
429 if (NT_SUCCESS(rc))
430 {
431 /*
432 * Register DPC and ISR.
433 */
434 Log(("VBoxGuest::vboxguestwinInit: Initializing DPC/ISR ...\n"));
435
436 IoInitializeDpcRequest(pDevExt->win.s.pDeviceObject, vboxguestwinDpcHandler);
437#ifdef TARGET_NT4
438 ULONG uInterruptVector;
439 KIRQL irqLevel;
440 /* Get an interrupt vector. */
441 /* Only proceed if the device provides an interrupt. */
442 if ( pDevExt->win.s.interruptLevel
443 || pDevExt->win.s.interruptVector)
444 {
445 Log(("VBoxGuest::vboxguestwinInit: Getting interrupt vector (HAL): Bus: %u, IRQL: %u, Vector: %u\n",
446 pDevExt->win.s.busNumber, pDevExt->win.s.interruptLevel, pDevExt->win.s.interruptVector));
447
448 uInterruptVector = HalGetInterruptVector(PCIBus,
449 pDevExt->win.s.busNumber,
450 pDevExt->win.s.interruptLevel,
451 pDevExt->win.s.interruptVector,
452 &irqLevel,
453 &pDevExt->win.s.interruptAffinity);
454 Log(("VBoxGuest::vboxguestwinInit: HalGetInterruptVector returns vector %u\n", uInterruptVector));
455 if (uInterruptVector == 0)
456 Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n"));
457 }
458 else
459 Log(("VBoxGuest::vboxguestwinInit: Device does not provide an interrupt!\n"));
460#endif
461 if (pDevExt->win.s.interruptVector)
462 {
463 Log(("VBoxGuest::vboxguestwinInit: Connecting interrupt ...\n"));
464
465 rc = IoConnectInterrupt(&pDevExt->win.s.pInterruptObject, /* Out: interrupt object. */
466 (PKSERVICE_ROUTINE)vboxguestwinIsrHandler, /* Our ISR handler. */
467 pDevExt, /* Device context. */
468 NULL, /* Optional spinlock. */
469#ifdef TARGET_NT4
470 uInterruptVector, /* Interrupt vector. */
471 irqLevel, /* Interrupt level. */
472 irqLevel, /* Interrupt level. */
473#else
474 pDevExt->win.s.interruptVector, /* Interrupt vector. */
475 (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */
476 (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */
477#endif
478 pDevExt->win.s.interruptMode, /* LevelSensitive or Latched. */
479 TRUE, /* Shareable interrupt. */
480 pDevExt->win.s.interruptAffinity, /* CPU affinity. */
481 FALSE); /* Don't save FPU stack. */
482 if (NT_ERROR(rc))
483 Log(("VBoxGuest::vboxguestwinInit: Could not connect interrupt, rc = 0x%x\n", rc));
484 }
485 else
486 Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n"));
487 }
488
489
490#ifdef VBOX_WITH_HGCM
491 Log(("VBoxGuest::vboxguestwinInit: Allocating kernel session data ...\n"));
492 int vrc = VBoxGuestCreateKernelSession(pDevExt, &pDevExt->win.s.pKernelSession);
493 if (RT_FAILURE(vrc))
494 {
495 Log(("VBoxGuest::vboxguestwinInit: Failed to allocated kernel session data! rc = %Rrc\n", rc));
496 rc = STATUS_UNSUCCESSFUL;
497 }
498#endif
499
500 if (RT_SUCCESS(rc))
501 {
502 /* Ready to rumble! */
503 Log(("VBoxGuest::vboxguestwinInit: Device is ready!\n"));
504 VBOXGUEST_UPDATE_DEVSTATE(pDevExt, WORKING);
505 }
506 else
507 {
508 pDevExt->win.s.pInterruptObject = NULL;
509 }
510
511 Log(("VBoxGuest::vboxguestwinInit: Returned with rc = 0x%x\n", rc));
512 return rc;
513}
514
515
516/**
517 * Cleans up hardware resources.
518 * Do not delete DevExt here.
519 *
520 * @param pDrvObj Driver object.
521 */
522NTSTATUS vboxguestwinCleanup(PDEVICE_OBJECT pDevObj)
523{
524 Log(("VBoxGuest::vboxguestwinCleanup\n"));
525
526 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
527 if (pDevExt)
528 {
529#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION
530 hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */
531#endif
532 /* According to MSDN we have to unmap previously mapped memory. */
533 vboxguestwinUnmapVMMDevMemory(pDevExt);
534 }
535 return STATUS_SUCCESS;
536}
537
538
539/**
540 * Unload the driver.
541 *
542 * @param pDrvObj Driver object.
543 */
544void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj)
545{
546 Log(("VBoxGuest::vboxguestwinGuestUnload\n"));
547#ifdef TARGET_NT4
548 vboxguestwinCleanup(pDrvObj->DeviceObject);
549
550 /* Destroy device extension and clean up everything else. */
551 if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension)
552 VBoxGuestDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension);
553
554 /*
555 * I don't think it's possible to unload a driver which processes have
556 * opened, at least we'll blindly assume that here.
557 */
558 UNICODE_STRING win32Name;
559 RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS);
560 NTSTATUS rc = IoDeleteSymbolicLink(&win32Name);
561
562 IoDeleteDevice(pDrvObj->DeviceObject);
563#else /* TARGET_NT4 */
564 /* On a PnP driver this routine will be called after
565 * IRP_MN_REMOVE_DEVICE (where we already did the cleanup),
566 * so don't do anything here (yet). */
567#endif
568
569 Log(("VBoxGuest::vboxguestwinGuestUnload: returning\n"));
570}
571
572
573/**
574 * Create (i.e. Open) file entry point.
575 *
576 * @param pDevObj Device object.
577 * @param pIrp Request packet.
578 */
579NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
580{
581 /** @todo AssertPtrReturn(pIrp); */
582 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
583 /** @todo AssertPtrReturn(pStack); */
584 PFILE_OBJECT pFileObj = pStack->FileObject;
585 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
586 NTSTATUS rc = STATUS_SUCCESS;
587
588 if (pDevExt->win.s.devState != WORKING)
589 {
590 Log(("VBoxGuest::vboxguestwinGuestCreate: device is not working currently: %d!\n",
591 pDevExt->win.s.devState));
592 rc = STATUS_UNSUCCESSFUL;
593 }
594 else if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
595 {
596 /*
597 * We are not remotely similar to a directory...
598 * (But this is possible.)
599 */
600 Log(("VBoxGuest::vboxguestwinGuestCreate: Uhm, we're not a directory!\n"));
601 rc = STATUS_NOT_A_DIRECTORY;
602 }
603 else
604 {
605#ifdef VBOX_WITH_HGCM
606 if (pFileObj)
607 {
608 Log(("VBoxGuest::vboxguestwinGuestCreate: File object type = %d\n",
609 pFileObj->Type));
610
611 int vrc;
612 PVBOXGUESTSESSION pSession;
613 if (pFileObj->Type == 5 /* File Object */)
614 {
615 /*
616 * Create a session object if we have a valid file object. This session object
617 * exists for every R3 process.
618 */
619 vrc = VBoxGuestCreateUserSession(pDevExt, &pSession);
620 }
621 else
622 {
623 /* ... otherwise we've been called from R0! */
624 vrc = VBoxGuestCreateKernelSession(pDevExt, &pSession);
625 }
626 if (RT_SUCCESS(vrc))
627 pFileObj->FsContext = pSession;
628 }
629#endif
630 }
631
632 /* Complete the request! */
633 pIrp->IoStatus.Information = 0;
634 pIrp->IoStatus.Status = rc;
635 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
636
637 Log(("VBoxGuest::vboxguestwinGuestCreate: Returning 0x%x\n", rc));
638 return rc;
639}
640
641
642/**
643 * Close file entry point.
644 *
645 * @param pDevObj Device object.
646 * @param pIrp Request packet.
647 */
648NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
649{
650 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
651 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
652 PFILE_OBJECT pFileObj = pStack->FileObject;
653
654 Log(("VBoxGuest::vboxguestwinGuestClose: pDevExt=0x%p pFileObj=0x%p FsContext=0x%p\n",
655 pDevExt, pFileObj, pFileObj->FsContext));
656
657#ifdef VBOX_WITH_HGCM
658 /* Close both, R0 and R3 sessions. */
659 PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
660 if (pSession)
661 VBoxGuestCloseSession(pDevExt, pSession);
662#endif
663
664 pFileObj->FsContext = NULL;
665 pIrp->IoStatus.Information = 0;
666 pIrp->IoStatus.Status = STATUS_SUCCESS;
667 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
668
669 return STATUS_SUCCESS;
670}
671
672
673/**
674 * Device I/O Control entry point.
675 *
676 * @param pDevObj Device object.
677 * @param pIrp Request packet.
678 */
679NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
680{
681 NTSTATUS Status = STATUS_SUCCESS;
682 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
683 PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
684 unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode;
685
686 char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* All requests are buffered. */
687 size_t cbData = pStack->Parameters.DeviceIoControl.InputBufferLength;
688 unsigned cbOut = 0;
689
690 /* Do we have a file object associated?*/
691 PFILE_OBJECT pFileObj = pStack->FileObject;
692 PVBOXGUESTSESSION pSession = NULL;
693 if (pFileObj) /* ... then we might have a session object as well! */
694 pSession = (PVBOXGUESTSESSION)pFileObj->FsContext;
695
696 Log(("VBoxGuest::vboxguestwinIOCtl: uCmd=%u, pDevExt=0x%p, pSession=0x%p\n",
697 uCmd, pDevExt, pSession));
698
699 /* We don't have a session associated with the file object? So this seems
700 * to be a kernel call then. */
701 if (pSession == NULL)
702 {
703 Log(("VBoxGuest::vboxguestwinIOCtl: Using kernel session data ...\n"));
704 pSession = pDevExt->win.s.pKernelSession;
705 }
706
707 /*
708 * First process Windows specific stuff which cannot be handled
709 * by the common code used on all other platforms. In the default case
710 * we then finally handle the common cases.
711 */
712 switch (uCmd)
713 {
714#ifdef VBOX_WITH_VRDP_SESSION_HANDLING
715 case VBOXGUEST_IOCTL_ENABLE_VRDP_SESSION:
716 {
717 LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Currently: %sabled\n",
718 pDevExt->fVRDPEnabled? "en": "dis"));
719 if (!pDevExt->fVRDPEnabled)
720 {
721 KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
722
723 pDevExt->fVRDPEnabled = TRUE;
724 LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
725 pSharedUserData->ActiveConsoleId));
726 pDevExt->ulOldActiveConsoleId = pSharedUserData->ActiveConsoleId;
727 pSharedUserData->ActiveConsoleId = 2;
728 }
729 break;
730 }
731
732 case VBOXGUEST_IOCTL_DISABLE_VRDP_SESSION:
733 {
734 LogRel(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Currently: %sabled\n",
735 pDevExt->fVRDPEnabled? "en": "dis"));
736 if (pDevExt->fVRDPEnabled)
737 {
738 KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA;
739
740 pDevExt->fVRDPEnabled = FALSE;
741 Log(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Current active console ID: 0x%08X\n",
742 pSharedUserData->ActiveConsoleId));
743 pSharedUserData->ActiveConsoleId = pDevExt->ulOldActiveConsoleId;
744 pDevExt->ulOldActiveConsoleId = 0;
745 }
746 break;
747 }
748#else
749 /* Add at least one (bogus) fall through case to shut up MSVC! */
750 case 0:
751#endif
752 default:
753 {
754 /*
755 * Process the common IOCtls.
756 */
757 size_t cbDataReturned;
758 int vrc = VBoxGuestCommonIOCtl(uCmd, pDevExt, pSession, (void*)pBuf, cbData, &cbDataReturned);
759
760 Log(("VBoxGuest::vboxguestwinGuestDeviceControl: rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n",
761 vrc, pBuf, cbData, cbDataReturned));
762
763 if (RT_SUCCESS(vrc))
764 {
765 if (RT_UNLIKELY(cbDataReturned > cbData))
766 {
767 Log(("VBoxGuest::vboxguestwinGuestDeviceControl: Too much output data %u - expected %u!\n", cbDataReturned, cbData));
768 cbDataReturned = cbData;
769 Status = STATUS_BUFFER_TOO_SMALL;
770 }
771 if (cbDataReturned > 0)
772 cbOut = cbDataReturned;
773 }
774 else
775 {
776 if ( vrc == VERR_NOT_SUPPORTED
777 || vrc == VERR_INVALID_PARAMETER)
778 {
779 Status = STATUS_INVALID_PARAMETER;
780 }
781 else
782 Status = STATUS_UNSUCCESSFUL;
783 }
784 break;
785 }
786 }
787
788 pIrp->IoStatus.Status = Status;
789 pIrp->IoStatus.Information = cbOut;
790
791 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
792
793 //Log(("VBoxGuest::vboxguestwinGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status));
794 return Status;
795}
796
797
798/**
799 * IRP_MJ_SYSTEM_CONTROL handler.
800 *
801 * @returns NT status code
802 * @param pDevObj Device object.
803 * @param pIrp IRP.
804 */
805NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
806{
807 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
808
809 Log(("VBoxGuest::vboxguestwinGuestSystemControl\n"));
810
811 /* Always pass it on to the next driver. */
812 IoSkipCurrentIrpStackLocation(pIrp);
813
814 return IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp);
815}
816
817
818/**
819 * IRP_MJ_SHUTDOWN handler.
820 *
821 * @returns NT status code
822 * @param pDevObj Device object.
823 * @param pIrp IRP.
824 */
825NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp)
826{
827 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
828
829 Log(("VBoxGuest::vboxguestwinGuestShutdown\n"));
830
831 VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest;
832 if (pReq)
833 {
834 pReq->header.requestType = VMMDevReq_SetPowerStatus;
835 pReq->powerState = VMMDevPowerState_PowerOff;
836
837 int rc = VbglGRPerform(&pReq->header);
838 if (RT_FAILURE(rc))
839 {
840 Log(("VBoxGuest::vboxguestwinGuestShutdown: Error performing request to VMMDev! "
841 "rc = %Rrc\n", rc));
842 }
843 }
844 return STATUS_SUCCESS;
845}
846
847
848/**
849 * Stub function for functions we don't implemented.
850 *
851 * @returns STATUS_NOT_SUPPORTED
852 * @param pDevObj Device object.
853 * @param pIrp IRP.
854 */
855NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp)
856{
857 Log(("VBoxGuest::vboxguestwinGuestNotSupportedStub\n"));
858
859 pIrp->IoStatus.Information = 0;
860 pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
861 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
862
863 return STATUS_NOT_SUPPORTED;
864}
865
866
867/**
868 * DPC handler.
869 *
870 * @param pDPC DPC descriptor.
871 * @param pDevObj Device object.
872 * @param pIrp Interrupt request packet.
873 * @param pContext Context specific pointer.
874 */
875void vboxguestwinDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj,
876 PIRP pIrp, PVOID pContext)
877{
878 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
879 Log(("VBoxGuest::vboxguestwinGuestDpcHandler: pDevExt=0x%p\n", pDevExt));
880
881 /* Process the wake-up list we were asked by the scheduling a DPC
882 * in vboxguestwinIsrHandler(). */
883 VBoxGuestWaitDoWakeUps(pDevExt);
884}
885
886
887/**
888 * ISR handler.
889 *
890 * @return BOOLEAN Indicates whether the IRQ came from us (TRUE) or not (FALSE).
891 * @param pInterrupt Interrupt that was triggered.
892 * @param pServiceContext Context specific pointer.
893 */
894BOOLEAN vboxguestwinIsrHandler(PKINTERRUPT pInterrupt, PVOID pServiceContext)
895{
896 PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pServiceContext;
897 if (pDevExt == NULL)
898 return FALSE;
899
900 /*Log(("VBoxGuest::vboxguestwinGuestIsrHandler: pDevExt = 0x%p, pVMMDevMemory = 0x%p\n",
901 pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));*/
902
903 /* Enter the common ISR routine and do the actual work. */
904 BOOLEAN fIRQTaken = VBoxGuestCommonISR(pDevExt);
905
906 /* If we need to wake up some events we do that in a DPC to make
907 * sure we're called at the right IRQL. */
908 if (fIRQTaken)
909 {
910 Log(("VBoxGuest::vboxguestwinGuestIsrHandler: IRQ was taken! pInterrupt = 0x%p, pDevExt = 0x%p\n",
911 pInterrupt, pDevExt));
912 if (!RTListIsEmpty(&pDevExt->WakeUpList))
913 {
914 Log(("VBoxGuest::vboxguestwinGuestIsrHandler: Requesting DPC ...\n"));
915 IoRequestDpc(pDevExt->win.s.pDeviceObject, pDevExt->win.s.pCurrentIrp, NULL);
916 }
917 }
918 return fIRQTaken;
919}
920
921
922/*
923 * Overridden routine for mouse polling events. Not
924 * used at the moment on Windows.
925 *
926 * @param pDevExt Device extension structure.
927 */
928void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt)
929{
930 NOREF(pDevExt);
931}
932
933
934/**
935 * Helper to scan the PCI resource list and remember stuff.
936 *
937 * @param pResList Resource list
938 * @param pDevExt Device extension
939 */
940NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXT pDevExt)
941{
942 /* Enumerate the resource list. */
943 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Found %d resources\n",
944 pResList->List->PartialResourceList.Count));
945
946 NTSTATUS rc = STATUS_SUCCESS;
947 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL;
948 ULONG rangeCount = 0;
949 ULONG cMMIORange = 0;
950 PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->win.s.pciBaseAddress;
951 for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++)
952 {
953 pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i];
954 switch (pPartialData->Type)
955 {
956 case CmResourceTypePort:
957 {
958 /* Overflow protection. */
959 if (rangeCount < PCI_TYPE0_ADDRESSES)
960 {
961 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range: Base = %08x:%08x, Length = %08x\n",
962 pPartialData->u.Port.Start.HighPart,
963 pPartialData->u.Port.Start.LowPart,
964 pPartialData->u.Port.Length));
965
966 /* Save the IO port base. */
967 /** @todo Not so good. */
968 pDevExt->IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart;
969
970 /* Save resource information. */
971 pBaseAddress->RangeStart = pPartialData->u.Port.Start;
972 pBaseAddress->RangeLength = pPartialData->u.Port.Length;
973 pBaseAddress->RangeInMemory = FALSE;
974 pBaseAddress->ResourceMapped = FALSE;
975
976 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
977 pPartialData->u.Port.Start.HighPart,
978 pPartialData->u.Port.Start.LowPart,
979 pPartialData->u.Port.Length));
980
981 /* Next item ... */
982 rangeCount++; pBaseAddress++;
983 }
984 break;
985 }
986
987 case CmResourceTypeInterrupt:
988 {
989 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Interrupt: Level = %x, Vector = %x, Mode = %x\n",
990 pPartialData->u.Interrupt.Level,
991 pPartialData->u.Interrupt.Vector,
992 pPartialData->Flags));
993
994 /* Save information. */
995 pDevExt->win.s.interruptLevel = pPartialData->u.Interrupt.Level;
996 pDevExt->win.s.interruptVector = pPartialData->u.Interrupt.Vector;
997 pDevExt->win.s.interruptAffinity = pPartialData->u.Interrupt.Affinity;
998
999 /* Check interrupt mode. */
1000 if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
1001 {
1002 pDevExt->win.s.interruptMode = Latched;
1003 }
1004 else
1005 {
1006 pDevExt->win.s.interruptMode = LevelSensitive;
1007 }
1008 break;
1009 }
1010
1011 case CmResourceTypeMemory:
1012 {
1013 /* Overflow protection. */
1014 if (rangeCount < PCI_TYPE0_ADDRESSES)
1015 {
1016 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range: Base = %08x:%08x, Length = %08x\n",
1017 pPartialData->u.Memory.Start.HighPart,
1018 pPartialData->u.Memory.Start.LowPart,
1019 pPartialData->u.Memory.Length));
1020
1021 /* We only care about read/write memory. */
1022 /** @todo Reconsider memory type. */
1023 if ( cMMIORange == 0 /* Only care about the first MMIO range (!!!). */
1024 && (pPartialData->Flags & VBOX_CM_PRE_VISTA_MASK) == CM_RESOURCE_MEMORY_READ_WRITE)
1025 {
1026 /* Save physical MMIO base + length for VMMDev. */
1027 pDevExt->win.s.vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start;
1028 pDevExt->win.s.vmmDevPhysMemoryLength = (ULONG)pPartialData->u.Memory.Length;
1029
1030 /* Save resource information. */
1031 pBaseAddress->RangeStart = pPartialData->u.Memory.Start;
1032 pBaseAddress->RangeLength = pPartialData->u.Memory.Length;
1033 pBaseAddress->RangeInMemory = TRUE;
1034 pBaseAddress->ResourceMapped = FALSE;
1035
1036 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n",
1037 pPartialData->u.Memory.Start.HighPart,
1038 pPartialData->u.Memory.Start.LowPart,
1039 pPartialData->u.Memory.Length));
1040
1041 /* Next item ... */
1042 rangeCount++; pBaseAddress++; cMMIORange++;
1043 }
1044 else
1045 {
1046 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Ignoring memory: Flags = %08x\n",
1047 pPartialData->Flags));
1048 }
1049 }
1050 break;
1051 }
1052
1053 default:
1054 {
1055 Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Unhandled resource found, type = %d\n", pPartialData->Type));
1056 break;
1057 }
1058 }
1059 }
1060
1061 /* Memorize the number of resources found. */
1062 pDevExt->win.s.pciAddressCount = rangeCount;
1063 return rc;
1064}
1065
1066
1067/**
1068 * Maps the I/O space from VMMDev to virtual kernel address space.
1069 *
1070 * @return NTSTATUS
1071 *
1072 * @param pDevExt The device extension.
1073 * @param physicalAdr Physical address to map.
1074 * @param ulLength Length (in bytes) to map.
1075 * @param ppvMMIOBase Pointer of mapped I/O base.
1076 * @param pcbMMIO Length of mapped I/O base.
1077 */
1078NTSTATUS vboxguestwinMapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt, PHYSICAL_ADDRESS physicalAdr, ULONG ulLength,
1079 void **ppvMMIOBase, uint32_t *pcbMMIO)
1080{
1081 AssertPtrReturn(pDevExt, VERR_INVALID_POINTER);
1082 AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER);
1083 /* pcbMMIO is optional. */
1084
1085 NTSTATUS rc = STATUS_SUCCESS;
1086 if (physicalAdr.LowPart > 0) /* We're mapping below 4GB. */
1087 {
1088 VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(physicalAdr, ulLength, MmNonCached);
1089 Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: pVMMDevMemory = 0x%x\n", pVMMDevMemory));
1090 if (pVMMDevMemory)
1091 {
1092 Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory: Version = 0x%x, Size = %d\n",
1093 pVMMDevMemory->u32Version, pVMMDevMemory->u32Size));
1094
1095 /* Check version of the structure; do we have the right memory version? */
1096 if (pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION)
1097 {
1098 Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: Wrong version (%u), refusing operation!\n",
1099 pVMMDevMemory->u32Version));
1100
1101 /* Not our version, refuse operation and unmap the memory. */
1102 vboxguestwinUnmapVMMDevMemory(pDevExt);
1103 rc = STATUS_UNSUCCESSFUL;
1104 }
1105 else
1106 {
1107 /* Save results. */
1108 *ppvMMIOBase = pVMMDevMemory;
1109 if (pcbMMIO) /* Optional. */
1110 *pcbMMIO = pVMMDevMemory->u32Size;
1111
1112 Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n",
1113 *ppvMMIOBase));
1114 }
1115 }
1116 else
1117 rc = STATUS_UNSUCCESSFUL;
1118 }
1119 return rc;
1120}
1121
1122
1123/**
1124 * Unmaps the VMMDev I/O range from kernel space.
1125 *
1126 * @param pDevExt The device extension.
1127 */
1128void vboxguestwinUnmapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt)
1129{
1130 Log(("VBoxGuest::vboxguestwinUnmapVMMDevMemory: pVMMDevMemory = 0x%x\n", pDevExt->pVMMDevMemory));
1131 if (pDevExt->pVMMDevMemory)
1132 {
1133 MmUnmapIoSpace((void*)pDevExt->pVMMDevMemory, pDevExt->win.s.vmmDevPhysMemoryLength);
1134 pDevExt->pVMMDevMemory = NULL;
1135 }
1136
1137 pDevExt->win.s.vmmDevPhysMemoryAddress.QuadPart = 0;
1138 pDevExt->win.s.vmmDevPhysMemoryLength = 0;
1139}
1140
1141
1142VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer)
1143{
1144 VBOXOSTYPE enmOsType;
1145 switch (winVer)
1146 {
1147 case WINNT4:
1148 enmOsType = VBOXOSTYPE_WinNT4;
1149 break;
1150
1151 case WIN2K:
1152 enmOsType = VBOXOSTYPE_Win2k;
1153 break;
1154
1155 case WINXP:
1156#if ARCH_BITS == 64
1157 enmOsType = VBOXOSTYPE_WinXP_x64;
1158#else
1159 enmOsType = VBOXOSTYPE_WinXP;
1160#endif
1161 break;
1162
1163 case WIN2K3:
1164#if ARCH_BITS == 64
1165 enmOsType = VBOXOSTYPE_Win2k3_x64;
1166#else
1167 enmOsType = VBOXOSTYPE_Win2k3;
1168#endif
1169 break;
1170
1171 case WINVISTA:
1172#if ARCH_BITS == 64
1173 enmOsType = VBOXOSTYPE_WinVista_x64;
1174#else
1175 enmOsType = VBOXOSTYPE_WinVista;
1176#endif
1177 break;
1178
1179 case WIN7:
1180#if ARCH_BITS == 64
1181 enmOsType = VBOXOSTYPE_Win7_x64;
1182#else
1183 enmOsType = VBOXOSTYPE_Win7;
1184#endif
1185 break;
1186
1187 default:
1188 /* We don't know, therefore NT family. */
1189 enmOsType = VBOXOSTYPE_WinNT;
1190 break;
1191 }
1192 return enmOsType;
1193}
1194
1195
1196#ifdef DEBUG
1197/** A quick implementation of AtomicTestAndClear for uint32_t and multiple
1198 * bits.
1199 */
1200static uint32_t vboxugestwinAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32Mask)
1201{
1202 AssertPtrReturn(pu32Bits, 0);
1203 LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(long *)pu32Bits,
1204 u32Mask));
1205 uint32_t u32Result = 0;
1206 uint32_t u32WorkingMask = u32Mask;
1207 int iBitOffset = ASMBitFirstSetU32 (u32WorkingMask);
1208
1209 while (iBitOffset > 0)
1210 {
1211 bool fSet = ASMAtomicBitTestAndClear(pu32Bits, iBitOffset - 1);
1212 if (fSet)
1213 u32Result |= 1 << (iBitOffset - 1);
1214 u32WorkingMask &= ~(1 << (iBitOffset - 1));
1215 iBitOffset = ASMBitFirstSetU32 (u32WorkingMask);
1216 }
1217 LogFlowFunc(("Returning 0x%x\n", u32Result));
1218 return u32Result;
1219}
1220
1221
1222static void vboxguestwinTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits,
1223 uint32_t u32Exp)
1224{
1225 ULONG u32Bits2 = u32Bits;
1226 uint32_t u32Result = vboxugestwinAtomicBitsTestAndClear(&u32Bits2, u32Mask);
1227 if ( u32Result != u32Exp
1228 || (u32Bits2 & u32Mask)
1229 || (u32Bits2 & u32Result)
1230 || ((u32Bits2 | u32Result) != u32Bits)
1231 )
1232 AssertLogRelMsgFailed(("%s: TEST FAILED: u32Mask=0x%x, u32Bits (before)=0x%x, u32Bits (after)=0x%x, u32Result=0x%x, u32Exp=ox%x\n",
1233 __PRETTY_FUNCTION__, u32Mask, u32Bits, u32Bits2,
1234 u32Result));
1235}
1236
1237
1238static void vboxguestwinDoTests()
1239{
1240 vboxguestwinTestAtomicTestAndClearBitsU32(0x00, 0x23, 0);
1241 vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0, 0);
1242 vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x22, 0);
1243 vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1);
1244 vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10);
1245 vboxguestwinTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22);
1246}
1247#endif
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