windows-nt/Source/XPSP1/NT/net/tdi/sample/sys/tdipnp.cpp
2020-09-26 16:20:57 +08:00

775 lines
22 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2001 Microsoft Corporation
//
// Module Name:
// tdipnp.cpp
//
// Abstract:
// This module contains the tdi pnp functions called from the tdilib.sys
//
/////////////////////////////////////////////////////////////////////////////
#include "sysvars.h"
extern "C"
{
#pragma warning(disable: NAMELESS_STRUCT_UNION)
#include "tdiinfo.h"
#pragma warning(default: NAMELESS_STRUCT_UNION)
}
////////////////////////////////////////////////////////
// private defines and prototypes
////////////////////////////////////////////////////////
VOID
TSPrintTdiContext(
PTDI_PNP_CONTEXT Context
);
VOID
TSRemoveFromDeviceList(
PTA_ADDRESS pTaAddress,
PCWSTR pDeviceName,
ULONG ulNameLength
);
VOID
TSAddToDeviceList(
PTA_ADDRESS pTaAddress,
PCWSTR pDeviceName,
ULONG ulNameLength
);
const PCHAR strFunc1 = "TSPnpBindCallback";
const PCHAR strFunc2 = "TSPnpPowerHandler";
const PCHAR strFunc3 = "TSPnpAddAddressCallback";
const PCHAR strFunc4 = "TSPnpDelAddressCallback";
const PCHAR strFunc5 = "TSGetNumDevices";
const PCHAR strFunc6 = "TSGetDevice";
const PCHAR strFunc7 = "TSGetAddress";
//const PCHAR strFuncP1 = "TSPrintTdiContext";
const PCHAR strFuncP2 = "TSAddToDeviceList";
//const PCHAR strFuncP3 = "TSRemoveFromDeviceList";
///////////////////////////////////////////////////////
// public functions
///////////////////////////////////////////////////////
// ---------------------------------------
//
// Function: TSPnpBindCallback
//
// Arguments: TdiPnpOpcode -- callback type
// pusDeviceName -- name of device to deal with
// pwstrBindingList -- information from registry Linkage key
// (if appropriate)
//
// Returns: none
//
// Descript: This function is called by tdi.sys when tdisample.sys
// registers its PnpCallbackHandlers. It is called several
// times, with the reason for each call in TdiPnpOpcode
//
// Currently, it just writes the information passed in to the
// debugger
//
// ---------------------------------------
VOID
TSPnpBindCallback(TDI_PNP_OPCODE TdiPnpOpcode,
PUNICODE_STRING pusDeviceName,
PWSTR pwstrBindingList)
{
if (ulDebugLevel & ulDebugShowHandlers)
{
if (pusDeviceName)
{
DebugPrint1("DeviceName: %wZ\r\n", pusDeviceName);
}
else
{
DebugPrint0("DeviceName: NULL\n");
}
DebugPrint0("OPCODE: ");
switch (TdiPnpOpcode)
{
case TDI_PNP_OP_MIN:
DebugPrint0("TDI_PNP_OP_MIN\n");
break;
case TDI_PNP_OP_ADD:
DebugPrint0("TDI_PNP_OP_ADD\n");
break;
case TDI_PNP_OP_DEL:
DebugPrint0("TDI_PNP_OP_DEL\n");
break;
case TDI_PNP_OP_UPDATE:
DebugPrint0("TDI_PNP_OP_UPDATE\n");
break;
case TDI_PNP_OP_PROVIDERREADY:
DebugPrint0("TDI_PNP_OP_PROVIDERREADY\n");
break;
case TDI_PNP_OP_NETREADY:
DebugPrint0("TDI_PNP_OP_NETREADY\n");
break;
default:
DebugPrint1("INCORRECT OPCODE FROM TDI!! [0x%08x]\n",
TdiPnpOpcode);
DbgBreakPoint();
break;
}
//
// this is the information from the registry under
// HKLM/SYSTEM/CurrentControlSet/Services/clientname/Linkage/Bind
//
if( pwstrBindingList == NULL )
{
DebugPrint0("Bindinglist is NULL\n");
}
else
{
ULONG_PTR ulStrLen;
DebugPrint0("BindingList:\n");
while (*pwstrBindingList)
{
DebugPrint1("%ws\n", pwstrBindingList);
ulStrLen = 1 + wcslen(pwstrBindingList);
pwstrBindingList += ulStrLen;
}
DebugPrint0("\n");
}
}
}
// --------------------------------------
//
// Function: TSPnpPowerHandler
//
// Arguments: pusDeviceName -- device name to deal with
// pNetPnpEvent -- power event to deal with
// pTdiPnpContext1
// pTdiPnpContext2
//
// Returns: status of operation
//
// Descript: This function deals with pnp and power management issues
//
// Currently, it just outputs information to the debugger
//
// --------------------------------------
NTSTATUS
TSPnpPowerHandler(PUNICODE_STRING pusDeviceName,
PNET_PNP_EVENT pNetPnpEvent,
PTDI_PNP_CONTEXT pTdiPnpContext1,
PTDI_PNP_CONTEXT pTdiPnpContext2)
{
if (ulDebugLevel & ulDebugShowHandlers)
{
if (pusDeviceName)
{
DebugPrint1("DeviceName: %wZ\r\n", pusDeviceName);
}
else
{
DebugPrint0("DeviceName: NULL\n");
}
switch (pNetPnpEvent->NetEvent)
{
case NetEventSetPower:
case NetEventQueryPower:
{
if (pNetPnpEvent->NetEvent == NetEventSetPower)
{
DebugPrint1("%s: NetEventSetPower--", strFunc2);
}
else
{
DebugPrint1("%s: NetEventQueryPower -- ", strFunc2);
}
NET_DEVICE_POWER_STATE NetDevicePowerState
= *(PNET_DEVICE_POWER_STATE)pNetPnpEvent->Buffer;
switch (NetDevicePowerState)
{
case NetDeviceStateUnspecified:
DebugPrint0("PowerStateUnspecified\n");
break;
case NetDeviceStateD0:
DebugPrint0("PowerUp\n");
break;
case NetDeviceStateD1:
case NetDeviceStateD2:
case NetDeviceStateD3:
DebugPrint0("PowerDown\n");
break;
}
break;
}
case NetEventQueryRemoveDevice:
DebugPrint1("%s: NetEventQueryRemoveDevice\n", strFunc2);
break;
case NetEventCancelRemoveDevice:
DebugPrint1("%s: NetEventCancelRemoveDevice\n", strFunc2);
break;
case NetEventReconfigure:
DebugPrint1("%s: NetEventReconfigure\n", strFunc2);
break;
case NetEventBindList:
DebugPrint1("%s: NetEventBindList\n", strFunc2);
break;
case NetEventBindsComplete:
DebugPrint1("%s: NetEventBindsComplete\n", strFunc2);
break;
case NetEventPnPCapabilities:
DebugPrint1("%s: NetEventPnPCapabilities\n", strFunc2);
break;
}
if (pTdiPnpContext1)
{
DebugPrint0("TdiPnpContext1:\n");
TSPrintTdiContext(pTdiPnpContext1);
}
if (pTdiPnpContext2)
{
DebugPrint0("TdiPnpContext2:\n");
TSPrintTdiContext(pTdiPnpContext2);
}
}
return STATUS_SUCCESS;
}
// -----------------------------------------------
//
// Function: TSPnpAddAddressCallback
//
// Arguments: pTaAddress -- address to register
// pusDeviceName -- device name associated with address
// pTdiPnpContext
//
// Returns: none
//
// Descript: called by tdi.sys. When called, tdisample adds this device
// to its registered list, if it recognizes the address format
//
// -----------------------------------------------
VOID
TSPnpAddAddressCallback(PTA_ADDRESS pTaAddress,
PUNICODE_STRING pusDeviceName,
PTDI_PNP_CONTEXT pTdiPnpContext)
{
if (ulDebugLevel & ulDebugShowHandlers)
{
//
// write info to debugger
//
DebugPrint1("DeviceName: %wZ\r\n", pusDeviceName);
TSPrintTaAddress(pTaAddress);
if (pTdiPnpContext)
{
DebugPrint0("TdiPnpContext:\n");
TSPrintTdiContext(pTdiPnpContext);
}
}
//
// add this to our list of devices/addresses, if appropriate
//
TSAddToDeviceList(pTaAddress,
pusDeviceName->Buffer,
pusDeviceName->Length);
}
// -----------------------------------------------
//
// Function: TSDelAddAddressCallback
//
// Arguments: pTaAddress -- address to de-register
// pusDeviceName -- device name associated with address
// pTdiPnpContext
//
// Returns: none
//
// Descript: called by tdi.sys. When called, tdisample removes this device
// to its registered list, if it recognizes the address format
//
// -----------------------------------------------
VOID
TSPnpDelAddressCallback(PTA_ADDRESS pTaAddress,
PUNICODE_STRING pusDeviceName,
PTDI_PNP_CONTEXT pTdiPnpContext)
{
if (ulDebugLevel & ulDebugShowHandlers)
{
DebugPrint1("DeviceName: %wZ\r\n", pusDeviceName);
TSPrintTaAddress(pTaAddress);
if (pTdiPnpContext)
{
DebugPrint0("TdiPnpContext:\n");
TSPrintTdiContext(pTdiPnpContext);
}
}
//
// remove this from our list of devices/addresses, if appropriate
//
TSRemoveFromDeviceList(pTaAddress,
pusDeviceName->Buffer,
pusDeviceName->Length);
}
// ----------------------------------------
//
// Function: TSGetNumDevices
//
// Arguments: pSendBuffer
// pReceiveBuffer
//
// Returns: none
//
// Descript: Finds the number of devices in tdidevicelist,
// and returns that value..
//
// ----------------------------------------
VOID
TSGetNumDevices(PSEND_BUFFER pSendBuffer,
PRECEIVE_BUFFER pReceiveBuffer)
{
ULONG ulSlot = 0;
ULONG ulAddressType = pSendBuffer->COMMAND_ARGS.GetDevArgs.ulAddressType;
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint1("\nCommand = ulGETNUMDEVICES\n"
"AddressType = 0x%08x\n",
ulAddressType);
}
TSAcquireSpinLock(&pTdiDevnodeList->TdiSpinLock);
for (ULONG ulCount = 0; ulCount < ulMAX_DEVICE_NODES; ulCount++)
{
PTDI_DEVICE_NODE pTdiDeviceNode = &(pTdiDevnodeList->TdiDeviceNode[ulCount]);
if ((pTdiDeviceNode->ulState != ulDEVSTATE_UNUSED) &&
(pTdiDeviceNode->pTaAddress->AddressType == (USHORT)ulAddressType))
{
++ulSlot;
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
pReceiveBuffer->RESULTS.ulReturnValue = ulSlot;
}
// ----------------------------------------
//
// Function: TSGetDevice
//
// Arguments: pSendBuffer -- arguments
// pReceiveBuffer -- where to put result
//
// Returns: NTSTATUS (success if finds slot, else false)
//
// Descript: Finds the device name indicated, and returns
// the string for that value
//
// ----------------------------------------
NTSTATUS
TSGetDevice(PSEND_BUFFER pSendBuffer,
PRECEIVE_BUFFER pReceiveBuffer)
{
ULONG ulSlot = 0;
ULONG ulAddressType = pSendBuffer->COMMAND_ARGS.GetDevArgs.ulAddressType;
ULONG ulSlotNum = pSendBuffer->COMMAND_ARGS.GetDevArgs.ulSlotNum;
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulGETDEVICE\n"
"AddressType = 0x%08x\n"
"SlotNum = %d\n",
ulAddressType,
ulSlotNum);
}
TSAcquireSpinLock(&pTdiDevnodeList->TdiSpinLock);
for (ULONG ulCount = 0; ulCount < ulMAX_DEVICE_NODES; ulCount++)
{
PTDI_DEVICE_NODE pTdiDeviceNode = &(pTdiDevnodeList->TdiDeviceNode[ulCount]);
if ((pTdiDeviceNode->ulState != ulDEVSTATE_UNUSED) &&
(pTdiDeviceNode->pTaAddress->AddressType == (USHORT)ulAddressType))
{
if (ulSlot == ulSlotNum)
{
if (pTdiDeviceNode->ustrDeviceName.MaximumLength > (ulMAX_CNTSTRING_LENGTH * sizeof(WCHAR)))
{
DebugPrint0("string length problem!\n");
DbgBreakPoint();
}
RtlZeroMemory(&pReceiveBuffer->RESULTS.ucsStringReturn.wcBuffer,
ulMAX_CNTSTRING_LENGTH * sizeof(WCHAR));
pReceiveBuffer->RESULTS.ucsStringReturn.usLength
= pTdiDeviceNode->ustrDeviceName.Length;
RtlCopyMemory(pReceiveBuffer->RESULTS.ucsStringReturn.wcBuffer,
pTdiDeviceNode->ustrDeviceName.Buffer,
pTdiDeviceNode->ustrDeviceName.Length);
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
if (pTdiDeviceNode->ulState == ulDEVSTATE_INUSE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
++ulSlot;
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
return STATUS_UNSUCCESSFUL;
}
// ----------------------------------------
//
// Function: TSGetAddress
//
// Arguments: pSendBuffer -- arguments
// pReceiveBuffer -- where to put result
//
// Returns: NTSTATUS (success if finds slot, else false)
//
// Descript: Finds the device name indicated, and returns
// the string for that value
//
// ----------------------------------------
NTSTATUS
TSGetAddress(PSEND_BUFFER pSendBuffer,
PRECEIVE_BUFFER pReceiveBuffer)
{
ULONG ulSlot = 0;
ULONG ulAddressType = pSendBuffer->COMMAND_ARGS.GetDevArgs.ulAddressType;
ULONG ulSlotNum = pSendBuffer->COMMAND_ARGS.GetDevArgs.ulSlotNum;
if (ulDebugLevel & ulDebugShowCommand)
{
DebugPrint2("\nCommand = ulGETADDRESS\n"
"AddressType = 0x%08x\n"
"SlotNum = %d\n",
ulAddressType,
ulSlotNum);
}
TSAcquireSpinLock(&pTdiDevnodeList->TdiSpinLock);
for (ULONG ulCount = 0; ulCount < ulMAX_DEVICE_NODES; ulCount++)
{
PTDI_DEVICE_NODE pTdiDeviceNode = &(pTdiDevnodeList->TdiDeviceNode[ulCount]);
if ((pTdiDeviceNode->ulState != ulDEVSTATE_UNUSED) &&
(pTdiDeviceNode->pTaAddress->AddressType == (USHORT)ulAddressType))
{
if (ulSlot == ulSlotNum)
{
ULONG ulLength = FIELD_OFFSET(TA_ADDRESS, Address)
+ pTdiDeviceNode->pTaAddress->AddressLength;
pReceiveBuffer->RESULTS.TransAddr.TAAddressCount = 1;
RtlCopyMemory(&pReceiveBuffer->RESULTS.TransAddr.TaAddress,
pTdiDeviceNode->pTaAddress,
ulLength);
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
if (pTdiDeviceNode->ulState == ulDEVSTATE_INUSE)
{
return STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
++ulSlot;
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
return STATUS_UNSUCCESSFUL;
}
//////////////////////////////////////////////////////
// private functions
//////////////////////////////////////////////////////
// ---------------------------------
//
// Function: TSPrintTdiContext
//
// Arguments: pTdiPnpContext -- context to dump
//
// Returns: none
//
// Descript: prints out information in pTdiPnpContext structure
//
// ---------------------------------
VOID
TSPrintTdiContext(PTDI_PNP_CONTEXT pTdiPnpContext)
{
if (pTdiPnpContext)
{
PUCHAR pucTemp = pTdiPnpContext->ContextData;
DebugPrint2("TdiPnpContextSize: %u\n"
"TdiPnpContextType: %u\n"
"TdiPnpContextData: ",
pTdiPnpContext->ContextSize,
pTdiPnpContext->ContextType);
for (ULONG ulCount = 0; ulCount < pTdiPnpContext->ContextSize; ulCount++)
{
DebugPrint1("%02x ", *pucTemp);
++pucTemp;
}
DebugPrint0("\n");
}
}
// ------------------------------------------
//
// Function: TSAddToDeviceList
//
// Arguments: pTaAddress -- current address structure
// pusDeviceName -- actual name of device
//
// Returns: none
//
// Descript: Adds this device to our device list, if appropriate
//
// ------------------------------------------
VOID
TSAddToDeviceList(PTA_ADDRESS pTaAddress,
PCWSTR pDeviceName,
ULONG ulNameLength)
{
//
// scan list for first available slot. For any slot before the first
// available whose entry has been deleted, check to see if this is the
// same device coming back
//
ULONG ulLengthNeeded = FIELD_OFFSET(TA_ADDRESS, Address)
+ pTaAddress->AddressLength;
ULONG ulAddressType = pTaAddress->AddressType;
TSAcquireSpinLock(&pTdiDevnodeList->TdiSpinLock);
for (ULONG ulCount = 0; ulCount < ulMAX_DEVICE_NODES; ulCount++)
{
PTDI_DEVICE_NODE pTdiDeviceNode = &(pTdiDevnodeList->TdiDeviceNode[ulCount]);
switch (pTdiDeviceNode->ulState)
{
//
// this is first unused slot
// allocate buffers and set
//
case ulDEVSTATE_UNUSED:
if ((TSAllocateMemory((PVOID *)&pTdiDeviceNode->pTaAddress,
ulLengthNeeded,
strFuncP2,
"TaAddress")) == STATUS_SUCCESS)
{
if ((TSAllocateMemory((PVOID *)&pTdiDeviceNode->ustrDeviceName.Buffer,
ulNameLength+2,
strFuncP2,
"Buffer")) == STATUS_SUCCESS)
{
RtlCopyMemory(pTdiDeviceNode->pTaAddress,
pTaAddress,
ulLengthNeeded);
pTdiDeviceNode->ustrDeviceName.MaximumLength = (USHORT)(ulNameLength + 2);
pTdiDeviceNode->ustrDeviceName.Length = (USHORT)ulNameLength;
RtlCopyMemory(pTdiDeviceNode->ustrDeviceName.Buffer,
pDeviceName,
ulNameLength);
pTdiDeviceNode->ulState = ulDEVSTATE_INUSE;
}
else
{
TSFreeMemory(pTdiDeviceNode->pTaAddress);
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
return;
//
// device in slot has been removed. See if this is the same
// device coming back
//
case ulDEVSTATE_DELETED:
{
//
// check for correct name
//
ULONG_PTR ulCompareLength = RtlCompareMemory(pTdiDeviceNode->ustrDeviceName.Buffer,
pDeviceName,
ulNameLength);
if (ulCompareLength == ulNameLength)
{
//
// for tcpip, netbios, and appletalk this is enough
// for ipx/spx, need to check address as well
//
if (ulAddressType == TDI_ADDRESS_TYPE_IPX)
{
ulCompareLength = RtlCompareMemory(pTdiDeviceNode->pTaAddress,
pTaAddress,
pTaAddress->AddressLength + sizeof(ULONG));
//
// if address is incorrect, not right ipx
//
if (ulCompareLength != pTaAddress->AddressLength + sizeof(ULONG))
{
break;
}
}
else
{
//
// copy address info over in case it changed..
//
RtlCopyMemory(pTdiDeviceNode->pTaAddress,
pTaAddress,
ulLengthNeeded);
}
pTdiDeviceNode->ulState = ulDEVSTATE_INUSE;
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
return;
}
}
break;
//
// device in slot is in used. Leave it alone
//
case ulDEVSTATE_INUSE:
break;
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
}
// ------------------------------------------
//
// Function: TSRemoveFromDeviceList
//
// Arguments: pTaAddress -- current address structure
// pusDeviceName -- actual name of device
//
// Returns: none
//
// Descript: Remove this device from our device list, if is it
// on it..
//
// ------------------------------------------
VOID
TSRemoveFromDeviceList(PTA_ADDRESS pTaAddress,
PCWSTR pDeviceName,
ULONG ulNameLength)
{
//
// search list for the item to remove..
//
TSAcquireSpinLock(&pTdiDevnodeList->TdiSpinLock);
for (ULONG ulCount = 0; ulCount < ulMAX_DEVICE_NODES; ulCount++)
{
PTDI_DEVICE_NODE pTdiDeviceNode = &(pTdiDevnodeList->TdiDeviceNode[ulCount]);
//
// check to see that it is the right node...
// first check to see if the address is correct
//
ULONG_PTR ulCompareLength = RtlCompareMemory(pTdiDeviceNode->pTaAddress,
pTaAddress,
pTaAddress->AddressLength + sizeof(ULONG));
//
// if address is correct, check for correct name
//
if (ulCompareLength == pTaAddress->AddressLength + sizeof(ULONG))
{
ulCompareLength = RtlCompareMemory(pTdiDeviceNode->ustrDeviceName.Buffer,
pDeviceName,
ulNameLength);
//
// if this matches, it's the right node. Delete it!
//
if (ulCompareLength == ulNameLength)
{
pTdiDeviceNode->ulState = ulDEVSTATE_DELETED;
break;
}
}
}
TSReleaseSpinLock(&pTdiDevnodeList->TdiSpinLock);
}
/////////////////////////////////////////////////////////////////
// end of file tdipnp.cpp
/////////////////////////////////////////////////////////////////