226 lines
5.6 KiB
C
226 lines
5.6 KiB
C
/*++
|
||
|
||
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 */
|
||
|