blob: 348df824d4e23a69c16f4b34df995be3c6e29718 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This module has code to deal with loading and unloading of the driver
*/
#include "pch.hpp"
#include "driver.tmh"
#ifdef OTTMP_LEGACY
static GLOBALS GlobalData = { 0 };
#endif
INITCODE
extern "C"
NTSTATUS
DriverEntry (
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
DriverEntry initializes the driver and is the first routine called by the
system after the driver is loaded. DriverEntry specifies the other entry
points in the function driver, such as EvtDevice and DriverUnload.
Parameters Description:
DriverObject - represents the instance of the function driver that is loaded
into memory. DriverEntry must initialize members of DriverObject before it
returns to the caller. DriverObject is allocated by the system before the
driver is loaded, and it is released by the system after the system unloads
the function driver from memory.
RegistryPath - represents the driver specific path in the Registry.
The function driver can use the path to store driver related data between
reboots. The path does not store hardware instance specific data.
Return Value:
A success status as determined by NT_SUCCESS macro, if successful.
--*/
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
#ifdef OTTMP_LEGACY
NDIS_STATUS ndisStatus = NDIS_STATUS_FAILURE;
NDIS_MINIPORT_DRIVER_CHARACTERISTICS MPChar = { 0 };
NET_BUFFER_LIST_POOL_PARAMETERS NblParams = { 0 };
NET_BUFFER_POOL_PARAMETERS NbParams = { 0 };
#endif
WPP_INIT_TRACING(DriverObject, RegistryPath);
LogFuncEntry(DRIVER_DEFAULT);
//
// Create the WdfDriver Object
//
WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
#ifdef OTTMP_LEGACY
//
// Set WdfDriverInitNoDispatchOverride flag to tell the framework
// not to provide dispatch routines for the driver. In other words,
// the framework must not intercept IRPs that the I/O manager has
// directed to the driver. In this case, it will be handled by NDIS
// port driver.
//
config.DriverInitFlags |= WdfDriverInitNoDispatchOverride;
#else
config.EvtDriverDeviceAdd = EvtDriverDeviceAdd;
config.EvtDriverUnload = EvtDriverUnload;
#endif
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
#ifdef OTTMP_LEGACY
&GlobalData.WdfDriver
#else
NULL
#endif
);
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "WdfDriverCreate failed, %!STATUS!", status);
goto error;
}
#ifdef OTTMP_LEGACY
MPChar.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
MPChar.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
MPChar.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
// Version Suff
MPChar.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
MPChar.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
MPChar.MajorDriverVersion = NIC_VENDOR_DRIVER_VERSION_MAJOR;
MPChar.MinorDriverVersion = NIC_VENDOR_DRIVER_VERSION_MINOR;
MPChar.InitializeHandlerEx = MPInitializeEx;
MPChar.HaltHandlerEx = MPHaltEx;
MPChar.UnloadHandler = MPDriverUnload;
MPChar.PauseHandler = MPPause;
MPChar.RestartHandler = MPRestart;
MPChar.OidRequestHandler = MPOidRequest;
MPChar.SendNetBufferListsHandler = MPSendNetBufferLists;
MPChar.ReturnNetBufferListsHandler = MPReturnNetBufferLists;
MPChar.CancelSendHandler = MPCancelSend;
MPChar.DevicePnPEventNotifyHandler = MPDevicePnpEventNotify;
MPChar.ShutdownHandlerEx = MPShutdownEx;
MPChar.CancelOidRequestHandler = MPCancelOidRequest;
ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
RegistryPath,
&GlobalData,
&MPChar,
&GlobalData.hDriver);
if (ndisStatus != NDIS_STATUS_SUCCESS)
{
LogError(DRIVER_DEFAULT, "NdisMRegisterMiniportDriver failed %!NDIS_STATUS!", ndisStatus);
status = STATUS_UNSUCCESSFUL;
goto error;
}
NblParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
NblParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
NblParams.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
NblParams.PoolTag = NIC_TAG_RECV_NBL;
GlobalData.hNblPool = NdisAllocateNetBufferListPool(GlobalData.hDriver, &NblParams);
if (GlobalData.hNblPool == 0)
{
LogError(DRIVER_DEFAULT, "NdisAllocateNetBufferListPool failed");
status = STATUS_INSUFFICIENT_RESOURCES;
goto error;
}
NbParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
NbParams.Header.Revision = NET_BUFFER_POOL_PARAMETERS_REVISION_1;
NbParams.Header.Size = NDIS_SIZEOF_NET_BUFFER_POOL_PARAMETERS_REVISION_1;
NbParams.PoolTag = NIC_TAG_RECV_NBL;
NbParams.DataSize = MAX_SPINEL_COMMAND_LENGTH;
GlobalData.hNbPool = NdisAllocateNetBufferPool(GlobalData.hDriver, &NbParams);
if (GlobalData.hNbPool == 0)
{
LogError(DRIVER_DEFAULT, "NdisAllocateNetBufferListPool failed");
status = STATUS_INSUFFICIENT_RESOURCES;
goto error;
}
#endif
error:
if (!NT_SUCCESS(status))
{
#ifdef OTTMP_LEGACY
MPDriverUnload(DriverObject);
#else
WPP_CLEANUP(DriverObject);
#endif
}
LogFuncExitNT(DRIVER_DEFAULT, status);
return status;
}
#ifdef OTTMP_LEGACY
PAGED
_Use_decl_annotations_
VOID
MPDriverUnload(
_In_ PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
MPDriverUnload will clean up the WPP resources that was allocated
for this driver.
Arguments:
DriverObject - Handle to a framework driver object created in DriverEntry
--*/
{
LogFuncEntry(DRIVER_DEFAULT);
PAGED_CODE();
if (GlobalData.WdfDriver)
{
NT_ASSERT(GlobalData.WdfDriver == WdfGetDriver());
WdfDriverMiniportUnload(GlobalData.WdfDriver);
GlobalData.WdfDriver = nullptr;
}
if (GlobalData.hNblPool)
{
NdisFreeNetBufferListPool(GlobalData.hNblPool);
GlobalData.hNblPool = nullptr;
}
if (GlobalData.hDriver)
{
NdisMDeregisterMiniportDriver(GlobalData.hDriver);
GlobalData.hDriver = nullptr;
}
LogFuncExit(DRIVER_DEFAULT);
#pragma warning(suppress: 25024) // Dangerous cast
WPP_CLEANUP(DriverObject);
}
#else
PAGED
VOID
EvtDriverUnload(
WDFDRIVER Driver
)
/*++
Routine Description:
EvtDriverUnload will clean up the WPP resources that was allocated
for this driver.
Arguments:
Driver - Handle to a framework driver object created in DriverEntry
--*/
{
LogFuncEntry(DRIVER_DEFAULT);
PAGED_CODE();
LogFuncExit(DRIVER_DEFAULT);
WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));
}
#endif