_Must_inspect_result_
BOOLEAN
FX_DRIVER_GLOBALS::IsDebuggerAttached(
    VOID
    )
{
    return (FALSE == KdRefreshDebuggerNotPresent());
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT  DriverObject,IN PUNICODE_STRING RegistryPath) {
	NTSTATUS				status;
	WDF_DRIVER_CONFIG		config;
    WDF_OBJECT_ATTRIBUTES	attributes;
	
#if defined(_DEBUG) || defined(DBG)
//	if (TRUE == KdRefreshDebuggerNotPresent())
//		return STATUS_UNSUCCESSFUL;// For the time being, don't load the driver if no debugger is attached
//	DbgBreakPoint();
	if (FALSE == KdRefreshDebuggerNotPresent())
		DbgBreakPoint();
#endif
	
    // Initialize WPP Tracing
    WPP_INIT_TRACING( DriverObject, RegistryPath );
	WPP_FLAG_LEVEL_ENABLED(MYDRIVER_ALL_INFO, TRACE_LEVEL_VERBOSE);

	TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "UsbCfgCtrl>> DriverEntry " __DATE__ " " __TIME__ "\r\n");

    // Register a cleanup callback so that we can call WPP_CLEANUP when the framework driver object is deleted during driver unload.
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
	attributes.EvtCleanupCallback = [](IN WDFOBJECT DriverObject) {
		TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
		// Stop WPP Tracing
		WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
	};

	WDF_DRIVER_CONFIG_INIT(&config, UsbCfgDevice::CreateDevice);// UsbCfgCtrlEvtDeviceAdd);

    status = WdfDriverCreate(DriverObject, RegistryPath, &attributes, &config, WDF_NO_HANDLE);
    if (NT_FAILED(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!\r\n", status);
        WPP_CLEANUP(DriverObject);
        return status;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit\r\n");

    return status;
}
NTSTATUS
DriverEntry(
__in PDRIVER_OBJECT  pDrvObj,
__in PUNICODE_STRING pRegistryPath
)
{
    NTSTATUS                       status = STATUS_SUCCESS;
#ifdef USE_STORPORT
    VIRTUAL_HW_INITIALIZATION_DATA hwInitData = { 0 };
#endif
#ifdef USE_SCSIPORT
    HW_INITIALIZATION_DATA         hwInitData = { 0 };
#endif
    pMPDriverInfo                  pMPDrvInfo;
    LARGE_INTEGER                  liTickCount;

    KdPrint(("PhDskMnt::DriverEntry: Begin '%wZ'.\n", pRegistryPath));
    
#if DBG

#if (NTDDI_VERSION >= NTDDI_WS03)
    KdRefreshDebuggerNotPresent();
#endif

    if (!KD_DEBUGGER_NOT_PRESENT)
        DbgBreakPoint();
#endif

#ifdef MP_DrvInfo_Inline

    // Because there's no good way to clean up the allocation of the global driver information, 
    // the global information is kept in an inline structure.

    pMPDrvInfo = &lclDriverInfo;

#else

    //
    // Allocate basic miniport driver object (shared across instances of miniport). The pointer is kept in the driver binary's static storage.
    //
    // Because there's no good way to clean up the allocation of the global driver information, 
    // the global information will be leaked.  This is deemed acceptable since it's not expected
    // that DriverEntry will be invoked often in the life of a Windows boot.
    //

    pMPDrvInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(MPDriverInfo), MP_TAG_GENERAL);

    if (!pMPDrvInfo) {                                // No good?
        status = STATUS_INSUFFICIENT_RESOURCES;

        goto Done;
    }

#endif

    // Initialize driver globals structure

    pMPDrvInfoGlobal = pMPDrvInfo;                    // Save pointer in binary's storage.

    RtlZeroMemory(pMPDrvInfo, sizeof(MPDriverInfo));  // Set pMPDrvInfo's storage to a known state.

    pMPDrvInfo->pDriverObj = pDrvObj;                 // Save pointer to driver object.

    KeInitializeSpinLock(&pMPDrvInfo->DrvInfoLock);   // Initialize spin lock.

    InitializeListHead(&pMPDrvInfo->ListMPHBAObj);    // Initialize list head.

    KeQueryTickCount(&liTickCount);
    pMPDrvInfo->RandomSeed = liTickCount.LowPart;     // Initialize random seed.

    // Get registry parameters.

    MpQueryRegParameters(pRegistryPath, &pMPDrvInfo->MPRegInfo);

    // Set up information for ScsiPortInitialize().

#ifdef USE_STORPORT
    hwInitData.HwInitializationDataSize = sizeof(VIRTUAL_HW_INITIALIZATION_DATA);
#endif
#ifdef USE_SCSIPORT
#ifdef NT4_COMPATIBLE
    hwInitData.HwInitializationDataSize = FIELD_OFFSET(HW_INITIALIZATION_DATA, HwAdapterControl);
#else
    hwInitData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
#endif
#endif

    hwInitData.HwInitialize = MpHwInitialize;           // Required for all ports.
    hwInitData.HwStartIo = MpHwStartIo;              // Required for all ports.
    hwInitData.HwFindAdapter = MpHwFindAdapter;          // Required for all ports.
    hwInitData.HwResetBus = MpHwResetBus;             // Required for all ports.
#ifndef NT4_COMPATIBLE
    hwInitData.HwAdapterControl = MpHwAdapterControl;       // Required for all > NT4 ports.
#endif

#ifdef USE_STORPORT
    hwInitData.HwFreeAdapterResources = MpHwFreeAdapterResources; // Required for virtual StorPort.
#endif

    hwInitData.AutoRequestSense = TRUE;

    hwInitData.TaggedQueuing = TRUE;
    hwInitData.MultipleRequestPerLu = TRUE;

    hwInitData.MapBuffers = STORAGE_MAP_BUFFERS_SETTING;

    hwInitData.DeviceExtensionSize = sizeof(HW_HBA_EXT);
    hwInitData.SpecificLuExtensionSize = sizeof(PVOID);
    hwInitData.SrbExtensionSize = sizeof(HW_SRB_EXTENSION);

    hwInitData.AdapterInterfaceType = STORAGE_INTERFACE_TYPE;

    status = StoragePortInitialize(                     // Tell port driver we're here.
        pDrvObj,
        pRegistryPath,
        (PHW_INITIALIZATION_DATA)&hwInitData,
        NULL
        );

    DbgPrint("PhDskMnt::DriverEntry: StoragePortInitialize returned 0x%X\n", status);

    if (NT_SUCCESS(status))
    {
        // Register our own dispatch hooks

        pMPDrvInfo->pChainUnload = pDrvObj->DriverUnload;
        pDrvObj->DriverUnload = ImScsiUnload;
    }
    else
    {
        ImScsiFreeGlobalResources();
    }

    KdPrint2(("PhDskMnt::DriverEntry: End. status=0x%X\n", status));

    return status;
}                                                     // End DriverEntry().
NTSTATUS RosKmdGlobal::DriverEntry(__in IN DRIVER_OBJECT* pDriverObject, __in IN UNICODE_STRING* pRegistryPath)
{
    NTSTATUS    Status;
    DRIVER_INITIALIZATION_DATA DriverInitializationData;

    // Only break into the debugger on driver entry if debugger is present
    if (KdRefreshDebuggerNotPresent() == FALSE)
    {
        DbgBreakPoint();
    }

    DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "DriverEntry\n");

    if (s_bDoNotInstall)
    {
        return STATUS_NO_MEMORY;
    }

    //
    // Allocate physically contiguous memory to represent cpu visible video memory
    //

    PHYSICAL_ADDRESS lowestAcceptableAddress;
    lowestAcceptableAddress.QuadPart = 0;

    PHYSICAL_ADDRESS highestAcceptableAddress;
    highestAcceptableAddress.QuadPart = -1;
    
    PHYSICAL_ADDRESS boundaryAddressMultiple;
    boundaryAddressMultiple.QuadPart = 0;

    s_videoMemorySize = kMaxVideoMemorySize;

    while (s_pVideoMemory == NULL)
    {
        //
        // The allocated contiguous memory is mapped as cached
        //
        // TODO[indyz]: Evaluate if flushing CPU cache for GPU access is the best option
        //
        // Use this option because GenerateRenderControlList has data alignment issue
        //

        s_pVideoMemory = MmAllocateContiguousMemorySpecifyCache(
                            s_videoMemorySize,
                            lowestAcceptableAddress,
                            highestAcceptableAddress,
                            boundaryAddressMultiple,
                            MmCached);
        if (s_pVideoMemory != NULL)
        {
            break;
        }

        s_videoMemorySize >>= 1;
    }

    s_videoMemoryPhysicalAddress = MmGetPhysicalAddress(s_pVideoMemory);

    //
    // Fill in the DriverInitializationData structure and call DlInitialize()
    //

    memset(&DriverInitializationData, 0, sizeof(DriverInitializationData));

    DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;

    DriverInitializationData.DxgkDdiAddDevice = RosKmdDdi::DdiAddAdapter;
    DriverInitializationData.DxgkDdiStartDevice = RosKmdDdi::DdiStartAdapter;
    DriverInitializationData.DxgkDdiStopDevice = RosKmdDdi::DdiStopAdapter;
    DriverInitializationData.DxgkDdiRemoveDevice = RosKmdDdi::DdiRemoveAdapter;

    DriverInitializationData.DxgkDdiDispatchIoRequest = RosKmdDdi::DdiDispatchIoRequest;
    DriverInitializationData.DxgkDdiInterruptRoutine = RosKmdDdi::DdiInterruptRoutine;
    DriverInitializationData.DxgkDdiDpcRoutine = RosKmdDdi::DdiDpcRoutine;

    DriverInitializationData.DxgkDdiQueryChildRelations = RosKmdDdi::DdiQueryChildRelations;
    DriverInitializationData.DxgkDdiQueryChildStatus = RosKmdDdi::DdiQueryChildStatus;
    DriverInitializationData.DxgkDdiQueryDeviceDescriptor = RosKmdDdi::DdiQueryDeviceDescriptor;
    DriverInitializationData.DxgkDdiSetPowerState = RosKmdDdi::DdiSetPowerState;
    DriverInitializationData.DxgkDdiNotifyAcpiEvent = RosKmdDdi::DdiNotifyAcpiEvent;
    DriverInitializationData.DxgkDdiResetDevice = RosKmdDdi::DdiResetDevice;
    DriverInitializationData.DxgkDdiUnload = RosKmdGlobal::DdiUnload;
    DriverInitializationData.DxgkDdiQueryInterface = RosKmdDdi::DdiQueryInterface;
    DriverInitializationData.DxgkDdiControlEtwLogging = RosKmdGlobal::DdiControlEtwLogging;

    DriverInitializationData.DxgkDdiQueryAdapterInfo = RosKmdDdi::DdiQueryAdapterInfo;

    DriverInitializationData.DxgkDdiCreateDevice = RosKmDevice::DdiCreateDevice;

    DriverInitializationData.DxgkDdiCreateAllocation = RosKmdDdi::DdiCreateAllocation;
    DriverInitializationData.DxgkDdiDestroyAllocation = RosKmdDdi::DdiDestroyAllocation;

    DriverInitializationData.DxgkDdiDescribeAllocation = RosKmdDdi::DdiDescribeAllocation;
    DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = RosKmdDdi::DdiGetStandardAllocationDriverData;

    // DriverInitializationData.DxgkDdiAcquireSwizzlingRange   = RosKmdAcquireSwizzlingRange;
    // DriverInitializationData.DxgkDdiReleaseSwizzlingRange   = RosKmdReleaseSwizzlingRange;

    DriverInitializationData.DxgkDdiOpenAllocation = RosKmDevice::DdiOpenAllocation;
    DriverInitializationData.DxgkDdiCloseAllocation = RosKmDevice::DdiCloseAllocation;

    DriverInitializationData.DxgkDdiPatch = RosKmdDdi::DdiPatch;
    DriverInitializationData.DxgkDdiSubmitCommand = RosKmdDdi::DdiSubmitCommand;
    DriverInitializationData.DxgkDdiBuildPagingBuffer = RosKmdDdi::DdiBuildPagingBuffer;
    DriverInitializationData.DxgkDdiPreemptCommand = RosKmdDdi::DdiPreemptCommand;

    DriverInitializationData.DxgkDdiDestroyDevice = RosKmDevice::DdiDestroyDevice;

    DriverInitializationData.DxgkDdiRender = RosKmContext::DdiRender;
    DriverInitializationData.DxgkDdiPresent = RosKmdDdi::DdiPresent;
    DriverInitializationData.DxgkDdiResetFromTimeout = RosKmdDdi::DdiResetFromTimeout;
    DriverInitializationData.DxgkDdiRestartFromTimeout = RosKmdDdi::DdiRestartFromTimeout;
    DriverInitializationData.DxgkDdiEscape = RosKmdDdi::DdiEscape;
    DriverInitializationData.DxgkDdiCollectDbgInfo = RosKmdDdi::DdiCollectDbgInfo;
    DriverInitializationData.DxgkDdiQueryCurrentFence = RosKmdDdi::DdiQueryCurrentFence;
    DriverInitializationData.DxgkDdiControlInterrupt = RosKmdDdi::DdiControlInterrupt;

    DriverInitializationData.DxgkDdiCreateContext = RosKmContext::DdiCreateContext;
    DriverInitializationData.DxgkDdiDestroyContext = RosKmContext::DdiDestroyContext;

    DriverInitializationData.DxgkDdiRenderKm = RosKmdDdi::DdiRenderKm;

    //
    // Fill in DDI routines for resetting individual engine
    //
    DriverInitializationData.DxgkDdiQueryDependentEngineGroup = RosKmdDdi::DdiQueryDependentEngineGroup;
    DriverInitializationData.DxgkDdiQueryEngineStatus = RosKmdDdi::DdiQueryEngineStatus;
    DriverInitializationData.DxgkDdiResetEngine = RosKmdDdi::DdiResetEngine;

    //
    // Fill in DDI for canceling DMA buffers
    //
    DriverInitializationData.DxgkDdiCancelCommand = RosKmdDdi::DdiCancelCommand;

    //
    // Fill in DDI for component power management
    //
    DriverInitializationData.DxgkDdiSetPowerComponentFState = RosKmdDdi::DdiSetPowerComponentFState;
    DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = RosKmdDdi::DdiPowerRuntimeControlRequest;

    DriverInitializationData.DxgkDdiGetNodeMetadata = RosKmdDdi::DdiGetNodeMetadata;

    DriverInitializationData.DxgkDdiSubmitCommandVirtual = RosKmdDdi::DdiSubmitCommandVirtual;

    DriverInitializationData.DxgkDdiCreateProcess = RosKmdDdi::DdiCreateProcess;
    DriverInitializationData.DxgkDdiDestroyProcess = RosKmdDdi::DdiDestroyProcess;

    DriverInitializationData.DxgkDdiCalibrateGpuClock = RosKmdDdi::DdiCalibrateGpuClock;
    DriverInitializationData.DxgkDdiSetStablePowerState = RosKmdDdi::DdiSetStablePowerState;

    Status = DxgkInitialize(pDriverObject, pRegistryPath, &DriverInitializationData);

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

    return Status;
}