|
|
/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
spxquery.c
Abstract:
This module contains code which performs the following TDI services:
o TdiQueryInformation
Author:
Adam Barr (adamba) Initial Version Nikhil Kamkolkar (nikhilk) 11-November-1993
Environment:
Kernel mode
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
// Discardable code after Init time
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, SpxQueryInitProviderInfo)
#endif
// Define module number for event logging entries
#define FILENUM SPXQUERY
// Useful macro to obtain the total length of an MDL chain.
#define SpxGetMdlChainLength(Mdl, Length) { \
PMDL _Mdl = (Mdl); \ *(Length) = 0; \ while (_Mdl) { \ *(Length) += MmGetMdlByteCount(_Mdl); \ _Mdl = _Mdl->Next; \ } \ }
VOID SpxQueryInitProviderInfo( PTDI_PROVIDER_INFO ProviderInfo ) { // Initialize to defaults first
RtlZeroMemory((PVOID)ProviderInfo, sizeof(TDI_PROVIDER_INFO));
ProviderInfo->Version = SPX_TDI_PROVIDERINFO_VERSION; KeQuerySystemTime (&ProviderInfo->StartTime); ProviderInfo->MinimumLookaheadData = SPX_PINFOMINMAXLOOKAHEAD; ProviderInfo->MaximumLookaheadData = IpxLineInfo.MaximumPacketSize; ProviderInfo->MaxSendSize = SPX_PINFOSENDSIZE; ProviderInfo->ServiceFlags = SPX_PINFOSERVICEFLAGS; return; }
NTSTATUS SpxTdiQueryInformation( 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:
NTSTATUS - status of operation.
--*/
{ NTSTATUS status; PSPX_ADDR_FILE AddressFile; PSPX_CONN_FILE ConnectionFile; PTDI_REQUEST_KERNEL_QUERY_INFORMATION query; struct { ULONG ActivityCount; TA_IPX_ADDRESS SpxAddress; } AddressInfo;
// what type of status do we want?
query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)REQUEST_PARAMETERS(Request);
switch (query->QueryType) { case TDI_QUERY_CONNECTION_INFO:
status = STATUS_NOT_IMPLEMENTED; break;
case TDI_QUERY_ADDRESS_INFO:
// The caller wants the exact address value.
ConnectionFile = (PSPX_CONN_FILE)REQUEST_OPEN_CONTEXT(Request); status = SpxConnFileVerify(ConnectionFile);
if (status == STATUS_SUCCESS) { AddressFile = ConnectionFile->scf_AddrFile; SpxConnFileDereference(ConnectionFile, CFREF_VERIFY); } else { AddressFile = (PSPX_ADDR_FILE)REQUEST_OPEN_CONTEXT(Request); }
status = SpxAddrFileVerify(AddressFile);
if (status == STATUS_SUCCESS) { DBGPRINT(RECEIVE, INFO, ("SpxTdiQuery: Net.Socket %lx.%lx\n", *(PULONG)Device->dev_Network, AddressFile->saf_Addr->sa_Socket));
AddressInfo.ActivityCount = 0; (VOID)SpxBuildTdiAddress( &AddressInfo.SpxAddress, sizeof(TA_IPX_ADDRESS), Device->dev_Network, Device->dev_Node, AddressFile->saf_Addr->sa_Socket);
status = TdiCopyBufferToMdl( &AddressInfo, 0, sizeof(AddressInfo), REQUEST_NDIS_BUFFER(Request), 0, (PULONG)&REQUEST_INFORMATION(Request));
SpxAddrFileDereference(AddressFile, AFREF_VERIFY);
}
break;
case TDI_QUERY_PROVIDER_INFO: { BYTE socketType; TDI_PROVIDER_INFO providerInfo = Device->dev_ProviderInfo;
//
// The device name extension comes down in the Irp
//
if (!NT_SUCCESS(status = SpxUtilGetSocketType( REQUEST_OPEN_NAME(Request), &socketType))) { DBGPRINT(RECEIVE, ERR, ("TDI_QUERY_PROVIDER_INFO: SpxUtilGetSocketType failed: %lx\n", status)); return(status); }
//
// The Catapult folks had a problem where AFD was discarding buffered sends on the NT box when it got a
// local disconnect on SPX1. This was because the Orderly release flag was always set in the provider
// info. AFD queries this once per device type. We detect the device above and OR in the orderly release
// flag if this query came down on an SPX2 endpoint.
// This is to make sure that AFD follows the correct disconnect semantics for SPX1 and SPX2 (SPX1 does
// only abortive; SPX2 does both abortive and orderly).
//
// this will still not solve the problem completely since a connection that starts off as an SPX2
// one can still be negotiated to SPX1 if the remote supports only SPX1.
//
if ((socketType == SOCKET2_TYPE_SEQPKT) || (socketType == SOCKET2_TYPE_STREAM)) {
DBGPRINT(RECEIVE, INFO, ("TDI_QUERY_PROVIDER_INFO: SPX2 socket\n")); providerInfo.ServiceFlags |= TDI_SERVICE_ORDERLY_RELEASE; } else { DBGPRINT(RECEIVE, INFO, ("TDI_QUERY_PROVIDER_INFO: SPX1 socket\n")); }
status = TdiCopyBufferToMdl ( &providerInfo, 0, sizeof (TDI_PROVIDER_INFO), REQUEST_TDI_BUFFER(Request), 0, (PULONG)&REQUEST_INFORMATION(Request)); break; }
case TDI_QUERY_PROVIDER_STATISTICS:
status = TdiCopyBufferToMdl ( &Device->dev_Stat, 0, FIELD_OFFSET (TDI_PROVIDER_STATISTICS, ResourceStats[0]), REQUEST_TDI_BUFFER(Request), 0, (PULONG)&REQUEST_INFORMATION(Request)); break;
default: status = STATUS_INVALID_DEVICE_REQUEST; break; }
return status;
} // SpxTdiQueryInformation
NTSTATUS SpxTdiSetInformation( 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;
} // SpxTdiSetInformation
|