|
|
/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
query.c
Abstract:
This module contains code which performs the following TDI services:
o TdiQueryInformation o TdiSetInformation
Environment:
Kernel mode
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Remove the warning -- this is defined in windef also.
//
#ifdef FAR
#undef FAR
#endif
#include <windef.h>
#include <nb30.h>
//
// Useful macro to obtain the total length of a buffer chain.
// Make this use NDIS macros ?
//
#define NbiGetBufferChainLength(Buffer, Length) { \
PNDIS_BUFFER _Buffer = (Buffer); \ *(Length) = 0; \ while (_Buffer) { \ *(Length) += MmGetMdlByteCount(_Buffer); \ _Buffer = _Buffer->Next; \ } \ }
NTSTATUS NbiTdiQueryInformation( IN PDEVICE Device, IN PREQUEST Request )
/*++
Routine Description:
This routine performs the TdiQueryInformation request for the transport provider.
Arguments:
Request - the request for the operation.
Return Value:
The status of operation.
--*/
{ NTSTATUS Status; PTDI_REQUEST_KERNEL_QUERY_INFORMATION Query; PADDRESS_FILE AddressFile; PADDRESS Address; PCONNECTION Connection; union { struct { ULONG ActivityCount; TA_NETBIOS_ADDRESS NbiAddress; } AddressInfo; TA_NETBIOS_ADDRESS BroadcastAddress; TDI_ADDRESS_IPX IpxAddress; TDI_DATAGRAM_INFO DatagramInfo; struct { FIND_NAME_HEADER Header; FIND_NAME_BUFFER Buffer; } FindNameInfo; } TempBuffer; IPX_SOURCE_ROUTING_INFO SourceRoutingInfo; PADAPTER_STATUS AdapterStatus; BOOLEAN RemoteAdapterStatus; TDI_ADDRESS_NETBIOS * RemoteAddress; ULONG TargetBufferLength; ULONG ActualBytesCopied; ULONG AdapterStatusLength; ULONG ValidStatusLength; ULONG ElementSize, TransportAddressSize; PTRANSPORT_ADDRESS TransportAddress; TA_ADDRESS * CurAddress; PNETBIOS_CACHE CacheName; FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL; UINT FindNameBufferLength; NTSTATUS QueryStatus; CTELockHandle LockHandle; PLIST_ENTRY p; BOOLEAN UsedConnection; UINT i;
//
// what type of status do we want?
//
Query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)REQUEST_PARAMETERS(Request);
switch (Query->QueryType) {
case TDI_QUERY_ADDRESS_INFO:
//
// The caller wants the exact address value.
//
if (REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
#if defined(_PNP_POWER)
Status = NbiVerifyAddressFile (AddressFile, CONFLICT_IS_NOT_OK); #else
Status = NbiVerifyAddressFile (AddressFile); #endif _PNP_POWER
if (!NT_SUCCESS(Status)) { break; }
UsedConnection = FALSE;
} else if (REQUEST_OPEN_TYPE(Request) == (PVOID)TDI_CONNECTION_FILE) {
Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
Status = NbiVerifyConnection (Connection);
if (!NT_SUCCESS(Status)) { break; }
if (!(AddressFile = Connection->AddressFile)) { Status = STATUS_INVALID_ADDRESS; break; }
UsedConnection = TRUE;
} else {
Status = STATUS_INVALID_ADDRESS; break;
}
Address = AddressFile->Address;
NB_DEBUG2 (QUERY, ("Query address info on %lx\n", AddressFile));
TempBuffer.AddressInfo.ActivityCount = 0;
NB_GET_LOCK (&Address->Lock, &LockHandle);
for (p = Address->AddressFileDatabase.Flink; p != &Address->AddressFileDatabase; p = p->Flink) {
if (CONTAINING_RECORD (p, ADDRESS_FILE, Linkage)->State == ADDRESSFILE_STATE_OPEN) { ++TempBuffer.AddressInfo.ActivityCount; } }
NB_FREE_LOCK (&Address->Lock, LockHandle);
TdiBuildNetbiosAddress( AddressFile->Address->NetbiosAddress.NetbiosName, (BOOLEAN)(AddressFile->Address->NetbiosAddress.NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP), &TempBuffer.AddressInfo.NbiAddress);
Status = TdiCopyBufferToMdl( &TempBuffer.AddressInfo, 0, sizeof(ULONG) + sizeof(TA_NETBIOS_ADDRESS), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied;
if (UsedConnection) {
NbiDereferenceConnection (Connection, CREF_VERIFY);
} else {
NbiDereferenceAddressFile (AddressFile, AFREF_VERIFY);
}
break;
case TDI_QUERY_CONNECTION_INFO:
//
// Connection info is queried on a connection,
// verify this.
//
Connection = (PCONNECTION)REQUEST_OPEN_CONTEXT(Request);
Status = NbiVerifyConnection (Connection);
if (!NT_SUCCESS (Status)) { return Status; }
if (Connection->State != CONNECTION_STATE_ACTIVE) {
Status = STATUS_INVALID_CONNECTION;
} else {
//
// Assume 50 ms of delay for every hop after the
// first. The delay is returned as a negative number.
//
if (Connection->HopCount > 1) { Connection->ConnectionInfo.Delay.HighPart = (ULONG)-1; Connection->ConnectionInfo.Delay.LowPart = -((Connection->HopCount-1) * 50 * MILLISECONDS); } else { Connection->ConnectionInfo.Delay.HighPart = 0; Connection->ConnectionInfo.Delay.LowPart = 0; }
//
// We have tick count; to convert to bytes/second we do:
//
// packet 576 bytes 18.21 ticks
// ---------------- * --------- * -----------
// tick_count ticks packet seconds
//
// to get 10489/tick_count = bytes/second. We
// double this because routers tend to
// overestimate it.
//
// Since tick_count has such a low granularity,
// a tick count of 1 gives us a throughput of
// only 84 kbps, which is much too low. In
// that case we return twice the link speed
// which is in 100 bps units; that corresponds
// to about 1/6 of our bandwidth in bytes/sec.
//
if (Connection->TickCount <= Connection->HopCount) {
Connection->ConnectionInfo.Throughput.QuadPart = UInt32x32To64 (Connection->LineInfo.LinkSpeed, 2);
} else {
Connection->ConnectionInfo.Throughput.HighPart = 0; Connection->ConnectionInfo.Throughput.LowPart = 20978 / (Connection->TickCount - Connection->HopCount);
}
Connection->ConnectionInfo.Unreliable = FALSE;
Status = TdiCopyBufferToMdl ( &Connection->ConnectionInfo, 0, sizeof(TDI_CONNECTION_INFO), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied; }
NbiDereferenceConnection (Connection, CREF_VERIFY);
break;
case TDI_QUERY_PROVIDER_INFO:
NB_DEBUG2 (QUERY, ("Query provider info\n"));
Status = TdiCopyBufferToMdl ( &Device->Information, 0, sizeof (TDI_PROVIDER_INFO), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied; break;
case TDI_QUERY_BROADCAST_ADDRESS:
//
// for this provider, the broadcast address is a zero byte name,
// contained in a Transport address structure.
//
NB_DEBUG2 (QUERY, ("Query broadcast address\n"));
TempBuffer.BroadcastAddress.TAAddressCount = 1; TempBuffer.BroadcastAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; TempBuffer.BroadcastAddress.Address[0].AddressLength = 0;
Status = TdiCopyBufferToMdl ( (PVOID)&TempBuffer.BroadcastAddress, 0L, sizeof (TempBuffer.BroadcastAddress.TAAddressCount) + sizeof (TempBuffer.BroadcastAddress.Address[0].AddressType) + sizeof (TempBuffer.BroadcastAddress.Address[0].AddressLength), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied;
break;
case TDI_QUERY_ADAPTER_STATUS:
//
// Determine if this is a local or remote query.
//
RemoteAdapterStatus = FALSE;
if (Query->RequestConnectionInformation != NULL) {
RemoteAddress = NbiParseTdiAddress(Query->RequestConnectionInformation->RemoteAddress, Query->RequestConnectionInformation->RemoteAddressLength, FALSE);
if (RemoteAddress == NULL) { return STATUS_BAD_NETWORK_PATH; }
#if defined(_PNP_POWER)
if ( !NbiFindAdapterAddress( RemoteAddress->NetbiosName, LOCK_NOT_ACQUIRED ) ) {
RemoteAdapterStatus = TRUE; } #else
if (!RtlEqualMemory( RemoteAddress->NetbiosName, Device->ReservedNetbiosName, 16)) {
RemoteAdapterStatus = TRUE;
} #endif _PNP_POWER
}
if (RemoteAdapterStatus) {
//
// See if we have this name cached.
//
NB_GET_LOCK (&Device->Lock, &LockHandle);
Status = CacheFindName( Device, FindNameOther, RemoteAddress->NetbiosName, &CacheName);
if (Status == STATUS_PENDING) {
//
// A request for routes to this name has been
// sent out on the net, we queue up this status
// request and processing will be resumed when
// we get a response.
//
// The status field in the request will hold
// the cache entry for the remote. The information
// field will hold the remote netbios name while
// it is in the WaitingAdapterStatus queue, and
// will hold a timeout value while we it is in
// the ActiveAdapterStatus queue.
//
NB_DEBUG2 (QUERY, ("Queueing up adapter status %lx\n", Request));
NbiReferenceDevice (Device, DREF_STATUS_QUERY);
REQUEST_INFORMATION (Request) = (ULONG_PTR) RemoteAddress;
InsertTailList( &Device->WaitingAdapterStatus, REQUEST_LINKAGE (Request));
NB_FREE_LOCK (&Device->Lock, LockHandle);
} else if (Status == STATUS_SUCCESS) {
NB_DEBUG2 (QUERY, ("Found adapter status cached %lx\n", Request));
//
// We reference the cache name entry so it won't
// go away while we are using it.
//
REQUEST_STATUSPTR(Request) = (PVOID)CacheName; ++CacheName->ReferenceCount;
NbiReferenceDevice (Device, DREF_STATUS_QUERY);
REQUEST_INFORMATION (Request) = 0;
InsertTailList( &Device->ActiveAdapterStatus, REQUEST_LINKAGE (Request));
NB_FREE_LOCK (&Device->Lock, LockHandle);
NbiSendStatusQuery (Request);
Status = STATUS_PENDING;
} else {
if (Status != STATUS_INSUFFICIENT_RESOURCES) { Status = STATUS_IO_TIMEOUT; }
REQUEST_INFORMATION (Request) = 0;
NB_FREE_LOCK (&Device->Lock, LockHandle);
}
} else {
//
// Local adapter status.
//
NbiGetBufferChainLength (REQUEST_NDIS_BUFFER(Request), &TargetBufferLength);
Status = NbiStoreAdapterStatus( TargetBufferLength, 1, // NIC ID, was 0, changed to 1 for Bug #18026
// because for NicId = 0, Ipx returns virtual
// address. Netbios uses that to register the
// name (00...01) and fails.
&AdapterStatus, &AdapterStatusLength, &ValidStatusLength);
if (Status != STATUS_INSUFFICIENT_RESOURCES) {
//
// This should succeed since we know the length
// will fit.
//
(VOID)TdiCopyBufferToMdl( AdapterStatus, 0, ValidStatusLength, REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied;
NbiFreeMemory (AdapterStatus, AdapterStatusLength, MEMORY_STATUS, "Adapter Status"); }
}
break;
case TDI_QUERY_FIND_NAME:
//
// Check that there is a valid Netbios remote address.
//
if ((Query->RequestConnectionInformation == NULL) || ((RemoteAddress = NbiParseTdiAddress(Query->RequestConnectionInformation->RemoteAddress, Query->RequestConnectionInformation->RemoteAddressLength, FALSE)) == NULL)) {
return STATUS_BAD_NETWORK_PATH; }
//
// We assume the entire request buffer is in the first
// piece of the MDL chain.
// Make sure there is room for at least the header.
//
NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength, HighPagePriority); if ((!FindNameHeader) || (FindNameBufferLength < sizeof(FIND_NAME_HEADER))) { return STATUS_INSUFFICIENT_RESOURCES; }
//
// See if we have this name cached. We specify that this is
// a netbios name query, so this will only succeed if this is a
// unique name -- for a group name it will queue up a find
// name query and when we get the response we will fill in
// the request's buffer based on it.
//
NB_GET_LOCK (&Device->Lock, &LockHandle);
Status = CacheFindName( Device, FindNameNetbiosFindName, RemoteAddress->NetbiosName, &CacheName);
if (Status == STATUS_PENDING) {
//
// A request for routes to this name has been
// sent out on the net, we queue up this find
// name request and processing will be resumed when
// we get a response.
//
// The information field will hold the remote
// netbios name while it is in the WaitingNetbiosFindName
// queue. The status will hold the current status --
// initially failure, then success, then overflow
// if the buffer is too small.
//
NB_DEBUG2 (QUERY, ("Queueing up find name %lx\n", Request));
NbiReferenceDevice (Device, DREF_NB_FIND_NAME);
FindNameHeader->node_count = 0; FindNameHeader->reserved = 0; FindNameHeader->unique_group = 0;
REQUEST_INFORMATION (Request) = (ULONG_PTR)RemoteAddress;
//
// Assume it fails, we update the status to
// SUCCESS or BUFFER_OVERFLOW if needed.
//
REQUEST_STATUS (Request) = STATUS_IO_TIMEOUT;
InsertTailList( &Device->WaitingNetbiosFindName, REQUEST_LINKAGE (Request));
NB_FREE_LOCK (&Device->Lock, LockHandle);
} else if (Status == STATUS_SUCCESS) {
NB_DEBUG2 (QUERY, ("Found find name cached %lx\n", Request));
//
// We don't need to reference the cache entry since
// we only use it here with the lock still held.
//
//
// Query the local address, which we will return as
// the destination address of this query. Since we
// use TempBuffer.IpxAddress for this query, we have
// to immediately copy it to its correct place in
// TempBuffer.FindNameInfo.Buffer.
//
#if defined(_PNP_POWER)
if( (*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, &CacheName->Networks[0].LocalTarget.NicHandle, &TempBuffer.IpxAddress, sizeof(TDI_ADDRESS_IPX), NULL) != STATUS_SUCCESS ) { NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_IPX_ADDRESS, CacheName->Networks[0].LocalTarget.NicHandle.NicId ));
goto QueryFindNameFailed; } #else
(VOID)(*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, CacheName->Networks[0].LocalTarget.NicId, &TempBuffer.IpxAddress, sizeof(TDI_ADDRESS_IPX), NULL); #endif _PNP_POWER
RtlMoveMemory (TempBuffer.FindNameInfo.Buffer.destination_addr, TempBuffer.IpxAddress.NodeAddress, 6); TempBuffer.FindNameInfo.Buffer.access_control = 0x10; // standard token-ring values
TempBuffer.FindNameInfo.Buffer.frame_control = 0x40; RtlCopyMemory (TempBuffer.FindNameInfo.Buffer.source_addr, CacheName->FirstResponse.NodeAddress, 6);
//
// Query source routing information about this remote, if any.
//
SourceRoutingInfo.Identifier = IDENTIFIER_NB; RtlCopyMemory (SourceRoutingInfo.RemoteAddress, CacheName->FirstResponse.NodeAddress, 6);
QueryStatus = (*Device->Bind.QueryHandler)( IPX_QUERY_SOURCE_ROUTING, #if defined(_PNP_POWER)
&CacheName->Networks[0].LocalTarget.NicHandle, #else
CacheName->Networks[0].LocalTarget.NicId, #endif _PNP_POWER
&SourceRoutingInfo, sizeof(IPX_SOURCE_ROUTING_INFO), NULL);
RtlZeroMemory(TempBuffer.FindNameInfo.Buffer.routing_info, 18); if (QueryStatus != STATUS_SUCCESS) { SourceRoutingInfo.SourceRoutingLength = 0; } else if (SourceRoutingInfo.SourceRoutingLength > 0) { RtlMoveMemory( TempBuffer.FindNameInfo.Buffer.routing_info, SourceRoutingInfo.SourceRouting, SourceRoutingInfo.SourceRoutingLength); }
TempBuffer.FindNameInfo.Buffer.length = (UCHAR)(14 + SourceRoutingInfo.SourceRoutingLength);
TempBuffer.FindNameInfo.Header.node_count = 1; TempBuffer.FindNameInfo.Header.reserved = 0; TempBuffer.FindNameInfo.Header.unique_group = 0; // unique
NB_FREE_LOCK (&Device->Lock, LockHandle);
//
// 33 is sizeof(FIND_NAME_BUFFER) without the padding.
//
Status = TdiCopyBufferToMdl ( (PVOID)&TempBuffer.FindNameInfo, 0, sizeof(FIND_NAME_HEADER) + 33, REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied; } else {
#if defined(_PNP_POWER)
QueryFindNameFailed: #endif _PNP_POWER
if (Status != STATUS_INSUFFICIENT_RESOURCES) { Status = STATUS_IO_TIMEOUT; }
REQUEST_INFORMATION (Request) = 0;
NB_FREE_LOCK (&Device->Lock, LockHandle);
}
break;
case TDI_QUERY_PROVIDER_STATISTICS:
//
// Keep track of more of these.
//
NB_DEBUG2 (QUERY, ("Query provider statistics\n"));
Status = TdiCopyBufferToMdl ( &Device->Statistics, 0, FIELD_OFFSET (TDI_PROVIDER_STATISTICS, ResourceStats[0]), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied; break;
case TDI_QUERY_DATAGRAM_INFO:
NB_DEBUG2 (QUERY, ("Query datagram info\n"));
TempBuffer.DatagramInfo.MaximumDatagramBytes = 0; TempBuffer.DatagramInfo.MaximumDatagramCount = 0;
Status = TdiCopyBufferToMdl ( &TempBuffer.DatagramInfo, 0, sizeof(TempBuffer.DatagramInfo), REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied; break;
case TDI_QUERY_DATA_LINK_ADDRESS: case TDI_QUERY_NETWORK_ADDRESS:{ #if defined(_PNP_POWER)
Status = (*Device->Bind.QueryHandler)( // Check return code
(Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS ? IPX_QUERY_DATA_LINK_ADDRESS : IPX_QUERY_NETWORK_ADDRESS ), NULL, Request, 0, NULL); #else
ULONG TransportAddressAllocSize;
if (Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) { ElementSize = (2 * sizeof(USHORT)) + 6; } else { ElementSize = (2 * sizeof(USHORT)) + sizeof(TDI_ADDRESS_IPX); }
// TransportAddress = CTEAllocMem(sizeof(int) + (ElementSize * Device->MaximumNicId));
TransportAddressAllocSize = sizeof(int) + ( ElementSize * Device->MaximumNicId); TransportAddress = NbiAllocateMemory( TransportAddressAllocSize, MEMORY_QUERY, "Temp Query Allocation");
if (TransportAddress == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
} else {
TransportAddress->TAAddressCount = 0; TransportAddressSize = sizeof(int); CurAddress = (TA_ADDRESS UNALIGNED *)TransportAddress->Address;
for (i = 1; i <= Device->MaximumNicId; i++) {
Status = (*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, (USHORT)i, &TempBuffer.IpxAddress, sizeof(TDI_ADDRESS_IPX), NULL);
if (Status != STATUS_SUCCESS) { continue; }
if (Query->QueryType == TDI_QUERY_DATA_LINK_ADDRESS) { CurAddress->AddressLength = 6; CurAddress->AddressType = TDI_ADDRESS_TYPE_UNSPEC; RtlCopyMemory (CurAddress->Address, TempBuffer.IpxAddress.NodeAddress, 6); } else { CurAddress->AddressLength = sizeof(TDI_ADDRESS_IPX); CurAddress->AddressType = TDI_ADDRESS_TYPE_IPX; RtlCopyMemory (CurAddress->Address, &TempBuffer.IpxAddress, sizeof(TDI_ADDRESS_IPX)); } ++TransportAddress->TAAddressCount; TransportAddressSize += ElementSize; CurAddress = (TA_ADDRESS UNALIGNED *)(((PUCHAR)CurAddress) + ElementSize);
}
Status = TdiCopyBufferToMdl ( TransportAddress, 0, TransportAddressSize, REQUEST_NDIS_BUFFER(Request), 0, &ActualBytesCopied);
REQUEST_INFORMATION(Request) = ActualBytesCopied;
// CTEFreeMem (TransportAddress);
NbiFreeMemory( TransportAddress, TransportAddressAllocSize, MEMORY_QUERY, "Temp Query Allocation");
} #endif _PNP_POWER
break; } default:
NB_DEBUG (QUERY, ("Invalid query type %d\n", Query->QueryType)); Status = STATUS_INVALID_DEVICE_REQUEST; break; }
return Status;
} /* NbiTdiQueryInformation */
NTSTATUS NbiStoreAdapterStatus( IN ULONG MaximumLength, IN USHORT NicId, OUT PVOID * StatusBuffer, OUT ULONG * StatusBufferLength, OUT ULONG * ValidBufferLength )
/*++
Routine Description:
This routine allocates an ADAPTER_STATUS buffer and fills it in. The buffer will be allocated at most MaximumLength size. The caller is responsible for freeing the buffer.
Arguments:
MaximumLength - The maximum length to allocate.
NicId - The NIC ID the query was received on, or 0 for a local query.
StatusBuffer - Returns the allocated buffer.
StatusBufferLength - Returns the length of the buffer.
ValidBufferLength - Returns the length of the buffer which contains valid adapter status data.
Return Value:
STATUS_SUCCESS - The buffer was written successfully. STATUS_BUFFER_OVERFLOW - The buffer was written but not all data could fit in MaximumLength bytes. STATUS_INSUFFICIENT_RESOURCES - The buffer could not be allocated.
--*/
{
PADAPTER_STATUS AdapterStatus; PNAME_BUFFER NameBuffer; ADAPTER_STATUS TempAdapterStatus; #if !defined(_PNP_POWER)
TDI_ADDRESS_IPX IpxAddress; #endif !_PNP_POWER
PDEVICE Device = NbiDevice; PADDRESS Address; UCHAR NameCount; ULONG LengthNeeded; ULONG BytesWritten; NTSTATUS Status; PLIST_ENTRY p; CTELockHandle LockHandle;
//
// First fill in the basic adapter status structure, to make
// it easier to copy over if the target buffer is really short.
//
RtlZeroMemory ((PVOID)&TempAdapterStatus, sizeof(ADAPTER_STATUS));
#if defined(_PNP_POWER)
RtlCopyMemory (TempAdapterStatus.adapter_address, Device->Bind.Node, 6); #else
(VOID)(*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, NicId, &IpxAddress, sizeof(TDI_ADDRESS_IPX), NULL);
RtlCopyMemory (TempAdapterStatus.adapter_address, IpxAddress.NodeAddress, 6); #endif _PNP_POWER
//
// Some of the fields mean different things for Novell Netbios,
// as described in the comments.
//
TempAdapterStatus.rev_major = 0; // Jumpers
TempAdapterStatus.reserved0 = 0; // SelfTest
TempAdapterStatus.adapter_type = 0; // MajorVersion
TempAdapterStatus.rev_minor = 0; // MinorVersion
TempAdapterStatus.duration = 0; // ReportingPeriod
TempAdapterStatus.frmr_recv = 0; // ReceiveCRCErrors
TempAdapterStatus.frmr_xmit = 0; // ReceiveAlignErrors
TempAdapterStatus.iframe_recv_err = 0; // XmitCollisions
TempAdapterStatus.xmit_aborts = 0; // XmitAbort
TempAdapterStatus.xmit_success = Device->Statistics.DataFramesSent; // SuccessfulXmits
TempAdapterStatus.recv_success = Device->Statistics.DataFramesReceived; // SuccessfulReceive
TempAdapterStatus.iframe_xmit_err = (WORD)Device->Statistics.DataFramesResent; // XmitRetries
TempAdapterStatus.recv_buff_unavail = (WORD)Device->Statistics.DataFramesRejected; // ExhaustedResource
// t1_timeouts, ti_timeouts, and reserved1 are unused.
TempAdapterStatus.free_ncbs = 0xffff; // FreeBlocks
TempAdapterStatus.max_cfg_ncbs = 0xffff; // ConfiguredNCB
TempAdapterStatus.max_ncbs = 0xffff; // MaxNCB
// xmit_bug_unavail and max_dgram_size are unused.
TempAdapterStatus.pending_sess = (WORD)Device->Statistics.OpenConnections; // CurrentSessions
TempAdapterStatus.max_cfg_sess = 0xffff; // MaxSessionConfigured
TempAdapterStatus.max_sess = 0xffff; // MaxSessionPossible
TempAdapterStatus.max_sess_pkt_size = (USHORT) (Device->Bind.LineInfo.MaximumSendSize - sizeof(NB_CONNECTION)); // MaxSessionPacketSize
TempAdapterStatus.name_count = 0;
//
// Do a quick estimate of how many names we need room for.
// This includes stopping addresses and the broadcast
// address, for the moment.
//
NB_GET_LOCK (&Device->Lock, &LockHandle);
LengthNeeded = sizeof(ADAPTER_STATUS) + (Device->AddressCount * sizeof(NAME_BUFFER));
if (LengthNeeded > MaximumLength) { LengthNeeded = MaximumLength; }
AdapterStatus = NbiAllocateMemory(LengthNeeded, MEMORY_STATUS, "Adapter Status"); if (AdapterStatus == NULL) { NB_FREE_LOCK (&Device->Lock, LockHandle); return STATUS_INSUFFICIENT_RESOURCES; }
*StatusBuffer = AdapterStatus; *StatusBufferLength = LengthNeeded;
if (LengthNeeded < sizeof(ADAPTER_STATUS)) { RtlCopyMemory (AdapterStatus, &TempAdapterStatus, LengthNeeded); *ValidBufferLength = LengthNeeded; NB_FREE_LOCK (&Device->Lock, LockHandle); return STATUS_BUFFER_OVERFLOW; }
RtlCopyMemory (AdapterStatus, &TempAdapterStatus, sizeof(ADAPTER_STATUS));
BytesWritten = sizeof(ADAPTER_STATUS); NameBuffer = (PNAME_BUFFER)(AdapterStatus+1); NameCount = 0;
//
// Scan through the device's address database, filling in
// the NAME_BUFFERs.
//
Status = STATUS_SUCCESS;
for (p = Device->AddressDatabase.Flink; p != &Device->AddressDatabase; p = p->Flink) {
Address = CONTAINING_RECORD (p, ADDRESS, Linkage);
//
// Ignore addresses that are shutting down.
//
#if defined(_PNP_POWER)
if ((Address->State != ADDRESS_STATE_OPEN) || (Address->Flags & ADDRESS_FLAGS_CONFLICT)) { continue; } #else
if ((Address->State != ADDRESS_STATE_OPEN) != 0) { continue; } #endif _PNP_POWER
//
// Ignore the broadcast address.
//
if (Address->NetbiosAddress.Broadcast) { continue; }
//
// Ignore our reserved address.
//
#if defined(_PNP_POWER)
if ( NbiFindAdapterAddress( Address->NetbiosAddress.NetbiosName, LOCK_ACQUIRED )) { continue; } #else
if (RtlEqualMemory( Address->NetbiosAddress.NetbiosName, Device->ReservedNetbiosName, 16)) { continue; }
#endif _PNP_POWER
//
// Make sure we still have room.
//
if (BytesWritten + sizeof(NAME_BUFFER) > LengthNeeded) { Status = STATUS_BUFFER_OVERFLOW; break; }
RtlCopyMemory( NameBuffer->name, Address->NetbiosAddress.NetbiosName, 16);
++NameCount; NameBuffer->name_num = NameCount;
NameBuffer->name_flags = REGISTERED; if (Address->NameTypeFlag == NB_NAME_GROUP) { NameBuffer->name_flags |= GROUP_NAME; }
BytesWritten += sizeof(NAME_BUFFER); ++NameBuffer;
}
AdapterStatus->name_count = (WORD)NameCount; *ValidBufferLength = BytesWritten; NB_FREE_LOCK (&Device->Lock, LockHandle); return Status;
} /* NbiStoreAdapterStatus */
VOID NbiUpdateNetbiosFindName( IN PREQUEST Request, #if defined(_PNP_POWER)
IN PNIC_HANDLE NicHandle, #else
IN USHORT NicId, #endif _PNP_POWER
IN TDI_ADDRESS_IPX UNALIGNED * RemoteIpxAddress, IN BOOLEAN Unique )
/*++
Routine Description:
This routine updates the find name request with the new information received. It updates the status in the request if needed.
Arguments:
Request - The netbios find name request.
NicId - The NIC ID the response was received on.
RemoteIpxAddress - The IPX address of the remote.
Unique - TRUE if the name is unique.
Return Value:
None.
--*/
{ FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL; FIND_NAME_BUFFER UNALIGNED * FindNameBuffer; UINT FindNameBufferLength; TDI_ADDRESS_IPX LocalIpxAddress; IPX_SOURCE_ROUTING_INFO SourceRoutingInfo; NTSTATUS QueryStatus; UINT i;
NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength, HighPagePriority); if (!FindNameHeader) { return; }
//
// Scan through the names saved so far and see if this one
// is there.
//
FindNameBuffer = (FIND_NAME_BUFFER UNALIGNED *)(FindNameHeader+1); for (i = 0; i < FindNameHeader->node_count; i++) {
if (RtlEqualMemory( FindNameBuffer->source_addr, RemoteIpxAddress->NodeAddress, 6)) {
//
// This remote already responded, ignore it.
//
return;
}
FindNameBuffer = (FIND_NAME_BUFFER UNALIGNED *) (((PUCHAR)FindNameBuffer) + 33); }
//
// Make sure there is room for this new node. 33 is
// sizeof(FIND_NAME_BUFFER) without padding.
//
if (FindNameBufferLength < sizeof(FIND_NAME_HEADER) + ((FindNameHeader->node_count+1) * 33)) { REQUEST_STATUS(Request) = STATUS_BUFFER_OVERFLOW; return; }
//
// Query the local address, which we will return as
// the destination address of this query.
//
#if defined(_PNP_POWER)
if( (*NbiDevice->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, NicHandle, &LocalIpxAddress, sizeof(TDI_ADDRESS_IPX), NULL) != STATUS_SUCCESS ) { //
// Ignore this response if the query fails. maybe the NicHandle
// is bad or it just got removed.
//
NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_IPX_ADDRESS, NicHandle->NicId )); return; } #else
(VOID)(*NbiDevice->Bind.QueryHandler)( // Check return code
IPX_QUERY_IPX_ADDRESS, NicId, &LocalIpxAddress, sizeof(TDI_ADDRESS_IPX), NULL); #endif _PNP_POWER
FindNameBuffer->access_control = 0x10; // standard token-ring values
FindNameBuffer->frame_control = 0x40; RtlMoveMemory (FindNameBuffer->destination_addr, LocalIpxAddress.NodeAddress, 6); RtlCopyMemory (FindNameBuffer->source_addr, RemoteIpxAddress->NodeAddress, 6);
//
// Query source routing information about this remote, if any.
//
SourceRoutingInfo.Identifier = IDENTIFIER_NB; RtlCopyMemory (SourceRoutingInfo.RemoteAddress, RemoteIpxAddress->NodeAddress, 6);
QueryStatus = (*NbiDevice->Bind.QueryHandler)( IPX_QUERY_SOURCE_ROUTING, #if defined(_PNP_POWER)
NicHandle, #else
NicId, #endif _PNP_POWER
&SourceRoutingInfo, sizeof(IPX_SOURCE_ROUTING_INFO), NULL);
RtlZeroMemory(FindNameBuffer->routing_info, 18); if (QueryStatus != STATUS_SUCCESS) { SourceRoutingInfo.SourceRoutingLength = 0; } else if (SourceRoutingInfo.SourceRoutingLength > 0) { RtlMoveMemory( FindNameBuffer->routing_info, SourceRoutingInfo.SourceRouting, SourceRoutingInfo.SourceRoutingLength); }
FindNameBuffer->length = (UCHAR)(14 + SourceRoutingInfo.SourceRoutingLength);
++FindNameHeader->node_count; if (!Unique) { FindNameHeader->unique_group = 1; // group
}
REQUEST_STATUS(Request) = STATUS_SUCCESS;
} /* NbiUpdateNetbiosFindName */
VOID NbiSetNetbiosFindNameInformation( IN PREQUEST Request )
/*++
Routine Description:
This routine sets the REQUEST_INFORMATION field to the right value based on the number of responses recorded in the netbios find name request's buffer.
Arguments:
Request - The netbios find name request.
Return Value:
None.
--*/
{ FIND_NAME_HEADER UNALIGNED * FindNameHeader = NULL; UINT FindNameBufferLength;
NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request), (PVOID *)&FindNameHeader, &FindNameBufferLength, HighPagePriority); if (FindNameHeader) { //
// 33 is sizeof(FIND_NAME_BUFFER) without the padding.
//
REQUEST_INFORMATION(Request) = sizeof(FIND_NAME_HEADER) + (FindNameHeader->node_count * 33); }
} /* NbiSetNetbiosFindNameInformation */
NTSTATUS NbiTdiSetInformation( IN PDEVICE Device, IN PREQUEST Request )
/*++
Routine Description:
This routine performs the TdiSetInformation request for the transport provider.
Arguments:
Device - the device.
Request - the request for the operation.
Return Value:
NTSTATUS - status of operation.
--*/
{ UNREFERENCED_PARAMETER (Device); UNREFERENCED_PARAMETER (Request);
return STATUS_NOT_IMPLEMENTED;
} /* NbiTdiSetInformation */
VOID NbiProcessStatusQuery( IN PIPX_LOCAL_TARGET RemoteAddress, IN ULONG MacOptions, IN PUCHAR PacketBuffer, IN UINT PacketSize )
/*++
Routine Description:
This routine handles NB_CMD_STATUS_QUERY frames.
Arguments:
RemoteAddress - The local target this packet was received from.
MacOptions - The MAC options for the underlying NDIS binding.
LookaheadBuffer - The packet data, starting at the IPX header.
PacketSize - The total length of the packet, starting at the IPX header.
Return Value:
None.
--*/
{ PSINGLE_LIST_ENTRY s; PNB_SEND_RESERVED Reserved; PNDIS_PACKET Packet; NB_CONNECTIONLESS UNALIGNED * Header; NDIS_STATUS NdisStatus; IPX_LINE_INFO LineInfo; ULONG ResponseSize; NTSTATUS Status; PNDIS_BUFFER AdapterStatusBuffer; PADAPTER_STATUS AdapterStatus; ULONG AdapterStatusLength; ULONG ValidStatusLength; PDEVICE Device = NbiDevice; NB_CONNECTIONLESS UNALIGNED * Connectionless = (NB_CONNECTIONLESS UNALIGNED *)PacketBuffer;
//
// The old stack does not include the 14 bytes of padding in
// the 802.3 or IPX length of the packet.
//
if (PacketSize < (sizeof(IPX_HEADER) + 2)) { return; }
//
// Get the maximum size we can send.
//
#if defined(_PNP_POWER)
if( (*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_LINE_INFO, &RemoteAddress->NicHandle, &LineInfo, sizeof(IPX_LINE_INFO), NULL) != STATUS_SUCCESS ) { //
// Bad NicHandle or it just got removed.
//
NB_DEBUG( QUERY, ("Ipx Query %d failed for Nic %x\n",IPX_QUERY_LINE_INFO, RemoteAddress->NicHandle.NicId ));
return; }
//
// Allocate a packet from the pool.
//
s = NbiPopSendPacket(Device, FALSE); if (s == NULL) { return; } #else
//
// Allocate a packet from the pool.
//
s = NbiPopSendPacket(Device, FALSE); if (s == NULL) { return; }
//
// Get the maximum size we can send.
//
(VOID)(*Device->Bind.QueryHandler)( // Check return code
IPX_QUERY_LINE_INFO, RemoteAddress->NicId, &LineInfo, sizeof(IPX_LINE_INFO), NULL); #endif _PNP_POWER
ResponseSize = LineInfo.MaximumSendSize - sizeof(IPX_HEADER) - sizeof(NB_STATUS_RESPONSE);
//
// Get the local adapter status (this allocates a buffer).
//
Status = NbiStoreAdapterStatus( ResponseSize, #if defined(_PNP_POWER)
RemoteAddress->NicHandle.NicId, #else
RemoteAddress->NicId, #endif _PNP_POWER
&AdapterStatus, &AdapterStatusLength, &ValidStatusLength);
if (Status == STATUS_INSUFFICIENT_RESOURCES) { ExInterlockedPushEntrySList( &Device->SendPacketList, s, &NbiGlobalPoolInterlock); return; }
//
// Allocate an NDIS buffer to map the extra buffer.
//
NdisAllocateBuffer( &NdisStatus, &AdapterStatusBuffer, Device->NdisBufferPoolHandle, AdapterStatus, ValidStatusLength);
if (NdisStatus != NDIS_STATUS_SUCCESS) { NbiFreeMemory (AdapterStatus, AdapterStatusLength, MEMORY_STATUS, "Adapter Status"); ExInterlockedPushEntrySList( &Device->SendPacketList, s, &NbiGlobalPoolInterlock); return; }
NB_DEBUG2 (QUERY, ("Reply to AdapterStatus from %lx %2.2x-%2.2x-%2.2x-%2.2x-%2.2x-%2.2x\n", *(UNALIGNED ULONG *)Connectionless->IpxHeader.SourceNetwork, Connectionless->IpxHeader.SourceNode[0], Connectionless->IpxHeader.SourceNode[1], Connectionless->IpxHeader.SourceNode[2], Connectionless->IpxHeader.SourceNode[3], Connectionless->IpxHeader.SourceNode[4], Connectionless->IpxHeader.SourceNode[5]));
Reserved = CONTAINING_RECORD (s, NB_SEND_RESERVED, PoolLinkage); Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
CTEAssert (Reserved->SendInProgress == FALSE); Reserved->SendInProgress = TRUE; Reserved->Type = SEND_TYPE_STATUS_RESPONSE; Reserved->u.SR_AS.ActualBufferLength = AdapterStatusLength;
//
// Fill in the IPX header -- the default header has the broadcast
// address on net 0 as the destination IPX address.
//
Header = (NB_CONNECTIONLESS UNALIGNED *) (&Reserved->Header[Device->Bind.IncludedHeaderOffset]); RtlCopyMemory((PVOID)&Header->IpxHeader, &Device->ConnectionlessHeader, sizeof(IPX_HEADER)); RtlCopyMemory(&Header->IpxHeader.DestinationNetwork, Connectionless->IpxHeader.SourceNetwork, 12);
Header->IpxHeader.PacketLength[0] = (UCHAR)((sizeof(IPX_HEADER)+sizeof(NB_STATUS_RESPONSE)+ValidStatusLength) / 256); Header->IpxHeader.PacketLength[1] = (UCHAR)((sizeof(IPX_HEADER)+sizeof(NB_STATUS_RESPONSE)+ValidStatusLength) % 256);
Header->IpxHeader.PacketType = 0x04;
//
// Now fill in the Netbios header.
//
Header->StatusResponse.ConnectionControlFlag = 0x00; Header->StatusResponse.DataStreamType = NB_CMD_STATUS_RESPONSE;
NbiReferenceDevice (Device, DREF_STATUS_RESPONSE);
NdisChainBufferAtBack (Packet, AdapterStatusBuffer);
//
// Now send the frame, IPX will adjust the length of the
// first buffer correctly.
//
NdisAdjustBufferLength(NB_GET_NBHDR_BUFF(Packet), sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE)); if ((NdisStatus = (*Device->Bind.SendHandler)( RemoteAddress, Packet, sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + ValidStatusLength, sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE))) != STATUS_PENDING) {
NbiSendComplete( Packet, NdisStatus);
}
} /* NbiProcessStatusQuery */
VOID NbiSendStatusQuery( IN PREQUEST Request )
/*++
Routine Description:
This routine sends NB_CMD_STATUS_QUERY frames.
Arguments:
Request - Holds the request describing the remote adapter status query. REQUEST_STATUS(Request) points to the netbios cache entry for the remote name.
Return Value:
None.
--*/
{ PSINGLE_LIST_ENTRY s; PNB_SEND_RESERVED Reserved; PNDIS_PACKET Packet; NB_CONNECTIONLESS UNALIGNED * Header; NDIS_STATUS NdisStatus; PNETBIOS_CACHE CacheName; PIPX_LOCAL_TARGET LocalTarget; PDEVICE Device = NbiDevice;
//
// Allocate a packet from the pool.
//
s = NbiPopSendPacket(Device, FALSE); if (s == NULL) { return; }
Reserved = CONTAINING_RECORD (s, NB_SEND_RESERVED, PoolLinkage); Packet = CONTAINING_RECORD (Reserved, NDIS_PACKET, ProtocolReserved[0]);
CTEAssert (Reserved->SendInProgress == FALSE); Reserved->SendInProgress = TRUE; Reserved->Type = SEND_TYPE_STATUS_QUERY;
CacheName = (PNETBIOS_CACHE)REQUEST_STATUSPTR(Request);
//
// Fill in the IPX header -- the default header has the broadcast
// address on net 0 as the destination IPX address.
//
Header = (NB_CONNECTIONLESS UNALIGNED *) (&Reserved->Header[Device->Bind.IncludedHeaderOffset]); RtlCopyMemory((PVOID)&Header->IpxHeader, &Device->ConnectionlessHeader, sizeof(IPX_HEADER)); RtlCopyMemory (Header->IpxHeader.DestinationNetwork, &CacheName->FirstResponse, 12);
LocalTarget = &CacheName->Networks[0].LocalTarget;
Header->IpxHeader.PacketLength[0] = (sizeof(IPX_HEADER)+sizeof(NB_STATUS_QUERY)) / 256; Header->IpxHeader.PacketLength[1] = (sizeof(IPX_HEADER)+sizeof(NB_STATUS_QUERY)) % 256;
Header->IpxHeader.PacketType = 0x04;
//
// Now fill in the Netbios header.
//
Header->StatusResponse.ConnectionControlFlag = 0x00; Header->StatusResponse.DataStreamType = NB_CMD_STATUS_QUERY;
NbiReferenceDevice (Device, DREF_STATUS_FRAME);
//
// Now send the frame, IPX will adjust the length of the
// first buffer correctly.
//
NdisAdjustBufferLength(NB_GET_NBHDR_BUFF(Packet), sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY)); if ((NdisStatus = (*Device->Bind.SendHandler)( LocalTarget, Packet, sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY), sizeof(IPX_HEADER) + sizeof(NB_STATUS_QUERY))) != STATUS_PENDING) {
NbiSendComplete( Packet, NdisStatus);
}
} /* NbiProcessStatusQuery */
VOID NbiProcessStatusResponse( IN NDIS_HANDLE MacBindingHandle, IN NDIS_HANDLE MacReceiveContext, IN PIPX_LOCAL_TARGET RemoteAddress, IN ULONG MacOptions, IN PUCHAR LookaheadBuffer, IN UINT LookaheadBufferSize, IN UINT LookaheadBufferOffset, IN UINT PacketSize )
/*++
Routine Description:
This routine handles NB_CMD_STATUS_RESPONSE frames.
Arguments:
MacBindingHandle - A handle to use when calling NdisTransferData.
MacReceiveContext - A context to use when calling NdisTransferData.
RemoteAddress - The local target this packet was received from.
MacOptions - The MAC options for the underlying NDIS binding.
LookaheadBuffer - The lookahead buffer, starting at the IPX header.
LookaheadBufferSize - The length of the lookahead data.
LookaheadBufferOffset - The offset to add when calling NdisTransferData.
PacketSize - The total length of the packet, starting at the IPX header.
Return Value:
None.
--*/
{ PDEVICE Device = NbiDevice; CTELockHandle LockHandle; PREQUEST AdapterStatusRequest; PNETBIOS_CACHE CacheName; PLIST_ENTRY p; PSINGLE_LIST_ENTRY s; PNDIS_BUFFER TargetBuffer; ULONG TargetBufferLength, BytesToTransfer; ULONG BytesTransferred; NDIS_STATUS NdisStatus; PNB_RECEIVE_RESERVED ReceiveReserved; PNDIS_PACKET Packet; BOOLEAN Found; PNAME_BUFFER NameBuffer; UINT i,NameCount = 0; NB_CONNECTIONLESS UNALIGNED * Connectionless = (NB_CONNECTIONLESS UNALIGNED *)LookaheadBuffer;
if (PacketSize < (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE))) { return; }
//
// Find out how many names are there.
//
NameBuffer = (PNAME_BUFFER)(LookaheadBuffer + sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS)); if ( LookaheadBufferSize > sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS) ) { NameCount = (LookaheadBufferSize - (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE) + sizeof(ADAPTER_STATUS)) ) / sizeof(NAME_BUFFER); } //
// Find a request queued to this remote. If there are
// multiple requests outstanding for the same name we
// should get multiple responses, so we only need to
// find one.
//
NB_GET_LOCK (&Device->Lock, &LockHandle);
Found = FALSE; p = Device->ActiveAdapterStatus.Flink;
while (p != &Device->ActiveAdapterStatus) {
AdapterStatusRequest = LIST_ENTRY_TO_REQUEST(p); p = p->Flink;
CacheName = (PNETBIOS_CACHE)REQUEST_STATUSPTR(AdapterStatusRequest); if ( CacheName->Unique ) { if (RtlEqualMemory( &CacheName->FirstResponse, Connectionless->IpxHeader.SourceNetwork, 12)) { Found = TRUE; break; } } else if ( RtlEqualMemory( CacheName->NetbiosName,NetbiosBroadcastName,16)){ //
// It's a broadcast name. Any response is fine.
//
Found = TRUE; break; } else { //
// It's group name. Make sure that this remote
// has this group name registered with him.
//
for (i =0;i<NameCount;i++) { if ( (RtlEqualMemory( CacheName->NetbiosName, NameBuffer[i].name, 16)) &&
(NameBuffer[i].name_flags & GROUP_NAME) ) {
Found = TRUE; break; } } }
}
if (!Found) { NB_FREE_LOCK (&Device->Lock, LockHandle); return; }
NB_DEBUG2 (QUERY, ("Got response to AdapterStatus %lx\n", AdapterStatusRequest));
RemoveEntryList (REQUEST_LINKAGE(AdapterStatusRequest));
if (--CacheName->ReferenceCount == 0) {
NB_DEBUG2 (CACHE, ("Free delete name cache entry %lx\n", CacheName)); NbiFreeMemory( CacheName, sizeof(NETBIOS_CACHE) + ((CacheName->NetworksAllocated-1) * sizeof(NETBIOS_NETWORK)), MEMORY_CACHE, "Name deleted");
}
NB_FREE_LOCK (&Device->Lock, LockHandle);
s = NbiPopReceivePacket (Device); if (s == NULL) {
REQUEST_INFORMATION (AdapterStatusRequest) = 0; REQUEST_STATUS (AdapterStatusRequest) = STATUS_INSUFFICIENT_RESOURCES;
NbiCompleteRequest (AdapterStatusRequest); NbiFreeRequest (Device, AdapterStatusRequest);
NbiDereferenceDevice (Device, DREF_STATUS_QUERY);
return; }
ReceiveReserved = CONTAINING_RECORD (s, NB_RECEIVE_RESERVED, PoolLinkage); Packet = CONTAINING_RECORD (ReceiveReserved, NDIS_PACKET, ProtocolReserved[0]);
//
// Initialize the receive packet.
//
ReceiveReserved->Type = RECEIVE_TYPE_ADAPTER_STATUS; ReceiveReserved->u.RR_AS.Request = AdapterStatusRequest; REQUEST_STATUS(AdapterStatusRequest) = STATUS_SUCCESS; CTEAssert (!ReceiveReserved->TransferInProgress); ReceiveReserved->TransferInProgress = TRUE;
//
// Now that we have a packet and a buffer, set up the transfer.
// We will complete the request when the transfer completes.
//
TargetBuffer = REQUEST_NDIS_BUFFER (AdapterStatusRequest);
NdisChainBufferAtFront (Packet, TargetBuffer);
NbiGetBufferChainLength (TargetBuffer, &TargetBufferLength); BytesToTransfer = PacketSize - (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE)); if (TargetBufferLength < BytesToTransfer) { BytesToTransfer = TargetBufferLength; REQUEST_STATUS(AdapterStatusRequest) = STATUS_BUFFER_OVERFLOW; }
(*Device->Bind.TransferDataHandler) ( &NdisStatus, MacBindingHandle, MacReceiveContext, LookaheadBufferOffset + (sizeof(IPX_HEADER) + sizeof(NB_STATUS_RESPONSE)), BytesToTransfer, Packet, &BytesTransferred);
if (NdisStatus != NDIS_STATUS_PENDING) { #if DBG
if (NdisStatus == STATUS_SUCCESS) { CTEAssert (BytesTransferred == BytesToTransfer); } #endif
NbiTransferDataComplete( Packet, NdisStatus, BytesTransferred);
}
} /* NbiProcessStatusResponse */
|