summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/spx/spxquery.c
blob: 047ecabe81f263e204e3c2915ac9591b6a1400d2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*++

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,
                &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).
        //
        // BUGBUG: 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,
                    &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,
                    &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