VirtualBox

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

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

VBoxGuest/win/WINNT: Corrected return value in case of errors.

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