Beispiel #1
0
NTSTATUS
NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
{
    PDEVICE_EXTENSION DeviceExtension;
    PDEVICE_OBJECT DeviceObject;
    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Beep");
    NTSTATUS Status;

    UNREFERENCED_PARAMETER(RegistryPath);

    /* Create the device */
    Status = IoCreateDevice(DriverObject,
                            sizeof(DEVICE_EXTENSION),
                            &DeviceName,
                            FILE_DEVICE_BEEP,
                            0,
                            FALSE,
                            &DeviceObject);
    if (!NT_SUCCESS(Status)) return Status;

    /* Make it use buffered I/O */
    DeviceObject->Flags |= DO_BUFFERED_IO;

    /* Setup the Driver Object */
    DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl;
    DriverObject->DriverUnload = BeepUnload;
    DriverObject->DriverStartIo = BeepStartIo;

    /* Set up device extension */
    DeviceExtension = DeviceObject->DeviceExtension;
    DeviceExtension->ReferenceCount = 0;
    DeviceExtension->TimerActive = FALSE;
    IoInitializeDpcRequest(DeviceObject, (PIO_DPC_ROUTINE)BeepDPC);
    KeInitializeTimer(&DeviceExtension->Timer);
    ExInitializeFastMutex(&DeviceExtension->Mutex);

    /* Page the entire driver */
    MmPageEntireDriver(DriverEntry);
    return STATUS_SUCCESS;
}
Beispiel #2
0
/*! \brief Initialize the IEC bus

 This function initializes the IEC bus itself, and sets some
 variables in the device extension. It has to be called before
 any other IEC function is called.

 \param Pdx
   Pointer to the device extension.

 \return 
   If the routine succeeds, it returns STATUS_SUCCESS. Otherwise, it
   returns one of the error status values.
*/
NTSTATUS
cbmiec_init(IN PDEVICE_EXTENSION Pdx)
{
    NTSTATUS ntStatus;

    FUNC_ENTER();

    // Initialize the event which is used to wake up the
    // task in wait_for_listener()

    DBG_IRQL( == PASSIVE_LEVEL);
    KeInitializeEvent(&Pdx->EventWaitForListener, SynchronizationEvent, FALSE);

#ifdef USE_DPC

    // Initialize the DPC object which will be used for waking
    // up cbmiec_wait_for_listener() later

    DBG_IRQL( == PASSIVE_LEVEL)
    IoInitializeDpcRequest(Pdx->Fdo, cbmiec_dpc);

#endif // #ifdef USE_DPC

    ntStatus = cbmiec_testcable(Pdx);

    if (!NT_SUCCESS(ntStatus)) {
        FUNC_LEAVE_NTSTATUS(ntStatus);
    }

    Pdx->IecBusy = FALSE;

    if (!Pdx->DoNotReleaseBus)
    {
        CBMIEC_RELEASE(PP_RESET_OUT | PP_DATA_OUT | PP_ATN_OUT | PP_LP_BIDIR | PP_LP_IRQ);
        CBMIEC_SET(PP_CLK_OUT);
    }

    FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
}
Beispiel #3
0
static BOOLEAN NTAPI
AddControllers(PDRIVER_OBJECT DriverObject)
/*
 * FUNCTION: Called on initialization to find our controllers and build device and controller objects for them
 * ARGUMENTS:
 *     DriverObject: Our driver's DriverObject (so we can create devices against it)
 * RETURNS:
 *     FALSE if we can't allocate a device, adapter, or interrupt object, or if we fail to find any controllers
 *     TRUE otherwise (i.e. we have at least one fully-configured controller)
 * NOTES:
 *     - Currently we only support ISA buses.
 *     - BUG: Windows 2000 seems to clobber the response from the IoQueryDeviceDescription callback, so now we
 *       just test a boolean value in the first object to see if it was completely populated.  The same value
 *       is tested for each controller before we build device objects for it.
 * TODO:
 *     - Report resource usage to the HAL
 */
{
    INTERFACE_TYPE InterfaceType = Isa;
    CONFIGURATION_TYPE ControllerType = DiskController;
    CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
    KAFFINITY Affinity;
    DEVICE_DESCRIPTION DeviceDescription;
    UCHAR i;
    UCHAR j;

    PAGED_CODE();

    /* Find our controllers on all ISA buses */
    IoQueryDeviceDescription(&InterfaceType, 0, &ControllerType, 0, &PeripheralType, 0, ConfigCallback, 0);

    /*
     * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just
     * looking for a return value from ConfigCallback.  We expect at least one controller.
     */
    if(!gControllerInfo[0].Populated)
    {
        WARN_(FLOPPY, "AddControllers: failed to get controller info from registry\n");
        return FALSE;
    }

    /* Now that we have a controller, set it up with the system */
    for(i = 0; i < gNumberOfControllers; i++)
    {
        /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */
        /* FIXME: Implement me. */

        /* 1: Set up interrupt */
        gControllerInfo[i].MappedVector = HalGetInterruptVector(gControllerInfo[i].InterfaceType, gControllerInfo[i].BusNumber,
                                          gControllerInfo[i].Level, gControllerInfo[i].Vector,
                                          &gControllerInfo[i].MappedLevel, &Affinity);

        /* Must set up the DPC before we connect the interrupt */
        KeInitializeDpc(&gControllerInfo[i].Dpc, DpcForIsr, &gControllerInfo[i]);

        INFO_(FLOPPY, "Connecting interrupt %d to controller%d (object 0x%p)\n", gControllerInfo[i].MappedVector,
              i, &gControllerInfo[i]);

        /* NOTE: We cannot share our interrupt, even on level-triggered buses.  See Isr() for details. */
        if(IoConnectInterrupt(&gControllerInfo[i].InterruptObject, Isr, &gControllerInfo[i], 0, gControllerInfo[i].MappedVector,
                              gControllerInfo[i].MappedLevel, gControllerInfo[i].MappedLevel, gControllerInfo[i].InterruptMode,
                              FALSE, Affinity, 0) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers: unable to connect interrupt\n");
            continue;
        }

        /* 2: Set up DMA */
        memset(&DeviceDescription, 0, sizeof(DeviceDescription));
        DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
        DeviceDescription.DmaChannel = gControllerInfo[i].Dma;
        DeviceDescription.InterfaceType = gControllerInfo[i].InterfaceType;
        DeviceDescription.BusNumber = gControllerInfo[i].BusNumber;
        DeviceDescription.MaximumLength = 2*18*512; /* based on a 1.44MB floppy */

        /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */
        DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits;

        gControllerInfo[i].AdapterObject = HalGetAdapter(&DeviceDescription, &gControllerInfo[i].MapRegisters);

        if(!gControllerInfo[i].AdapterObject)
        {
            WARN_(FLOPPY, "AddControllers: unable to allocate an adapter object\n");
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2b: Initialize the new controller */
        if(InitController(&gControllerInfo[i]) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers(): Unable to set up controller %d - initialization failed\n", i);
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2c: Set the controller's initlized flag so we know to release stuff in Unload */
        gControllerInfo[i].Initialized = TRUE;

        /* 3: per-drive setup */
        for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
        {
            WCHAR DeviceNameBuf[MAX_DEVICE_NAME];
            UNICODE_STRING DeviceName;
            UNICODE_STRING LinkName;
            UNICODE_STRING ArcPath;
            UCHAR DriveNumber;

            INFO_(FLOPPY, "AddControllers(): Configuring drive %d on controller %d\n", i, j);

            /*
             * 3a: create a device object for the drive
             * Controllers and drives are 0-based, so the combos are:
             * 0: 0,0
             * 1: 0,1
             * 2: 0,2
             * 3: 0,3
             * 4: 1,0
             * 5: 1,1
             * ...
             * 14: 3,2
             * 15: 3,3
             */

            DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */

            RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR));
            swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber);
            RtlInitUnicodeString(&DeviceName, DeviceNameBuf);

            if(IoCreateDevice(DriverObject, sizeof(PVOID), &DeviceName,
                              FILE_DEVICE_DISK, FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, FALSE,
                              &gControllerInfo[i].DriveInfo[j].DeviceObject) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: unable to register a Device object\n");
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                continue; /* continue on to next drive */
            }

            INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject);

            /* 3b.5: Create an ARC path in case we're booting from this drive */
            swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer,
                     L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber);

            RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
            IoAssignArcName(&ArcPath, &DeviceName);

            /* 3c: Set flags up */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO;

            /* 3d: Create a symlink */
            swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A');
            RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
            if(IoCreateSymbolicLink(&LinkName, &DeviceName) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber);
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                IoDeassignArcName(&ArcPath);
                continue; /* continue to next drive */
            }

            /* 3e: Increase global floppy drives count */
            IoGetConfigurationInformation()->FloppyCount++;

            /* 3f: Set up the DPC */
            IoInitializeDpcRequest(gControllerInfo[i].DriveInfo[j].DeviceObject, (PIO_DPC_ROUTINE)DpcForIsr);

            /* 3g: Point the device extension at our DriveInfo struct */
            gControllerInfo[i].DriveInfo[j].DeviceObject->DeviceExtension = &gControllerInfo[i].DriveInfo[j];

            /* 3h: neat comic strip */

            /* 3i: set the initial media type to unknown */
            memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY));
            gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown;

            /* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */
            gControllerInfo[i].DriveInfo[j].Initialized = TRUE;

            /* 3k: Clear the DO_DEVICE_INITIALIZING flag */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        }
    }

    INFO_(FLOPPY, "AddControllers: --------------------------------------------> finished adding controllers\n");

    return TRUE;
}
Beispiel #4
0
NTSTATUS
SoundCreateDevice(
    IN   PCSOUND_DEVICE_INIT DeviceInit,
    IN   UCHAR CreationFlags,
    IN   PDRIVER_OBJECT pDriverObject,
    IN   PVOID pGDI,
    IN   PVOID DeviceSpecificData,
    IN   PVOID pHw,
    IN   int i,
    OUT  PDEVICE_OBJECT *ppDevObj
)

/*++

Routine Description:

    Create a new device using a name derived from szPrototypeName
    by adding a number on to the end such that the no device with the
    qualified name exists.

    A symbolic link in \DosDevices is also created

Arguments:

    DeviceInit - device initialization data

    NoRange - if this is set then no number is concatenated, the
          explicit name is used.

    pDriverObject - our driver

    pGDI - global context

    pHw - hardware context

    i - device number for back reference

    ppDevObj - where to write back the device object pointer

Return Value:

    An NTSTATUS code.

--*/

{

    UCHAR DeviceNumber;
    NTSTATUS Status;
    UNICODE_STRING DeviceName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PLOCAL_DEVICE_INFO pLDI;

    for (DeviceNumber = 0; ; DeviceNumber++) {

        //
        // Append the device number if required
        //

        if ((CreationFlags & SOUND_CREATION_NO_NAME_RANGE)) {
            DeviceNumber = 255;
        }

        Status = SoundCreateDeviceName(
                     L"",
                     DeviceInit->PrototypeName,
                     DeviceNumber,
                     &DeviceName);

        if (!NT_SUCCESS(Status)) {
            return Status;
        }

        Status = IoCreateDevice(
                     pDriverObject,
                     sizeof(LOCAL_DEVICE_INFO),
                     &DeviceName,
                     DeviceInit->Type,
                     0,
                     FALSE,                      // Non-Exclusive
                     ppDevObj
                     );

        if (NT_SUCCESS(Status)) {
            dprintf2(("Created device %d", DeviceNumber));

            //
            // Set up the rest of the device stuff
            //

            (*ppDevObj)->Flags |= DeviceInit->IoMethod;
            (*ppDevObj)->AlignmentRequirement = FILE_BYTE_ALIGNMENT;

            if (DeviceInit->DeferredRoutine) {
                IoInitializeDpcRequest((*ppDevObj), DeviceInit->DeferredRoutine);
            }

            pLDI = (*ppDevObj)->DeviceExtension;
            RtlZeroMemory(pLDI, sizeof(*pLDI));

            //
            // Try to create a symbolic link object for this device
            //
            // No security
            //
            // We make (eg)
            //    \DosDevices\WaveOut0
            // Point to
            //    \Device\WaveOut0
            //

            {
                UNICODE_STRING LinkObject;

                Status = SoundCreateDeviceName(
                             L"\\DosDevices\\",
                             DeviceInit->PrototypeName + wcslen(L"\\Device\\"),
                             DeviceNumber,
                             &LinkObject);

                if (NT_SUCCESS(Status)) {
                    Status = IoCreateSymbolicLink(&LinkObject, &DeviceName);
                    ExFreePool(LinkObject.Buffer);
                }

                ExFreePool(DeviceName.Buffer);

                if (!NT_SUCCESS(Status)) {
                    dprintf1(("Failed to create symbolic link object"));
                    IoDeleteDevice(*ppDevObj);
                    *ppDevObj = NULL;
                    return Status;
                }
            }

            //
            // Fill in the rest of the device information
            //

#ifdef VOLUME_NOTIFY
            InitializeListHead(&pLDI->VolumeQueue);
#endif // VOLUME_NOTIFY

            pLDI->DeviceNumber = DeviceNumber;
            pLDI->DeviceInit = DeviceInit;
            pLDI->CreationFlags = CreationFlags;

            pLDI->Key = *(PULONG)DeviceInit->Key;
            pLDI->DeviceType = (UCHAR)DeviceInit->DeviceType;
            pLDI->DeviceIndex = (UCHAR)i;
            pLDI->pGlobalInfo = pGDI;
            pLDI->DeviceSpecificData = DeviceSpecificData;
            pLDI->HwContext = pHw;
            pLDI->VolumeControlId = SOUND_MIXER_INVALID_CONTROL_ID;

            return STATUS_SUCCESS;
        } else {

            ExFreePool(DeviceName.Buffer);
        }

        if (DeviceNumber >= SOUND_MAX_DEVICES) {
            break;
        }
    }

    //
    // Failed !
    //

    return STATUS_INSUFFICIENT_RESOURCES;
}
NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath)
#endif
{
    PVBOXGUESTDEVEXT pDevExt   = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension;
#ifndef TARGET_NT4
    PIO_STACK_LOCATION pStack  = IoGetCurrentIrpStackLocation(pIrp);
#endif

    Log(("VBoxGuest::vboxguestwinInit\n"));

    int rc = STATUS_SUCCESS;
#ifdef TARGET_NT4
    /*
     * Let's have a look at what our PCI adapter offers.
     */
    Log(("VBoxGuest::vboxguestwinInit: Starting to scan PCI resources of VBoxGuest ...\n"));

    /* Assign the PCI resources. */
    PCM_RESOURCE_LIST pResourceList = NULL;
    UNICODE_STRING classNameString;
    RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter");
    rc = HalAssignSlotResources(pRegPath, &classNameString,
                                pDrvObj, pDevObj,
                                PCIBus, pDevExt->win.s.busNumber, pDevExt->win.s.slotNumber,
                                &pResourceList);
    if (pResourceList && pResourceList->Count > 0)
        vboxguestwinShowDeviceResources(&pResourceList->List[0].PartialResourceList);
    if (NT_SUCCESS(rc))
        rc = vboxguestwinScanPCIResourceList(pResourceList, pDevExt);
#else
    if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0)
        vboxguestwinShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList);
    if (NT_SUCCESS(rc))
        rc = vboxguestwinScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated,
                                             pDevExt);
#endif
    if (NT_SUCCESS(rc))
    {
        /*
         * Map physical address of VMMDev memory into MMIO region
         * and init the common device extension bits.
         */
        void *pvMMIOBase = NULL;
        uint32_t cbMMIO = 0;
        rc = vboxguestwinMapVMMDevMemory(pDevExt,
                                         pDevExt->win.s.vmmDevPhysMemoryAddress,
                                         pDevExt->win.s.vmmDevPhysMemoryLength,
                                         &pvMMIOBase,
                                         &cbMMIO);
        if (NT_SUCCESS(rc))
        {
            pDevExt->pVMMDevMemory = (VMMDevMemory *)pvMMIOBase;

            Log(("VBoxGuest::vboxguestwinInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->pVMMDevMemory = 0x%p\n",
                 pvMMIOBase, pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));

            int vrc = VBoxGuestInitDevExt(pDevExt,
                                          pDevExt->IOPortBase,
                                          pvMMIOBase, cbMMIO,
                                          vboxguestwinVersionToOSType(g_winVersion),
                                          VMMDEV_EVENT_MOUSE_POSITION_CHANGED);
            if (RT_FAILURE(vrc))
            {
                Log(("VBoxGuest::vboxguestwinInit: Could not init device extension, rc = %Rrc!\n", vrc));
                rc = STATUS_DEVICE_CONFIGURATION_ERROR;
            }
        }
        else
            Log(("VBoxGuest::vboxguestwinInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc));
    }

    if (NT_SUCCESS(rc))
    {
        int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->win.s.pPowerStateRequest,
                              sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus);
        if (RT_FAILURE(vrc))
        {
            Log(("VBoxGuest::vboxguestwinInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc));
            rc = STATUS_UNSUCCESSFUL;
        }
    }

    if (NT_SUCCESS(rc))
    {
        /*
         * Register DPC and ISR.
         */
        Log(("VBoxGuest::vboxguestwinInit: Initializing DPC/ISR ...\n"));

        IoInitializeDpcRequest(pDevExt->win.s.pDeviceObject, vboxguestwinDpcHandler);
#ifdef TARGET_NT4
        ULONG uInterruptVector;
        KIRQL irqLevel;
        /* Get an interrupt vector. */
        /* Only proceed if the device provides an interrupt. */
        if (   pDevExt->win.s.interruptLevel
            || pDevExt->win.s.interruptVector)
        {
            Log(("VBoxGuest::vboxguestwinInit: Getting interrupt vector (HAL): Bus: %u, IRQL: %u, Vector: %u\n",
                 pDevExt->win.s.busNumber, pDevExt->win.s.interruptLevel, pDevExt->win.s.interruptVector));

            uInterruptVector = HalGetInterruptVector(PCIBus,
                                                     pDevExt->win.s.busNumber,
                                                     pDevExt->win.s.interruptLevel,
                                                     pDevExt->win.s.interruptVector,
                                                     &irqLevel,
                                                     &pDevExt->win.s.interruptAffinity);
            Log(("VBoxGuest::vboxguestwinInit: HalGetInterruptVector returns vector %u\n", uInterruptVector));
            if (uInterruptVector == 0)
                Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n"));
        }
        else
            Log(("VBoxGuest::vboxguestwinInit: Device does not provide an interrupt!\n"));
#endif
        if (pDevExt->win.s.interruptVector)
        {
            Log(("VBoxGuest::vboxguestwinInit: Connecting interrupt ...\n"));

            rc = IoConnectInterrupt(&pDevExt->win.s.pInterruptObject,          /* Out: interrupt object. */
                                    (PKSERVICE_ROUTINE)vboxguestwinIsrHandler, /* Our ISR handler. */
                                    pDevExt,                                   /* Device context. */
                                    NULL,                                      /* Optional spinlock. */
#ifdef TARGET_NT4
                                    uInterruptVector,                          /* Interrupt vector. */
                                    irqLevel,                                  /* Interrupt level. */
                                    irqLevel,                                  /* Interrupt level. */
#else
                                    pDevExt->win.s.interruptVector,            /* Interrupt vector. */
                                    (KIRQL)pDevExt->win.s.interruptLevel,      /* Interrupt level. */
                                    (KIRQL)pDevExt->win.s.interruptLevel,      /* Interrupt level. */
#endif
                                    pDevExt->win.s.interruptMode,              /* LevelSensitive or Latched. */
                                    TRUE,                                      /* Shareable interrupt. */
                                    pDevExt->win.s.interruptAffinity,          /* CPU affinity. */
                                    FALSE);                                    /* Don't save FPU stack. */
            if (NT_ERROR(rc))
                Log(("VBoxGuest::vboxguestwinInit: Could not connect interrupt, rc = 0x%x\n", rc));
        }
        else
            Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n"));
    }


#ifdef VBOX_WITH_HGCM
    Log(("VBoxGuest::vboxguestwinInit: Allocating kernel session data ...\n"));
    int vrc = VBoxGuestCreateKernelSession(pDevExt, &pDevExt->win.s.pKernelSession);
    if (RT_FAILURE(vrc))
    {
        Log(("VBoxGuest::vboxguestwinInit: Failed to allocated kernel session data! rc = %Rrc\n", rc));
        rc = STATUS_UNSUCCESSFUL;
    }
#endif

    if (RT_SUCCESS(rc))
    {
        ULONG ulValue = 0;
        NTSTATUS s = vboxguestwinRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled",
                                                   &ulValue);
        if (NT_SUCCESS(s))
        {
            pDevExt->fLoggingEnabled = ulValue >= 0xFF;
            if (pDevExt->fLoggingEnabled)
                Log(("Logging to release log enabled (0x%x)", ulValue));
        }

        /* Ready to rumble! */
        Log(("VBoxGuest::vboxguestwinInit: Device is ready!\n"));
        VBOXGUEST_UPDATE_DEVSTATE(pDevExt, WORKING);
    }
    else
    {
        pDevExt->win.s.pInterruptObject = NULL;
    }

    Log(("VBoxGuest::vboxguestwinInit: Returned with rc = 0x%x\n", rc));
    return rc;
}