|
|
////////////////////////////////////////////////////////////////////////////
//
// 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
/////////////////////////////////////////////////////////////////
|