Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

225 lines
5.6 KiB

/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
action.c
Abstract:
This module contains code which implements the TDI action
dispatch routines.
Environment:
Kernel mode
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
typedef struct _NB_ACTION_GET_COUNTS {
USHORT MaximumNicId; // returns maximum NIC ID
USHORT NicIdCounts[32]; // session counts for first 32 NIC IDs
} NB_ACTION_GET_COUNTS, *PNB_ACTION_GET_COUNTS;
NTSTATUS
NbiTdiAction(
IN PDEVICE Device,
IN PREQUEST Request
)
/*++
Routine Description:
This routine handles action requests.
Arguments:
Device - The netbios device.
Request - The request describing the action.
Return Value:
NTSTATUS - status of operation.
--*/
{
NTSTATUS Status;
PADDRESS_FILE AddressFile;
PCONNECTION Connection;
UINT BufferLength;
UINT DataLength;
PNDIS_BUFFER NdisBuffer;
CTELockHandle LockHandle;
union {
PNB_ACTION_GET_COUNTS GetCounts;
} u;
PNWLINK_ACTION NwlinkAction = NULL;
UINT i;
static UCHAR BogusId[4] = { 0x01, 0x00, 0x00, 0x00 }; // old nwrdr uses this
//
// To maintain some compatibility with the NWLINK streams-
// based transport, we use the streams header format for
// our actions. The old transport expected the action header
// to be in InputBuffer and the output to go in OutputBuffer.
// We follow the TDI spec, which states that OutputBuffer
// is used for both input and output. Since IOCTL_TDI_ACTION
// is method out direct, this means that the output buffer
// is mapped by the MDL chain; for action the chain will
// only have one piece so we use it for input and output.
//
NdisBuffer = REQUEST_NDIS_BUFFER(Request);
if (NdisBuffer == NULL) {
return STATUS_INVALID_PARAMETER;
}
NdisQueryBufferSafe (REQUEST_NDIS_BUFFER(Request),(PVOID *)&NwlinkAction,&BufferLength,HighPagePriority);
if (!NwlinkAction)
{
return (STATUS_INSUFFICIENT_RESOURCES);
}
//
// Make sure we have enough room for just the header not
// including the data.
// (This will also include verification of buffer space for the TransportId) Bug# 171837
//
if (BufferLength < (UINT)(FIELD_OFFSET(NWLINK_ACTION, Data[0]))) {
NB_DEBUG (QUERY, ("Nwlink action failed, buffer too small\n"));
return STATUS_BUFFER_TOO_SMALL;
}
DataLength = BufferLength - FIELD_OFFSET(NWLINK_ACTION, Data[0]);
if ((!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "MISN", 4)) &&
(!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "MIPX", 4)) &&
(!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), "XPIM", 4)) &&
(!RtlEqualMemory ((PVOID)(&NwlinkAction->Header.TransportId), BogusId, 4))) {
return STATUS_NOT_SUPPORTED;
}
//
// Make sure that the correct file object is being used.
//
if (NwlinkAction->OptionType == NWLINK_OPTION_ADDRESS) {
if (REQUEST_OPEN_TYPE(Request) != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
NB_DEBUG (QUERY, ("Nwlink action failed, not address file\n"));
return STATUS_INVALID_HANDLE;
}
AddressFile = (PADDRESS_FILE)REQUEST_OPEN_CONTEXT(Request);
if ((AddressFile->Size != sizeof (ADDRESS_FILE)) ||
(AddressFile->Type != NB_ADDRESSFILE_SIGNATURE)) {
NB_DEBUG (QUERY, ("Nwlink action failed, bad address file\n"));
return STATUS_INVALID_HANDLE;
}
} else if (NwlinkAction->OptionType != NWLINK_OPTION_CONTROL) {
NB_DEBUG (QUERY, ("Nwlink action failed, option type %d\n", NwlinkAction->OptionType));
return STATUS_NOT_SUPPORTED;
}
//
// Handle the requests based on the action code. For these
// requests ActionHeader->ActionCode is 0, we use the
// Option field in the streams header instead.
//
Status = STATUS_SUCCESS;
switch (NwlinkAction->Option) {
case (I_MIPX | 351):
//
// A request for details on every binding.
//
if (DataLength < sizeof(NB_ACTION_GET_COUNTS)) {
return STATUS_BUFFER_TOO_SMALL;
}
u.GetCounts = (PNB_ACTION_GET_COUNTS)(NwlinkAction->Data);
u.GetCounts->MaximumNicId = NbiDevice->MaximumNicId;
for (i = 0; i < 32 ; i++) {
u.GetCounts->NicIdCounts[i] = 0;
}
for (i = 0; i < CONNECTION_HASH_COUNT; i++) {
NB_GET_LOCK (&Device->Lock, &LockHandle);
Connection = Device->ConnectionHash[i].Connections;
while (Connection != NULL) {
#if defined(_PNP_POWER)
if ((Connection->State == CONNECTION_STATE_ACTIVE) &&
(Connection->LocalTarget.NicHandle.NicId < 32)) {
++u.GetCounts->NicIdCounts[Connection->LocalTarget.NicHandle.NicId];
}
#else
if ((Connection->State == CONNECTION_STATE_ACTIVE) &&
(Connection->LocalTarget.NicId < 32)) {
++u.GetCounts->NicIdCounts[Connection->LocalTarget.NicId];
}
#endif _PNP_POWER
Connection = Connection->NextConnection;
}
NB_FREE_LOCK (&Device->Lock, LockHandle);
}
break;
//
// The Option was not supported, so fail.
//
default:
Status = STATUS_NOT_SUPPORTED;
break;
} // end of the long switch on NwlinkAction->Option
#if DBG
if (!NT_SUCCESS(Status)) {
NB_DEBUG (QUERY, ("Nwlink action %lx failed, status %lx\n", NwlinkAction->Option, Status));
}
#endif
return Status;
} /* NbiTdiAction */