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.9 KiB
225 lines
5.9 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 */
|
|
|