summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/nbf/nbftypes.h
blob: a72e9fe1b5dbe18aa8282ebc53969604b1c2416a (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
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    nbftypes.h

Abstract:

    This module defines private data structures and types for the NT
    NBF transport provider.

Author:

    David Beaver (dbeaver) 1 July 1991

Revision History:

--*/

#ifndef _NBFTYPES_
#define _NBFTYPES_

//
// This structure defines a NETBIOS name as a character array for use when
// passing preformatted NETBIOS names between internal routines.  It is
// not a part of the external interface to the transport provider.
//

#define NETBIOS_NAME_SIZE 16

typedef struct _NBF_NETBIOS_ADDRESS {
    UCHAR NetbiosName[NETBIOS_NAME_SIZE];
    USHORT NetbiosNameType;
} NBF_NETBIOS_ADDRESS, *PNBF_NETBIOS_ADDRESS;

typedef UCHAR NAME;
typedef NAME UNALIGNED *PNAME;


//
// This structure defines things associated with a TP_REQUEST, or outstanding
// TDI request, maintained on a queue somewhere in the transport.  All
// requests other than open/close require that a TP_REQUEST block be built.
//

#if DBG
#define REQUEST_HISTORY_LENGTH 20
extern KSPIN_LOCK NbfGlobalInterlock;
#endif

//
// the types of potential owners of requests
//

typedef  enum _REQUEST_OWNER {
    ConnectionType,
    AddressType,
    DeviceContextType
} REQUEST_OWNER;

//typedef
//NTSTATUS
//(*PTDI_TIMEOUT_ACTION)(
//    IN PTP_REQUEST Request
//    );

//
// The request itself
//

#if DBG
#define RREF_CREATION   0
#define RREF_PACKET     1
#define RREF_TIMER      2
#define RREF_RECEIVE    3
#define RREF_FIND_NAME  4
#define RREF_STATUS     5

#define NUMBER_OF_RREFS 8
#endif

typedef struct _TP_REQUEST {
    CSHORT Type;                          // type of this structure
    USHORT Size;                          // size of this structure
    LIST_ENTRY Linkage;                   // used by ExInterlocked routines.
    KSPIN_LOCK SpinLock;                  // spinlock for other fields.
                                          //  (used in KeAcquireSpinLock calls)
#if DBG
    LONG RefTypes[NUMBER_OF_RREFS];
#endif
    LONG ReferenceCount;                  // reasons why we can't destroy this req.

    struct _DEVICE_CONTEXT *Provider;     // pointer to the device context.
    PKSPIN_LOCK ProviderInterlock;        // &Provider->Interlock.

    PIRP IoRequestPacket;                 // pointer to IRP for this request.

    //
    // The following two fields are used to quickly reference the basic
    // components of the requests without worming through the IRP's stack.
    //

    PVOID Buffer2;                        // second buffer in the request.
    ULONG Buffer2Length;                  // length of the second buffer.

    //
    // The following two fields (Flags and Context) are used to clean up
    // queued requests which must be canceled or abnormally completed.
    // The Flags field contains bitflags indicating the state of the request,
    // and the specific queue type that the request is located on.  The
    // Context field contains a pointer to the owning structure (TP_CONNECTION
    // or TP_ADDRESS) so that the cleanup routines can perform post-cleanup
    // operations on the owning structure, such as dereferencing, etc.
    //

    ULONG Flags;                          // disposition of this request.
    PVOID Context;                        // context of this request.
    REQUEST_OWNER Owner;                  // what type of owner this request has.

#if DBG
    LARGE_INTEGER Time;                   // time when request created
#endif

    KTIMER Timer;                         // kernel timer for this request.
    KDPC Dpc;                             // DPC object for timeouts.

    //
    // These fields are used for FIND.NAME and STATUS.QUERY requests.
    //

    ULONG Retries;                        // timeouts remaining.
    USHORT BytesWritten;                  // usage varies.
    USHORT FrameContext;                  // identifies request.
    PVOID ResponseBuffer;                 // temp alloc to hold data.

#if DBG
  LIST_ENTRY GlobalLinkage;
  ULONG TotalReferences;
  ULONG TotalDereferences;
  ULONG NextRefLoc;
  struct {
     PVOID Caller;
     PVOID CallersCaller;
  } History[REQUEST_HISTORY_LENGTH];
  BOOLEAN Completed;
  BOOLEAN Destroyed;
#endif

} TP_REQUEST, *PTP_REQUEST;

#ifdef _PNP_POWER
//
// in nbfdrvr.c
//

extern UNICODE_STRING NbfRegistryPath;

//
// We need the driver object to create device context structures.
//

extern PDRIVER_OBJECT NbfDriverObject;

#endif // _PNP_POWER
#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalRequestList;
#define StoreRequestHistory(_req,_ref) {                                \
    KIRQL oldIrql;                                                      \
    KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql);                \
    if ((_req)->Destroyed) {                                            \
        DbgPrint ("request touched after being destroyed 0x%lx\n",      \
                    (_req));                                            \
        DbgBreakPoint();                                                \
    }                                                                   \
    RtlGetCallersAddress(                                               \
        &(_req)->History[(_req)->NextRefLoc].Caller,                    \
        &(_req)->History[(_req)->NextRefLoc].CallersCaller              \
        );                                                              \
    if ((_ref)) {                                                       \
        (_req)->TotalReferences++;                                      \
    } else {                                                            \
        (_req)->TotalDereferences++;                                    \
        (_req)->History[(_req)->NextRefLoc].Caller =                    \
         (PVOID)((ULONG)(_req)->History[(_req)->NextRefLoc].Caller &    \
                                                        ~0x80000000);   \
    }                                                                   \
    if (++(_req)->NextRefLoc == REQUEST_HISTORY_LENGTH) {               \
        (_req)->NextRefLoc = 0;                                         \
    }                                                                   \
    KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql);                 \
}
#endif

#define NBF_ALLOCATION_TYPE_REQUEST 1

#define REQUEST_FLAGS_TIMER      0x0001 // a timer is active for this request.
#define REQUEST_FLAGS_TIMED_OUT  0x0002 // a timer expiration occured on this request.
#define REQUEST_FLAGS_ADDRESS    0x0004 // request is attached to a TP_ADDRESS.
#define REQUEST_FLAGS_CONNECTION 0x0008 // request is attached to a TP_CONNECTION.
#define REQUEST_FLAGS_STOPPING   0x0010 // request is being killed.
#define REQUEST_FLAGS_EOR        0x0020 // TdiSend request has END_OF_RECORD mark.
#define REQUEST_FLAGS_PIGGYBACK  0x0040 // TdiSend that can be piggyback ack'ed.
#define REQUEST_FLAGS_DC         0x0080 // request is attached to a TP_DEVICE_CONTEXT

//
// This defines the TP_SEND_IRP_PARAMETERS, which is masked onto the
// Parameters section of a send IRP's stack location.
//

typedef struct _TP_SEND_IRP_PARAMETERS {
    TDI_REQUEST_KERNEL_SEND Request;
    LONG ReferenceCount;
    PVOID Irp;
} TP_SEND_IRP_PARAMETERS, *PTP_SEND_IRP_PARAMETERS;

#define IRP_SEND_LENGTH(_IrpSp) \
    (((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.SendLength)

#define IRP_SEND_FLAGS(_IrpSp) \
    (((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.SendFlags)

#define IRP_SEND_REFCOUNT(_IrpSp) \
    (((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->ReferenceCount)

#define IRP_SEND_IRP(_IrpSp) \
    (((PTP_SEND_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Irp)

#define IRP_SEND_CONNECTION(_IrpSp) \
    ((PTP_CONNECTION)((_IrpSp)->FileObject->FsContext))

#define IRP_DEVICE_CONTEXT(_IrpSp) \
    ((PDEVICE_CONTEXT)((_IrpSp)->DeviceObject))


//
// This defines the TP_RECEIVE_IRP_PARAMETERS, which is masked onto the
// Parameters section of a receive IRP's stack location.
//

typedef struct _TP_RECEIVE_IRP_PARAMETERS {
    TDI_REQUEST_KERNEL_RECEIVE Request;
    LONG ReferenceCount;
    PIRP Irp;
} TP_RECEIVE_IRP_PARAMETERS, *PTP_RECEIVE_IRP_PARAMETERS;

#define IRP_RECEIVE_LENGTH(_IrpSp) \
    (((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.ReceiveLength)

#define IRP_RECEIVE_FLAGS(_IrpSp) \
    (((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Request.ReceiveFlags)

#define IRP_RECEIVE_REFCOUNT(_IrpSp) \
    (((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->ReferenceCount)

#define IRP_RECEIVE_IRP(_IrpSp) \
    (((PTP_RECEIVE_IRP_PARAMETERS)&(_IrpSp)->Parameters)->Irp)

#define IRP_RECEIVE_CONNECTION(_IrpSp) \
    ((PTP_CONNECTION)((_IrpSp)->FileObject->FsContext))



//
// This structure defines a TP_UI_FRAME, or connectionless frame header,
// that is manipulated by the FRAME.C routines.
//

typedef struct _TP_UI_FRAME {
  PNDIS_PACKET NdisPacket;
  LIST_ENTRY Linkage;                     // used by ExInterLocked routines.
  PVOID DataBuffer;                       // for transport-created data.
  UCHAR Header[1];                        // the header in the frame (MAC + DLC + NBF)
} TP_UI_FRAME, *PTP_UI_FRAME;


//
// This structure defines a TP_VARIABLE, or network managable variable,
// maintained in a linked list on the device context.
//

typedef struct _TP_VARIABLE {

  struct _TP_VARIABLE *Fwdlink;         // next variable in provider's chain.

  ULONG VariableSerialNumber;           // identifier for this variable.
  ULONG VariableType;                   // type of this variable (see TDI.H).
  STRING VariableName;                  // allocated variable name.

  union {
      ULONG LongValue;
      HARDWARE_ADDRESS HardwareAddressValue;
      STRING StringValue;               // allocated string value, if of that type.
  } Value;

} TP_VARIABLE, *PTP_VARIABLE;


//
// This structure defines a TP_CONNECTION, or active transport connection,
// maintained on a transport address.
//

#if DBG
#define CONNECTION_HISTORY_LENGTH 50

#define CREF_SPECIAL_CREATION 0
#define CREF_SPECIAL_TEMP 1
#define CREF_COMPLETE_SEND 2
#define CREF_SEND_IRP 3
#define CREF_ADM_SESS 4
#define CREF_TRANSFER_DATA 5
#define CREF_FRAME_SEND 6
#define CREF_TIMER 7
#define CREF_BY_ID 8
#define CREF_LINK 9
#define CREF_SESSION_END 10
#define CREF_LISTENING 11
#define CREF_P_LINK 12
#define CREF_P_CONNECT 13
#define CREF_PACKETIZE 14
#define CREF_RECEIVE_IRP 15
#define CREF_PROCESS_DATA 16
#define CREF_REQUEST 17
#define CREF_TEMP 18
#define CREF_DATA_ACK_QUEUE 19
#define CREF_ASSOCIATE 20
#define CREF_STOP_ADDRESS 21
#define CREF_PACKETIZE_QUEUE 22
#define CREF_STALLED 23

#define NUMBER_OF_CREFS 24
#endif

//
// This structure holds our "complex send pointer" indicating
// where we are in the packetization of a send.
//

typedef struct _TP_SEND_POINTER {
    ULONG MessageBytesSent;             // up count, bytes sent/this msg.
    PIRP CurrentSendIrp;                // ptr, current send request in chain.
    PMDL  CurrentSendMdl;               // ptr, current MDL in send chain.
    ULONG SendByteOffset;               // current byte offset in current MDL.
} TP_SEND_POINTER, *PTP_SEND_POINTER;

typedef struct _TP_CONNECTION {

#if DBG
    ULONG RefTypes[NUMBER_OF_CREFS];
#endif

#if DBG
    ULONG LockAcquired;
    UCHAR LastAcquireFile[8];
    ULONG LastAcquireLine;
    ULONG Padding;
    UCHAR LastReleaseFile[8];
    ULONG LastReleaseLine;
#endif

    CSHORT Type;
    USHORT Size;

    LIST_ENTRY LinkList;                // used for link thread or for free
                                        // resource list
    KSPIN_LOCK SpinLock;                // spinlock for connection protection.
    PKSPIN_LOCK LinkSpinLock;           // pointer to link's spinlock

    LONG ReferenceCount;                // number of references to this object.
    LONG SpecialRefCount;               // controls freeing of connection.

    //
    // The following lists are used to associate this connection with a
    // particular address.
    //

    LIST_ENTRY AddressList;             // list of connections for given address
    LIST_ENTRY AddressFileList;         // list for connections bound to a
                                        // given address reference

    //
    // The following field is used as linkage in the device context's
    // PacketizeQueue
    //

    LIST_ENTRY PacketizeLinkage;

    //
    // The following field is used as linkage in the device context's
    // PacketWaitQueue.
    //

    LIST_ENTRY PacketWaitLinkage;

    //
    // The following field points to the TP_LINK object that describes the
    // (active) data link connection for this transport connection.  To be
    // valid, this field is non-NULL.
    //

    struct _TP_LINK *Link;                  // pointer to transport link object.
    struct _TP_ADDRESS_FILE *AddressFile;   // pointer to owning Address.
    struct _DEVICE_CONTEXT *Provider;       // device context to which we are attached.
    PKSPIN_LOCK ProviderInterlock;          // &Provider->Interlock
    PFILE_OBJECT FileObject;                // easy backlink to file object.

    //
    // The following field contains the actual ID we expose to the TDI client
    // to represent this connection.  A unique one is created from the address.
    //

    USHORT ConnectionId;                    // unique identifier.
    UCHAR SessionNumber;                    // the session number used in the packet header

    //
    // This field is used to keep the reason for the connection disconnect
    // around until connection deletion time.
    //

    BOOLEAN RemoteDisconnect;           // was this connection remotely disonnected?

    //
    // The following field is specified by the user at connection open time.
    // It is the context that the user associates with the connection so that
    // indications to and from the client can be associated with a particular
    // connection.
    //

    CONNECTION_CONTEXT Context;         // client-specified value.

    //
    // The following two queues are used to associate TdiSend and TdiReceive
    // IRPs with this connection.  New arrivals are placed at the end of
    // the queues (really a linked list) and IRPs are processed at the
    // front of the queues.  The first TdiSend IRP on the SendQueue is
    // the current TdiSend being processed, and the first TdiReceive IRP
    // on the ReceiveQueue is the first TdiReceive being processed, PROVIDED
    // the CONNECTION_FLAGS_ACTIVE_RECEIVE flag is set.  If this flag is not
    // set, then the first TdiReceive IRP on the ReceiveQueue is not active.
    // These queues are managed by the EXECUTIVE interlocked list manipuation
    // routines.
    //

    LIST_ENTRY SendQueue;               // FIFO of outstanding TdiSends.
    LIST_ENTRY ReceiveQueue;            // FIFO of outstanding TdiReceives.

    //
    // The following fields are used to maintain state for the current receive.
    //

    ULONG MessageBytesReceived;         // up count, bytes recd/this msg.
    ULONG MessageBytesAcked;            // bytes acked (NR or RO) this msg.
    ULONG MessageInitAccepted;          // bytes accepted during indication.

    //
    // These fields are only valid if the CONNECTION_FLAGS_ACTIVE_RECEIVE
    // flag is set.
    //

    PIRP SpecialReceiveIrp;             // a "no-request" receive IRP exists.
    PIRP CurrentReceiveIrp;             // ptr, current receive IRP.
    PMDL  CurrentReceiveMdl;            // ptr, current MDL in receive chain.
    ULONG ReceiveByteOffset;            // current byte offset in current MDL.
    ULONG ReceiveLength;                // current receive length, in bytes (total)
    ULONG ReceiveBytesUnaccepted;       // by client...only indicate when == 0

    //
    // The following fields are used to maintain state for the active send.
    // They only have meaning if the connection's SendState is not IDLE.
    // Because the TDI client may submit multiple TdiSend requests to comprise
    // a full message, we have to keep a complex pointer to the first byte of
    // unACKed data (hence the first three fields).  We also have a complex
    // pointer to the first byte of unsent data (hence the last three fields).
    //

    ULONG SendState;                    // send state machine variable.

    PIRP FirstSendIrp;                  // ptr, 1st TdiSend's IRP.
    PMDL  FirstSendMdl;                 // ptr, 1st unacked MDL in chain/this msg.
    ULONG FirstSendByteOffset;          // pre-acked bytes in that MDL.

    TP_SEND_POINTER sp;                 // current send loc, defined above.
    ULONG CurrentSendLength;            // how long is this send (total)
    ULONG StallCount;                   // times in a row we looked stalled.
    ULONG StallBytesSent;               // bytes sent last time we checked.

    //
    // This is TRUE if we need don't need to reference the current
    // receive IRP during transfers (because it is a special
    // receive or the driver doesn't pend transfers).
    //

    BOOLEAN CurrentReceiveSynchronous;

    //
    // This field will be TRUE if the last DOL received allowed
    // piggyback acks.
    //

    BOOLEAN CurrentReceiveAckQueueable;

    //
    //
    // This field will be TRUE if the last DOL received was
    // sent NO.ACK.
    //

    BOOLEAN CurrentReceiveNoAck;

    //
    // These fields handle asynchronous TransferData calls.
    //

    ULONG TransferBytesPending;         // bytes pending in current transfers
    ULONG TotalTransferBytesPending;    // bytes since TransferBytesPending was 0;
                                        // how much we back off if a transfer fails
    PMDL SavedCurrentReceiveMdl;        // used to back off by TotalTransferPending bytes
    ULONG SavedReceiveByteOffset;       // used to back off by TotalTransferPending bytes

    //
    // This field will be TRUE if we are in the middle of
    // processing a receive indication on this connection and
    // we are not yet in a state where another indication
    // can be handled.
    //
    // It is stored as a INT since access to it is guarded
    // by the connection's link spinlock, unlike the variables
    // around it (BUGBUG: What about Alpha?)
    //

    UINT IndicationInProgress;

    //
    // The following field is used as a linkage when on the device
    // context's DataAckQueue.
    //

    LIST_ENTRY DataAckLinkage;

    //
    // TRUE if the connection is on the data ack queue.
    // Also an INT so access can be non-guarded.
    //

    UINT OnDataAckQueue;

    //
    // These keep track of the number of consecutive sends or
    // receives on this connection. This is used in determining when
    // to queue a data ack.
    //

    ULONG ConsecutiveSends;
    ULONG ConsecutiveReceives;

    //
    // The following list head is used as a pointer to a TdiListen/TdiConnect
    // request which is in progress.  Although manipulated
    // with queue instructions, there will only be one request in the queue.
    // This is done for consistency with respect to TpCreateRequest, which
    // does a great job of creating a request and associating it atomically
    // with a supervisory object.
    //

    LIST_ENTRY InProgressRequest;       // TdiListen/TdiConnect

    //
    // If the connection is being disconnected as a result of
    // a TdiDisconnect call (RemoteDisconnect is FALSE) then this
    // will hold the IRP passed to TdiDisconnect. It is needed
    // when the TdiDisconnect request is completed.
    //

    PIRP DisconnectIrp;

    //
    // If the connection is being closed, this will hold
    // the IRP passed to TdiCloseConnection. It is needed
    // when the request is completed.
    //

    PIRP CloseIrp;

    //
    // These fields are used for deferred operations on connections; the only
    // deferred operation currently supported is piggyback ACK
    //

    ULONG DeferredFlags;
#if DBG
    ULONG DeferredPasses;
#endif
    LIST_ENTRY DeferredQueue;

    //
    // The following fields are used for connection housekeeping.
    //

    ULONG Flags;                        // attributes guarded by LinkSpinLock
    ULONG Flags2;                       // attributes guarded by SpinLock
    UINT OnPacketWaitQueue;             // TRUE if on PacketWaitQueue
    UCHAR Lsn;                          // local session number (1-254).
    UCHAR Rsn;                          // remote session number (1-254).
    USHORT Retries;                     // retry limit for NAME_QUERY shipments.
    KTIMER Timer;                       // kernel timer for timeouts on NQ/NR.
    LARGE_INTEGER ConnectStartTime;     // when we sent the committed NQ.
    KDPC Dpc;                           // DPC object for timeouts.
    NTSTATUS Status;                    // status code for connection rundown.
    ULONG LastPacketsSent;              // The value that was in Link->XXX the
    ULONG LastPacketsResent;            //  last time we calculated the throughput.
    NBF_NETBIOS_ADDRESS CalledAddress;  // TdiConnect request's T.A.
    USHORT MaximumDataSize;             // maximum I-frame data size for NBF.

    NBF_HDR_CONNECTION NetbiosHeader;   // pre-built Netbios header; we store
                                        // the current send and reply correlators
                                        // in the appropriate spots in this.

    //
    // These are for CONNECTION_INFO queries.
    //

    ULONG TransmittedTsdus;             // TSDUs sent on this connection.
    ULONG ReceivedTsdus;                // TSDUs received on this connection.
    ULONG TransmissionErrors;           // TSDUs transmitted in error/this connection.
    ULONG ReceiveErrors;                // TSDUs received in error/this connection.

    //
    // The following structure contains statistics counters for use
    // by TdiQueryInformation and TdiSetInformation.  They should not
    // be used for maintenance of internal data structures.
    //

    // TDI_CONNECTION_INFO Information;    // information about this connection.

#if DBG
    LIST_ENTRY GlobalLinkage;
    ULONG TotalReferences;
    ULONG TotalDereferences;
    ULONG NextRefLoc;
    struct {
        PVOID Caller;
        PVOID CallersCaller;
    } History[CONNECTION_HISTORY_LENGTH];
    BOOLEAN Destroyed;
#endif
    CHAR RemoteName[16];

} TP_CONNECTION, *PTP_CONNECTION;

#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalConnectionList;
#define StoreConnectionHistory(_conn,_ref) {                                \
    KIRQL oldIrql;                                                          \
    KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql);                    \
    if ((_conn)->Destroyed) {                                               \
        DbgPrint ("connection touched after being destroyed 0x%lx\n",       \
                    (_conn));                                               \
        DbgBreakPoint();                                                    \
    }                                                                       \
    RtlGetCallersAddress(                                                   \
        &(_conn)->History[(_conn)->NextRefLoc].Caller,                      \
        &(_conn)->History[(_conn)->NextRefLoc].CallersCaller                \
        );                                                                  \
    if ((_ref)) {                                                           \
        (_conn)->TotalReferences++;                                         \
    } else {                                                                \
        (_conn)->TotalDereferences++;                                       \
        (_conn)->History[(_conn)->NextRefLoc].Caller =                      \
         (PVOID)((ULONG)(_conn)->History[(_conn)->NextRefLoc].Caller | 1);  \
    }                                                                       \
    if (++(_conn)->NextRefLoc == CONNECTION_HISTORY_LENGTH) {               \
        (_conn)->NextRefLoc = 0;                                            \
    }                                                                       \
    KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql);                            \
}
#endif

#define CONNECTION_FLAGS_VERSION2       0x00000001 // remote netbios is version 2.0.
#define CONNECTION_FLAGS_RECEIVE_WAKEUP 0x00000002 // send a RECEIVE_OUTSTANDING when a receive arrives.
#define CONNECTION_FLAGS_ACTIVE_RECEIVE 0x00000004 // a receive is active.
#define CONNECTION_FLAGS_WAIT_SI        0x00000020 // waiting for a SESSION_INITIALIZE.
#define CONNECTION_FLAGS_WAIT_SC        0x00000040 // waiting for a SESSION_CONFIRM.
#define CONNECTION_FLAGS_WAIT_LINK_UP   0x00000080 // waiting for DDI to est. connection.
#define CONNECTION_FLAGS_READY          0x00000200 // sends/rcvs/discons valid.
#define CONNECTION_FLAGS_RC_PENDING     0x00001000 // a receive is pending completion
#define CONNECTION_FLAGS_W_PACKETIZE    0x00002000 // w/for a packet to packetize.
#define CONNECTION_FLAGS_PACKETIZE      0x00004000 // we're on the PacketizeQueue.
#define CONNECTION_FLAGS_W_RESYNCH      0x00008000 // waiting for resynch indicator. (receive)
#define CONNECTION_FLAGS_SEND_SI        0x00010000 // w/for a packet to send SI.
#define CONNECTION_FLAGS_SEND_SC        0x00020000 // w/for a packet to send SC.
#define CONNECTION_FLAGS_SEND_DA        0x00040000 // w/for a packet to send DA.
#define CONNECTION_FLAGS_SEND_RO        0x00080000 // w/for a packet to send RO.
#define CONNECTION_FLAGS_SEND_RC        0x00100000 // w/for a packet to send RC.
#define CONNECTION_FLAGS_SEND_SE        0x00200000 // w/for a packet to send SE.
#define CONNECTION_FLAGS_SEND_NR        0x00400000 // w/for a packet to send NR.
#define CONNECTION_FLAGS_NO_INDICATE    0x00800000 // don't take packets at indication time
#define CONNECTION_FLAGS_FAILING_TO_EOR 0x01000000 // wait for an EOF in an incoming request before sending
#define CONNECTION_FLAGS_RESYNCHING     0x02000000 // engaged send side resynch
#define CONNECTION_FLAGS_RCV_CANCELLED  0x10000000 // current receive was cancelled
#define CONNECTION_FLAGS_PEND_INDICATE  0x20000000 // new data received during RC_PENDING
#define CONNECTION_FLAGS_TRANSFER_FAIL  0x40000000 // a transfer data call failed

#define CONNECTION_FLAGS2_STOPPING      0x00000001 // connection is running down.
#define CONNECTION_FLAGS2_WAIT_NR       0x00000002 // waiting for NAME_RECOGNIZED.
#define CONNECTION_FLAGS2_WAIT_NQ       0x00000004 // waiting for NAME_QUERY.
#define CONNECTION_FLAGS2_WAIT_NR_FN    0x00000008 // waiting for FIND NAME response.
#define CONNECTION_FLAGS2_CLOSING       0x00000010 // connection is closing
#define CONNECTION_FLAGS2_ASSOCIATED    0x00000020 // associated with address
#define CONNECTION_FLAGS2_DISCONNECT    0x00000040 // disconnect done on connection
#define CONNECTION_FLAGS2_ACCEPTED      0x00000080 // accept done on connection
#define CONNECTION_FLAGS2_REQ_COMPLETED 0x00000100 // Listen/Connect request completed.
#define CONNECTION_FLAGS2_DISASSOCIATED 0x00000200 // associate CRef has been removed
#define CONNECTION_FLAGS2_DISCONNECTED  0x00000400 // disconnect has been indicated
#define CONNECTION_FLAGS2_NO_LISTEN     0x00000800 // no_listen received during setup
#define CONNECTION_FLAGS2_REMOTE_VALID  0x00001000 // Connection->RemoteName is valid
#define CONNECTION_FLAGS2_GROUP_LSN     0x00002000 // connection LSN is globally assigned
#define CONNECTION_FLAGS2_W_ADDRESS     0x00004000 // waiting for address reregistration.
#define CONNECTION_FLAGS2_PRE_ACCEPT    0x00008000 // no TdiAccept after listen completes
#define CONNECTION_FLAGS2_ABORT         0x00010000 // abort this connection.
#define CONNECTION_FLAGS2_ORDREL        0x00020000 // we're in orderly release.
#define CONNECTION_FLAGS2_DESTROY       0x00040000 // destroy this connection.
#define CONNECTION_FLAGS2_LISTENER      0x00100000 // we were the passive listener.
#define CONNECTION_FLAGS2_CONNECTOR     0x00200000 // we were the active connector.
#define CONNECTION_FLAGS2_WAITING_SC    0x00400000 // the connection is waiting for
                                                   // and accept to send the
                                                   // session confirm
#define CONNECTION_FLAGS2_INDICATING    0x00800000 // connection was manipulated while
                                                   // indication was in progress

#define CONNECTION_FLAGS2_LDISC         0x01000000 // Local disconnect req.
#ifdef RASAUTODIAL
#define CONNECTION_FLAGS2_AUTOCONNECTING 0x02000000 // RAS autodial in progress
#define CONNECTION_FLAGS2_AUTOCONNECTED  0x04000000 // RAS autodial done
#endif // RASAUTODIAL

#define CONNECTION_FLAGS_STARVED (     \
            CONNECTION_FLAGS_SEND_SI | \
            CONNECTION_FLAGS_SEND_SC | \
            CONNECTION_FLAGS_SEND_DA | \
            CONNECTION_FLAGS_SEND_RO | \
            CONNECTION_FLAGS_SEND_RC | \
            CONNECTION_FLAGS_SEND_NR | \
            CONNECTION_FLAGS_SEND_SE   \
        )

#define CONNECTION_FLAGS_DEFERRED_ACK     0x00000001  // send piggyback ack first opportunity
#define CONNECTION_FLAGS_DEFERRED_ACK_2   0x00000002  // deferred ack wasn't sent
#define CONNECTION_FLAGS_DEFERRED_NOT_Q   0x00000004  // DEFERRED_ACK set, but not on DataAckQueue
#define CONNECTION_FLAGS_DEFERRED_SENDS   0x80000000  // print completed sends

#define CONNECTION_SENDSTATE_IDLE       0       // no sends being processed.
#define CONNECTION_SENDSTATE_PACKETIZE  1       // send being packetized.
#define CONNECTION_SENDSTATE_W_PACKET   2       // waiting for free packet.
#define CONNECTION_SENDSTATE_W_LINK     3       // waiting for good link conditions.
#define CONNECTION_SENDSTATE_W_EOR      4       // waiting for TdiSend(EOR).
#define CONNECTION_SENDSTATE_W_ACK      5       // waiting for DATA_ACK.
#define CONNECTION_SENDSTATE_W_RCVCONT  6       // waiting for RECEIVE_CONTINUE.


//
// This structure is pointed to by the FsContext field in the FILE_OBJECT
// for this Address.  This structure is the base for all activities on
// the open file object within the transport provider.  All active connections
// on the address point to this structure, although no queues exist here to do
// work from. This structure also maintains a reference to a TP_ADDRESS
// structure, which describes the address that it is bound to. Thus, a
// connection will point to this structure, which describes the address the
// connection was associated with. When the address file closes, all connections
// opened on this address file get closed, too. Note that this may leave an
// address hanging around, with other references.
//

typedef struct _TP_ADDRESS_FILE {

    CSHORT Type;
    CSHORT Size;

    LIST_ENTRY Linkage;                 // next address file on this address.
                                        // also used for linkage in the
                                        // look-aside list

    LONG ReferenceCount;                // number of references to this object.

    //
    // This structure is edited after taking the Address spinlock for the
    // owning address. This ensures that the address and this structure
    // will never get out of syncronization with each other.
    //

    //
    // The following field points to a list of TP_CONNECTION structures,
    // one per connection open on this address.  This list of connections
    // is used to help the cleanup process if a process closes an address
    // before disassociating all connections on it. By design, connections
    // will stay around until they are explicitly
    // closed; we use this database to ensure that we clean up properly.
    //

    LIST_ENTRY ConnectionDatabase;      // list of defined transport connections.

    //
    // the current state of the address file structure; this is either open or
    // closing
    //

    UCHAR State;

    //
    // The following fields are kept for housekeeping purposes.
    //

    PIRP Irp;                           // the irp used for open or close
    struct _TP_ADDRESS *Address;        // address to which we are bound.
    PFILE_OBJECT FileObject;            // easy backlink to file object.
    struct _DEVICE_CONTEXT *Provider;   // device context to which we are attached.

    //
    // The following queue is used to queue receive datagram requests
    // on this address file. Send datagram requests are queued on the
    // address itself. These queues are managed by the EXECUTIVE interlocked
    // list management routines. The actual objects which get queued to this
    // structure are request control blocks (RCBs).
    //

    LIST_ENTRY ReceiveDatagramQueue;    // FIFO of outstanding TdiReceiveDatagrams.

    //
    // This holds the Irp used to close this address file,
    // for pended completion.
    //

    PIRP CloseIrp;

    //
    // is this address file currently indicating a connection request? if yes, we
    // need to mark connections that are manipulated during this time.
    //

    BOOLEAN ConnectIndicationInProgress;

    //
    // handler for kernel event actions. First we have a set of booleans that
    // indicate whether or not this address has an event handler of the given
    // type registered.
    //

    BOOLEAN RegisteredConnectionHandler;
    BOOLEAN RegisteredDisconnectHandler;
    BOOLEAN RegisteredReceiveHandler;
    BOOLEAN RegisteredReceiveDatagramHandler;
    BOOLEAN RegisteredExpeditedDataHandler;
    BOOLEAN RegisteredErrorHandler;

    //
    // This function pointer points to a connection indication handler for this
    // Address. Any time a connect request is received on the address, this
    // routine is invoked.
    //
    //

    PTDI_IND_CONNECT ConnectionHandler;
    PVOID ConnectionHandlerContext;

    //
    // The following function pointer always points to a TDI_IND_DISCONNECT
    // handler for the address.  If the NULL handler is specified in a
    // TdiSetEventHandler, this this points to an internal routine which
    // simply returns successfully.
    //

    PTDI_IND_DISCONNECT DisconnectHandler;
    PVOID DisconnectHandlerContext;

    //
    // The following function pointer always points to a TDI_IND_RECEIVE
    // event handler for connections on this address.  If the NULL handler
    // is specified in a TdiSetEventHandler, then this points to an internal
    // routine which does not accept the incoming data.
    //

    PTDI_IND_RECEIVE ReceiveHandler;
    PVOID ReceiveHandlerContext;

    //
    // The following function pointer always points to a TDI_IND_RECEIVE_DATAGRAM
    // event handler for the address.  If the NULL handler is specified in a
    // TdiSetEventHandler, this this points to an internal routine which does
    // not accept the incoming data.
    //

    PTDI_IND_RECEIVE_DATAGRAM ReceiveDatagramHandler;
    PVOID ReceiveDatagramHandlerContext;

    //
    // An expedited data handler. This handler is used if expedited data is
    // expected; it never is in NBF, thus this handler should always point to
    // the default handler.
    //

    PTDI_IND_RECEIVE_EXPEDITED ExpeditedDataHandler;
    PVOID ExpeditedDataHandlerContext;

    //
    // The following function pointer always points to a TDI_IND_ERROR
    // handler for the address.  If the NULL handler is specified in a
    // TdiSetEventHandler, this this points to an internal routine which
    // simply returns successfully.
    //

    PTDI_IND_ERROR ErrorHandler;
    PVOID ErrorHandlerContext;
    PVOID ErrorHandlerOwner;


} TP_ADDRESS_FILE, *PTP_ADDRESS_FILE;

#define ADDRESSFILE_STATE_OPENING   0x00    // not yet open for business
#define ADDRESSFILE_STATE_OPEN      0x01    // open for business
#define ADDRESSFILE_STATE_CLOSING   0x02    // closing


//
// This structure defines a TP_ADDRESS, or active transport address,
// maintained by the transport provider.  It contains all the visible
// components of the address (such as the TSAP and network name components),
// and it also contains other maintenance parts, such as a reference count,
// ACL, and so on. All outstanding connection-oriented and connectionless
// data transfer requests are queued here.
//

#if DBG
#define AREF_TIMER              0
#define AREF_TEMP_CREATE        1
#define AREF_OPEN               2
#define AREF_VERIFY             3
#define AREF_LOOKUP             4
#define AREF_FRAME_SEND         5
#define AREF_CONNECTION         6
#define AREF_TEMP_STOP          7
#define AREF_REQUEST            8
#define AREF_PROCESS_UI         9
#define AREF_PROCESS_DATAGRAM  10
#define AREF_TIMER_SCAN        11

#define NUMBER_OF_AREFS        12
#endif

typedef struct _TP_ADDRESS {

#if DBG
    ULONG RefTypes[NUMBER_OF_AREFS];
#endif

    USHORT Size;
    CSHORT Type;

    LIST_ENTRY Linkage;                 // next address/this device object.
    LONG ReferenceCount;                // number of references to this object.

    //
    // The following spin lock is acquired to edit this TP_ADDRESS structure
    // or to scan down or edit the list of address files.
    //

    KSPIN_LOCK SpinLock;                // lock to manipulate this structure.

    //
    // The following fields comprise the actual address itself.
    //

    PIRP Irp;                           // pointer to address creation IRP.
    PNBF_NETBIOS_ADDRESS NetworkName;    // this address

    //
    // The following fields are used to maintain state about this address.
    //

    ULONG Flags;                        // attributes of the address.
    struct _DEVICE_CONTEXT *Provider;   // device context to which we are attached.

    //
    // The following queues is used to hold send datagrams for this
    // address. Receive datagrams are queued to the address file. Requests are
    // processed in a first-in, first-out manner, so that the very next request
    // to be serviced is always at the head of its respective queue.  These
    // queues are managed by the EXECUTIVE interlocked list management routines.
    // The actual objects which get queued to this structure are request control
    // blocks (RCBs).
    //

    LIST_ENTRY SendDatagramQueue;       // FIFO of outstanding TdiSendDatagrams.

    //
    // The following field points to a list of TP_CONNECTION structures,
    // one per active, connecting, or disconnecting connections on this
    // address.  By definition, if a connection is on this list, then
    // it is visible to the client in terms of receiving events and being
    // able to post requests by naming the ConnectionId.  If the connection
    // is not on this list, then it is not valid, and it is guaranteed that
    // no indications to the client will be made with reference to it, and
    // no requests specifying its ConnectionId will be accepted by the transport.
    //

    LIST_ENTRY ConnectionDatabase;  // list of defined transport connections.
    LIST_ENTRY AddressFileDatabase; // list of defined address file objects

    //
    // The packet pool of size 1 that holds the UI frame, and the
    // frame that is allocated out of it.
    //

    NDIS_HANDLE UIFramePoolHandle;
    PTP_UI_FRAME UIFrame;               // DLC-UI/NBF header for datagram sends.

    //
    // The following fields are used to register this address on the network.
    //

    ULONG Retries;                      // retries of ADD_NAME_QUERY left to go.
    KTIMER Timer;                       // kernel timer for timeouts on ANQ/ANR.
    KDPC Dpc;                           // DPC object for timeout.

    //
    // These two can be a union because they are not used
    // concurrently.
    //

    union {

        //
        // This structure is used for checking share access.
        //

        SHARE_ACCESS ShareAccess;

        //
        // Used for delaying NbfDestroyAddress to a thread so
        // we can access the security descriptor.
        //

        WORK_QUEUE_ITEM DestroyAddressQueueItem;

    } u;

    //
    // This structure is used to hold ACLs on the address.

    PSECURITY_DESCRIPTOR SecurityDescriptor;

    //
    // If we get an ADD_NAME_RESPONSE frame, this holds the address
    // of the remote we got it from (used to check for duplicate names).
    //

    UCHAR UniqueResponseAddress[6];

    //
    // Set to TRUE once we send a name in conflict frame, so that
    // we don't flood the network with them on every response.
    //

    BOOLEAN NameInConflictSent;

} TP_ADDRESS, *PTP_ADDRESS;

#define ADDRESS_FLAGS_GROUP             0x00000001 // set if group, otherwise unique.
#define ADDRESS_FLAGS_CONFLICT          0x00000002 // address in conflict detected.
#define ADDRESS_FLAGS_REGISTERING       0x00000004 // registration in progress.
#define ADDRESS_FLAGS_DEREGISTERING     0x00000008 // deregistration in progress.
#define ADDRESS_FLAGS_DUPLICATE_NAME    0x00000010 // duplicate name was found on net.
#define ADDRESS_FLAGS_NEEDS_REG         0x00000020 // address must be registered.
#define ADDRESS_FLAGS_STOPPING          0x00000040 // TpStopAddress is in progress.
#define ADDRESS_FLAGS_BAD_ADDRESS       0x00000080 // name in conflict on associated address.
#define ADDRESS_FLAGS_SEND_IN_PROGRESS  0x00000100 // send datagram process active.
#define ADDRESS_FLAGS_CLOSED            0x00000200 // address has been closed;
                                                   // existing activity can
                                                   // complete, nothing new can start
#define ADDRESS_FLAGS_NEED_REREGISTER   0x00000400 // quick-reregister on next connect.
#define ADDRESS_FLAGS_QUICK_REREGISTER  0x00000800 // address is quick-reregistering.


//
// This structure defines a TP_LINK, or established data link object,
// maintained by the transport provider.  Each data link connection with
// a remote machine is represented by this object.  Zero, one, or several
// transport connections can be multiplexed over the same data link connection.
// This object is managed by routines in LINK.C.
//

#if DBG
#define LREF_SPECIAL_CONN 0
#define LREF_SPECIAL_TEMP 1
#define LREF_CONNECTION 2
#define LREF_STOPPING 3
#define LREF_START_T1 4
#define LREF_TREE 5
#define LREF_NOT_ADM 6
#define LREF_NDIS_SEND 7

#define NUMBER_OF_LREFS 8
#endif

#if DBG
#define LINK_HISTORY_LENGTH 20
#endif

typedef struct _TP_LINK {

    RTL_SPLAY_LINKS SplayLinks;         // for the link splay tree
    CSHORT Type;                          // type of this structure
    USHORT Size;                          // size of this structure

#if DBG
    ULONG RefTypes[NUMBER_OF_LREFS];
#endif

    LIST_ENTRY Linkage;               // for list of free links or deferred
                                        // operation queue
    KSPIN_LOCK SpinLock;                // lock to manipulate this structure.

    LONG ReferenceCount;                // number of references to this object.
    LONG SpecialRefCount;               // controls freeing of the link.

    //
    // information about the remote hardware this link is talking to.
    //

    BOOLEAN Loopback;                   // TRUE if this is a loopback link.
    UCHAR LoopbackDestinationIndex;    // if Loopback, the index.

    HARDWARE_ADDRESS HardwareAddress;   // hardware address of remote.
    ULARGE_INTEGER MagicAddress;        // numerical representation of the
                                        // hardware address used for quick
                                        // comparisons
    UCHAR Header[MAX_MAC_HEADER_LENGTH]; // a place to stick a prebuilt packet
                                         // header.
    ULONG HeaderLength;                 // length of Header for this link

    //
    // Vital conditions surrounding the data link connnection.
    //

    ULONG MaxFrameSize;                 // maximum size of NetBIOS frame, MAC
                                        // dependent.

    //
    // Connections associated with this link. We keep a simple list of
    // connections because it's unlikely we'll get more than a few connections
    // on a given link (we're assuming that the server or redir will be the
    // biggest user of the net in the vast majority of environments). We've
    // made the link lookup be via a splay tree, which vastly speeds the
    // process of getting to the proper link; as long as there are only a few
    // connections, the connection lookup will be fast. If this becomes a
    // problem down the road, we can make this connection list be a splay tree
    // also.
    //

    LIST_ENTRY ConnectionDatabase;
    ULONG ActiveConnectionCount;        // # connections in above list.

    //
    // The following fields are used to maintain state about this link.
    // One other field is implicit-- the address of this object is the
    // ConnectionContext value as described in the PDI spec.
    //

    ULONG Flags;                        // attributes of the link.
    ULONG DeferredFlags;                // when on the deferred queue.
    ULONG State;                        // link state variable.

    //
    // Send-side state.
    //

    ULONG PacketsSent;                  // number of packets sent.
    ULONG PacketsResent;                // number of packets resent.
    UCHAR SendState;                    // send-side state variable.
    UCHAR NextSend;                     // next N(S) we should send.
    UCHAR LastAckReceived;              // last N(R) we received.
    UCHAR SendWindowSize;               // current send window size.
    UCHAR PrevWindowSize;               // size last time we dropped a frame.
    UCHAR WindowsUntilIncrease;         // how many windows until size increases.
    UCHAR SendRetries;                  // number of retries left/this checkpoint.
    UCHAR ConsecutiveLastPacketLost;    // consecutive windows with last packet dropped.
    ULONG NdisSendsInProgress;          // >0 if sends queued to NdisSendQueue.
    LIST_ENTRY NdisSendQueue;           // queue of sends to pass to NdisSend.
    LIST_ENTRY WackQ;                   // sent packets waiting LLC acks.

    BOOLEAN OnDeferredRrQueue;
    LIST_ENTRY DeferredRrLinkage;

    //
    // Receive-side state.
    //

    ULONG PacketsReceived;              // number of packets received.
    UCHAR ReceiveState;                 // receive-side state variable.
    UCHAR NextReceive;                  // next expected N(S) we should receive.
    UCHAR LastAckSent;                  // last N(R) we sent.
    UCHAR ReceiveWindowSize;            // current receive window size.
    BOOLEAN RespondToPoll;              // remote guy is polling-- we must final.
    BOOLEAN ResendingPackets;           // ResendLlcPackets in progress
    BOOLEAN LinkBusy;                   // received RNR (really send-side state).

    //
    // Timer, used to determine delay and throughput.
    //

    ULONG Delay;                        // an NT time, but only LowPart is saved.
    LARGE_INTEGER Throughput;

    //
    // These are counters needed by ADAPTER_STATUS queries.
    //

    USHORT FrmrsReceived;
    USHORT FrmrsTransmitted;
    USHORT ErrorIFramesReceived;
    USHORT ErrorIFramesTransmitted;
    USHORT AbortedTransmissions;
    USHORT BuffersNotAvailable;
    ULONG SuccessfulTransmits;
    ULONG SuccessfulReceives;
    USHORT T1Expirations;
    USHORT TiExpirations;

    //
    // Timeout state.  There is one kernel timer for this transport that is set
    // to go off at regular intervals.  This timer increments the current time,
    // which is then used to compare against the timer queues. The timer queues
    // are ordered, so whenever the first element is not expired, the rest of
    // the queue is not expired. This allows us to have hundreds of timers
    // running with very little system overhead.
    // A value of 0 indicates that the timer is not active.
    //

    ULONG T1;                           // retry timer.
    ULONG T2;                           // delayed ack timer.
    ULONG Ti;                           // inactivity timer.
    BOOLEAN OnShortList;                // TRUE if link is in ShortList
    BOOLEAN OnLongList;                 // TRUE if link is in LongList
    LIST_ENTRY ShortList;               // list of links waiting t1 or t2
    LIST_ENTRY LongList;                // list of links waiting ti

    LIST_ENTRY PurgeList;

    //
    // This counter is used to keep track of whether there are
    // any "connectors" (connections initiated by this side) on
    // this link. If there are none, and we are on an easily
    // disconnected link, then we handle the inactivity timeout
    // differently.
    //

    LONG NumberOfConnectors;

    //
    // BaseT1Timeout is the current T1 timeout computed based on
    // the response to previous poll frames. T1Timeout is the
    // value to be used for the next T1, and will generally be
    // based on BaseT1Timeout but may be more if T1 is backing
    // off. T2Timeout and TiTimeout are independent of these.
    //

    ULONG BaseT1Timeout;                // Timeout value for T1, << 16.
    ULONG CurrentT1Timeout;             // Current backed-off T1 timeout.
    ULONG MinimumBaseT1Timeout;         // Minimum value, based on link speed.
    ULONG BaseT1RecalcThreshhold;       // Only recalc BaseT1 on frames > this.
    ULONG CurrentPollRetransmits;       // Current retransmits waiting for final.
    BOOLEAN ThroughputAccurate;         // Is the throughput on this link accurate?
    BOOLEAN CurrentT1Backoff;           // the last poll frame had retransmits
    BOOLEAN CurrentPollOutstanding;     // Check that we have a poll outstanding.
    LARGE_INTEGER CurrentTimerStart;    // Time that current timing was begun.
    ULONG CurrentPollSize;              // Size of current poll packet.
    ULONG T2Timeout;                    // Timeout value for T2.
    ULONG TiTimeout;                    // Timeout value for Ti.
    ULONG LlcRetries;                   // total retry count for this link.
    ULONG MaxWindowSize;                // maximum send window size.
    ULONG TiStartPacketsReceived;       // PacketsReceived when Ti was started.

    //
    // Adaptive window algorithm state.
    //

    ULONG WindowErrors;                 // # retransmissions/this adaptive run.
    UCHAR BestWindowSize;               // our best window from experience.
    UCHAR WorstWindowSize;              // our worst window from experience.

    //
    // Keep track of remotes that never poll so we can send
    // an RR every two frames.
    //

    BOOLEAN RemoteNoPoll;               // We think remote doesn't poll
    UCHAR ConsecutiveIFrames;           // number received since polling

#if DBG
    UCHAR CreatePacketFailures;         // consecutive failures
#endif

    LIST_ENTRY DeferredList;            // for threading on deferred list

    struct _DEVICE_CONTEXT *Provider;
    PKSPIN_LOCK ProviderInterlock;      // &Provider->Interlock

#if DBG
  LIST_ENTRY GlobalLinkage;
  ULONG TotalReferences;
  ULONG TotalDereferences;
  ULONG NextRefLoc;
  struct {
     PVOID Caller;
     PVOID CallersCaller;
  } History[LINK_HISTORY_LENGTH];
  BOOLEAN Destroyed;
#endif

} TP_LINK, *PTP_LINK;

#if DBG
extern KSPIN_LOCK NbfGlobalHistoryLock;
extern LIST_ENTRY NbfGlobalLinkList;
#define StoreLinkHistory(_link,_ref) {                                      \
    KIRQL oldIrql;                                                          \
    KeAcquireSpinLock (&NbfGlobalHistoryLock, &oldIrql);                    \
    if ((_link)->Destroyed) {                                               \
        DbgPrint ("link touched after being destroyed 0x%lx\n", (_link));   \
        DbgBreakPoint();                                                    \
    }                                                                       \
    RtlGetCallersAddress(                                                   \
        &(_link)->History[(_link)->NextRefLoc].Caller,                      \
        &(_link)->History[(_link)->NextRefLoc].CallersCaller                \
        );                                                                  \
    if ((_ref)) {                                                           \
        (_link)->TotalReferences++;                                         \
    } else {                                                                \
        (_link)->TotalDereferences++;                                       \
        (_link)->History[(_link)->NextRefLoc].Caller =                      \
            (PVOID)((ULONG)(_link)->History[(_link)->NextRefLoc].Caller &   \
                                                            ~0x80000000);   \
    }                                                                       \
    if (++(_link)->NextRefLoc == LINK_HISTORY_LENGTH) {                     \
        (_link)->NextRefLoc = 0;                                            \
    }                                                                       \
    KeReleaseSpinLock (&NbfGlobalHistoryLock, oldIrql);                     \
}
#endif

#define LINK_FLAGS_JUMP_START       0x00000040 // run adaptive alg/every sent window.
#define LINK_FLAGS_LOCAL_DISC       0x00000080 // link was stopped locally.

//
// deferred flags, used for processing at timer tick if needed
//

#define LINK_FLAGS_DEFERRED_DELETE  0x00010000  // delete at next opportunity
#define LINK_FLAGS_DEFERRED_ADD     0x00020000  // add to splay tree, next opportunity
#define LINK_FLAGS_DEFERRED_MASK    0x00030000  // (LINK_FLAGS_DEFERRED_DELETE | LINK_FLAGS_DEFERRED_ADD)

#define LINK_STATE_ADM          1       // asynchronous disconnected mode.
#define LINK_STATE_READY        2       // asynchronous balanced mode extended.
#define LINK_STATE_BUSY         3       // all link buffers are busy, sent RNR
#define LINK_STATE_CONNECTING   4       // waiting SABME response (UA-r/f).
#define LINK_STATE_W_POLL       5       // waiting initial checkpoint.
#define LINK_STATE_W_FINAL      6       // waiting final from initial checkpoint.
#define LINK_STATE_W_DISC_RSP   7       // waiting disconnect response.

#define SEND_STATE_DOWN         0       // asynchronous disconnected mode.
#define SEND_STATE_READY        1       // completely ready to send.
#define SEND_STATE_REJECTING    2       // other guy is rejecting.
#define SEND_STATE_CHECKPOINTING 3      // we're checkpointing (can't send data).

#define RECEIVE_STATE_DOWN      0       // asynchronous disconnected mode.
#define RECEIVE_STATE_READY     1       // we're ready to receive.
#define RECEIVE_STATE_REJECTING 2       // we're rejecting.


//
// This structure defines the DEVICE_OBJECT and its extension allocated at
// the time the transport provider creates its device object.
//

#if DBG
#define DCREF_CREATION    0
#define DCREF_ADDRESS     1
#define DCREF_CONNECTION  2
#define DCREF_LINK        3
#define DCREF_QUERY_INFO  4
#define DCREF_SCAN_TIMER  5
#define DCREF_REQUEST     6

#define NUMBER_OF_DCREFS 8
#endif


typedef struct _NBF_POOL_LIST_DESC {
    NDIS_HANDLE PoolHandle;
    USHORT   NumElements;
    USHORT   TotalElements;
    struct _NBF_POOL_LIST_DESC *Next;
} NBF_POOL_LIST_DESC, *PNBF_POOL_LIST_DESC;

typedef struct _DEVICE_CONTEXT {

    DEVICE_OBJECT DeviceObject;         // the I/O system's device object.

#if DBG
    ULONG RefTypes[NUMBER_OF_DCREFS];
#endif

    CSHORT Type;                          // type of this structure
    USHORT Size;                          // size of this structure

    LIST_ENTRY Linkage;                   // links them on NbfDeviceList;

    KSPIN_LOCK Interlock;               // GLOBAL spinlock for reference count.
                                        //  (used in ExInterlockedXxx calls)
    LONG ReferenceCount;                // activity count/this provider.


    //
    // This protects the LoopbackQueue.
    //

    KSPIN_LOCK LoopbackSpinLock;

    //
    // The queue of packets waiting to be looped back.
    //

    LIST_ENTRY LoopbackQueue;

    //
    // These two links are used for loopback.
    //

    PTP_LINK LoopbackLinks[2];

    //
    // This buffer is used for loopback indications; a
    // contiguous piece is copied into it. It is allocated
    // (of size NBF_MAX_LOOPBACK_LOOKAHEAD) when one of
    // the LoopbackLinks become non-NULL.
    //

    PUCHAR LookaheadContiguous;

    //
    // This holds the length of the header in the currently
    // indicating loopback packet.
    //

    ULONG LoopbackHeaderLength;

    //
    // Used for processing the loopback queue.
    //

    KDPC LoopbackDpc;

    //
    // Determines if a LoopbackDpc is in progress.
    //

    BOOLEAN LoopbackInProgress;

    //
    // Determines if a WanDelayedDpc is in progress.
    //

    BOOLEAN WanThreadQueued;

    //
    // Used for momentarily delaying WAN packetizing to
    // allow RR's to be received.
    //

    WORK_QUEUE_ITEM WanDelayedQueueItem;

    //
    // The queue of FIND.NAME requests waiting to be processed.
    //

    LIST_ENTRY FindNameQueue;

    //
    // The queue of STATUS.QUERY requests waiting to be processed.
    //

    LIST_ENTRY StatusQueryQueue;

    //
    // The queue of QUERY.INDICATION requests waiting to be completed.
    //

    LIST_ENTRY QueryIndicationQueue;

    //
    // The queue of DATAGRAM.INDICATION requests waiting to be completed.
    //

    LIST_ENTRY DatagramIndicationQueue;

    //
    // The queue of (currently receive only) IRPs waiting to complete.
    //

    LIST_ENTRY IrpCompletionQueue;

    //
    // This boolean is TRUE if either of the above two have ever
    // had anything on them.
    //

    BOOLEAN IndicationQueuesInUse;

    //
    // Following are protected by Global Device Context SpinLock
    //

    KSPIN_LOCK SpinLock;                // lock to manipulate this object.
                                        //  (used in KeAcquireSpinLock calls)

    //
    // the device context state, among open, closing
    //

    UCHAR State;

    //
    // Used when processing a STATUS_CLOSING indication.
    //

    WORK_QUEUE_ITEM StatusClosingQueueItem;

    //
    // The following queue holds free TP_LINK objects available for allocation.
    //

    LIST_ENTRY LinkPool;

    //
    // These counters keep track of resources uses by TP_LINK objects.
    //

    ULONG LinkAllocated;
    ULONG LinkInitAllocated;
    ULONG LinkMaxAllocated;
    ULONG LinkInUse;
    ULONG LinkMaxInUse;
    ULONG LinkExhausted;
    ULONG LinkTotal;
    ULONG LinkSamples;


    //
    // The following queue holds free TP_ADDRESS objects available for allocation.
    //

    LIST_ENTRY AddressPool;

    //
    // These counters keep track of resources uses by TP_ADDRESS objects.
    //

    ULONG AddressAllocated;
    ULONG AddressInitAllocated;
    ULONG AddressMaxAllocated;
    ULONG AddressInUse;
    ULONG AddressMaxInUse;
    ULONG AddressExhausted;
    ULONG AddressTotal;
    ULONG AddressSamples;


    //
    // The following queue holds free TP_ADDRESS_FILE objects available for allocation.
    //

    LIST_ENTRY AddressFilePool;

    //
    // These counters keep track of resources uses by TP_ADDRESS_FILE objects.
    //

    ULONG AddressFileAllocated;
    ULONG AddressFileInitAllocated;
    ULONG AddressFileMaxAllocated;
    ULONG AddressFileInUse;
    ULONG AddressFileMaxInUse;
    ULONG AddressFileExhausted;
    ULONG AddressFileTotal;
    ULONG AddressFileSamples;


    //
    // The following queue holds free TP_CONNECTION objects available for allocation.
    //

    LIST_ENTRY ConnectionPool;

    //
    // These counters keep track of resources uses by TP_CONNECTION objects.
    //

    ULONG ConnectionAllocated;
    ULONG ConnectionInitAllocated;
    ULONG ConnectionMaxAllocated;
    ULONG ConnectionInUse;
    ULONG ConnectionMaxInUse;
    ULONG ConnectionExhausted;
    ULONG ConnectionTotal;
    ULONG ConnectionSamples;


    //
    // The following is a free list of TP_REQUEST blocks which have been
    // previously allocated and are available for use.
    //

    LIST_ENTRY RequestPool;             // free request block pool.

    //
    // These counters keep track of resources uses by TP_REQUEST objects.
    //

    ULONG RequestAllocated;
    ULONG RequestInitAllocated;
    ULONG RequestMaxAllocated;
    ULONG RequestInUse;
    ULONG RequestMaxInUse;
    ULONG RequestExhausted;
    ULONG RequestTotal;
    ULONG RequestSamples;


    //
    // The following list comprises a pool of UI NetBIOS frame headers
    // that are manipulated by the routines in FRAMESND.C.
    //

    LIST_ENTRY UIFramePool;             // free UI frames (TP_UI_FRAME objects).

    //
    // These counters keep track of resources uses by TP_UI_FRAME objects.
    //

    ULONG UIFrameLength;
    ULONG UIFrameHeaderLength;
    ULONG UIFrameAllocated;
    ULONG UIFrameInitAllocated;
    ULONG UIFrameExhausted;


    //
    // The following queue holds I-frame Send packets managed by PACKET.C.
    //

    SINGLE_LIST_ENTRY PacketPool;

    //
    // These counters keep track of resources uses by TP_PACKET objects.
    //

    ULONG PacketLength;
    ULONG PacketHeaderLength;
    ULONG PacketAllocated;
    ULONG PacketInitAllocated;
    ULONG PacketExhausted;


    //
    // The following queue holds RR-frame Send packets managed by PACKET.C.
    //

    SINGLE_LIST_ENTRY RrPacketPool;


    //
    // The following queue contains Receive packets
    //

    SINGLE_LIST_ENTRY ReceivePacketPool;

    //
    // These counters keep track of resources uses by NDIS_PACKET objects.
    //

    ULONG ReceivePacketAllocated;
    ULONG ReceivePacketInitAllocated;
    ULONG ReceivePacketExhausted;


    //
    // This queue contains pre-allocated receive buffers
    //

    SINGLE_LIST_ENTRY ReceiveBufferPool;

    //
    // These counters keep track of resources uses by TP_PACKET objects.
    //

    ULONG ReceiveBufferLength;
    ULONG ReceiveBufferAllocated;
    ULONG ReceiveBufferInitAllocated;
    ULONG ReceiveBufferExhausted;


    //
    // This holds the total memory allocated for the above structures.
    //

    ULONG MemoryUsage;
    ULONG MemoryLimit;


    //
    // The following field is a head of a list of TP_ADDRESS objects that
    // are defined for this transport provider.  To edit the list, you must
    // hold the spinlock of the device context object.
    //

    LIST_ENTRY AddressDatabase;        // list of defined transport addresses.

    //
    // The following field is the pointer to the root of the splay tree of
    // links that are associated with this Device Context. You must hold the
    // LinkSpinLock to modify this list. You must set the LinkTreeSemaphore
    // to traverse this list without modifying it. Note that all modify
    // operations are deferred to timer(DPC)-time operations.
    //

    KSPIN_LOCK LinkSpinLock;            // protects these values
    PTP_LINK LastLink;                  // the last link found in the tree.
    PRTL_SPLAY_LINKS LinkTreeRoot;      // pointer to root of the tree.
    ULONG LinkTreeElements;             // how many elements in the tree
    LIST_ENTRY LinkDeferred;            // Deferred operations on links.
    ULONG DeferredNotSatisfied;         // how many times we've come to the
                                        // deferred well and not gotten it clear.

    //
    // The following queue holds connections which are waiting on available
    // packets.  As each new packet becomes available, a connection is removed
    // from this queue and placed on the PacketizeQueue.
    //

    LIST_ENTRY PacketWaitQueue;         // queue of packet-starved connections.
    LIST_ENTRY PacketizeQueue;          // queue of ready-to-packetize connections.

    //
    // The following queue holds connections which are waiting to send
    // a piggyback ack. In that case the CONNECTION_FLAGS_DEFERRED_ACK
    // bit in DeferredFlags will be set.
    //

    LIST_ENTRY DataAckQueue;

    //
    // The following queue holds links which are waiting to send an
    // RR frame because the remote they are talking to never polls.
    //

    LIST_ENTRY DeferredRrQueue;

    //
    // Used to track when the queue has changed.
    //

    BOOLEAN DataAckQueueChanged;

    //
    // When this hits thirty seconds we checked for stalled connections.
    //

    USHORT StalledConnectionCount;

    //
    // This queue contains receives that are in progress
    //

    LIST_ENTRY ReceiveInProgress;

    //
    // NDIS fields
    //

    //
    // following is used to keep adapter information.
    //

    NDIS_HANDLE NdisBindingHandle;

    //
    // The following fields are used for talking to NDIS. They keep information
    // for the NDIS wrapper to use when determining what pool to use for
    // allocating storage.
    //

    KSPIN_LOCK SendPoolListLock;            // protects these values
    PNBF_POOL_LIST_DESC SendPacketPoolDesc;
    KSPIN_LOCK RcvPoolListLock;            // protects these values
    PNBF_POOL_LIST_DESC ReceivePacketPoolDesc;
    NDIS_HANDLE NdisBufferPool;

    //
    // These are kept around for error logging.
    //

    ULONG SendPacketPoolSize;
    ULONG ReceivePacketPoolSize;
    ULONG MaxRequests;
    ULONG MaxLinks;
    ULONG MaxConnections;
    ULONG MaxAddressFiles;
    ULONG MaxAddresses;
    PWCHAR DeviceName;
    ULONG DeviceNameLength;

    //
    // This is the Mac type we must build the packet header for and know the
    // offsets for.
    //

    NBF_NDIS_IDENTIFICATION MacInfo;    // MAC type and other info
    ULONG MaxReceivePacketSize;         // does not include the MAC header
    ULONG MaxSendPacketSize;            // includes the MAC header
    ULONG CurSendPacketSize;            // may be smaller for async
    USHORT RecommendedSendWindow;       // used for Async lines
    BOOLEAN EasilyDisconnected;         // TRUE over wireless nets.

    //
    // some MAC addresses we use in the transport
    //

    HARDWARE_ADDRESS LocalAddress;      // our local hardware address.
    HARDWARE_ADDRESS NetBIOSAddress;    // NetBIOS functional address, used for TR

    //
    // The reserved Netbios address; consists of 10 zeroes
    // followed by LocalAddress;
    //

    UCHAR ReservedNetBIOSAddress[NETBIOS_NAME_LENGTH];
#ifdef _PNP_POWER
    HANDLE TdiDeviceHandle;
    HANDLE ReservedAddressHandle;
#endif

    //
    // These are used while initializing the MAC driver.
    //

    KEVENT NdisRequestEvent;            // used for pended requests.
    NDIS_STATUS NdisRequestStatus;      // records request status.

    //
    // This next field maintains a unique number which can next be assigned
    // as a connection identifier.  It is incremented by one each time a
    // value is allocated.
    //

    USHORT UniqueIdentifier;            // starts at 0, wraps around 2^16-1.

    //
    // This contains the next unique indentified to use as
    // the FsContext in the file object associated with an
    // open of the control channel.
    //

    USHORT ControlChannelIdentifier;

    //
    // The following fields are used to implement the lightweight timer
    // system in the protocol provider.  Each TP_LINK object in the device
    // context's LinkDatabase contains three lightweight timers that are
    // serviced by a DPC routine, which receives control by kernel functions.
    // There is one kernel timer for this transport that is set
    // to go off at regular intervals.  This timer increments the Absolute time,
    // which is then used to compare against the timer queues. The timer queues
    // are ordered, so whenever the first element is not expired, the rest of
    // the queue is not expired. This allows us to have hundreds of timers
    // running with very low system overhead.
    // A value of -1 indicates that the timer is not active.
    //

    LARGE_INTEGER ShortTimerStart;      // when the short timer was set.
    KDPC ShortTimerSystemDpc;           // kernel DPC object, short timer.
    KTIMER ShortSystemTimer;            // kernel timer object, short timer.
    ULONG ShortAbsoluteTime;            // up-count timer ticks, short timer.
    ULONG AdaptivePurge;                // absolute time of next purge (short timer).
    KDPC LongTimerSystemDpc;            // kernel DPC object, long timer.
    KTIMER LongSystemTimer;             // kernel timer object, long timer.
    ULONG LongAbsoluteTime;             // up-count timer ticks, long timer.
    union _DC_ACTIVE {
      struct _DC_INDIVIDUAL {
        BOOLEAN ShortListActive;        // ShortList is not empty.
        BOOLEAN DataAckQueueActive;     // DataAckQueue is not empty.
        BOOLEAN LinkDeferredActive;     // LinkDeferred is not empty.
      } i;
      ULONG AnyActive;                  // used to check all four at once.
    } a;
    BOOLEAN TimersInitialized;          // has the timer system been initialized.
    BOOLEAN ProcessingShortTimer;       // TRUE if we are in ScanShortTimer.
    KSPIN_LOCK TimerSpinLock;           // lock for following timer queues
    LIST_ENTRY ShortList;               // list of links waiting T1 or T2
    LIST_ENTRY LongList;                // list of links waiting Ti expire
    LIST_ENTRY PurgeList;               // list of links waiting LAT expire

    //
    // These fields are used on "easily disconnected" adapters.
    // Every time the long timer expires, it notes if there has
    // been any multicast traffic received. If there has not been,
    // it increments LongTimeoutsWithoutMulticast. Activity is
    // recorded by incrementing MulticastPacket when MC
    // packets are received, and zeroing it when the long timer
    // expires.
    //

    ULONG LongTimeoutsWithoutMulticast; // LongTimer timeouts since traffic.
    ULONG MulticastPacketCount;         // How many MC packets rcved, this timeout.

    //
    // This information is used to keep track of the speed of
    // the underlying medium.
    //

    ULONG MediumSpeed;                    // in units of 100 bytes/sec
    BOOLEAN MediumSpeedAccurate;          // if FALSE, can't use the link.

    //
    // This is TRUE if we are on a UP system.
    //

    BOOLEAN UniProcessor;

    //
    // Configuration information on how soon we should send
    // an unasked for RR with a non-polling remote.
    //

    UCHAR MaxConsecutiveIFrames;

    //
    // This is configuration information controlling the default
    // value of timers and retry counts.
    //

    ULONG DefaultT1Timeout;
    ULONG MinimumT1Timeout;
    ULONG DefaultT2Timeout;
    ULONG DefaultTiTimeout;
    ULONG LlcRetries;
    ULONG LlcMaxWindowSize;
    ULONG NameQueryRetries;
    ULONG NameQueryTimeout;
    ULONG AddNameQueryRetries;
    ULONG AddNameQueryTimeout;
    ULONG GeneralRetries;
    ULONG GeneralTimeout;
    ULONG MinimumSendWindowLimit;   // how low we can lock a connection's window

    //
    // Counters for most of the statistics that NBF maintains;
    // some of these are kept elsewhere. Including the structure
    // itself wastes a little space but ensures that the alignment
    // inside the structure is correct.
    //

    TDI_PROVIDER_STATISTICS Statistics;

    //
    // These are "temporary" versions of the other counters.
    // During normal operations we update these, then during
    // the short timer expiration we update the real ones.
    //

    ULONG TempIFrameBytesSent;
    ULONG TempIFramesSent;
    ULONG TempIFrameBytesReceived;
    ULONG TempIFramesReceived;

    //
    // Some counters needed for Netbios adapter status.
    //

    ULONG TiExpirations;
    ULONG FrmrReceived;
    ULONG FrmrTransmitted;

    //
    // These are used to compute AverageSendWindow.
    //

    ULONG SendWindowTotal;
    ULONG SendWindowSamples;

    //
    // Counters for "active" time.
    //

    LARGE_INTEGER NbfStartTime;

    //
    // This resource guards access to the ShareAccess
    // and SecurityDescriptor fields in addresses.
    //

    ERESOURCE AddressResource;

    //
    // This array is used to keep track of which LSNs are
    // available for use by Netbios sessions. LSNs can be
    // re-used for sessions to unique names if they are on
    // different links, but must be committed beforehand
    // for group names. The maximum value that can fit in
    // an array element is defined by LSN_TABLE_MAX.
    //

    UCHAR LsnTable[NETBIOS_SESSION_LIMIT+1];

    //
    // This is where we start looking in LsnTable for an
    // unused LSN. We cycle from 0-63 to prevent quick
    // down-and-up connections from getting funny data.
    //

    ULONG NextLsnStart;

    //
    // This array is used to quickly dismiss UI frames that
    // are not destined for us. The count is the number
    // of addresses with that first letter that are registered
    // on this device.
    //

    UCHAR AddressCounts[256];

    //
    // The following structure contains statistics counters for use
    // by TdiQueryInformation and TdiSetInformation.  They should not
    // be used for maintenance of internal data structures.
    //

    TDI_PROVIDER_INFO Information;      // information about this provider.

    PTP_VARIABLE NetmanVariables;       // list of network managable variables.

    //
    // The magic bullet is a packet that is sent under certain debugging
    // conditions. This allows the transport to signal packet capture devices
    // that a particular condiion has been met. This packet has the current
    // devicecontext as the source, and 0x04 in every other byte of the packet.
    //

    UCHAR MagicBullet[32];              //

} DEVICE_CONTEXT, *PDEVICE_CONTEXT;

//
// device context state definitions
//

#define DEVICECONTEXT_STATE_OPENING  0x00
#define DEVICECONTEXT_STATE_OPEN     0x01
#define DEVICECONTEXT_STATE_DOWN     0x02
#define DEVICECONTEXT_STATE_STOPPING 0x03

//
// This is the maximum value that can go in an element
// of LsnTable (should be 0xff if they are UCHARs,
// 0xffff for USHORTs, etc.).
//

#define LSN_TABLE_MAX     0xff


#define MAGIC_BULLET_FOOD 0x04


//
// These are constants for the LoopbackLinks elements.
// The distinctions are arbitrary; the listener link
// is the one established from ProcessNameQuery, and
// the connector link is the one established from
// ProcessNameRecognized.
//

#define LISTENER_LINK                0
#define CONNECTOR_LINK               1


//
// This structure defines the packet object, used to represent a DLC I-frame
// in some portion of its lifetime.  The PACKET.C module contains routines
// to manage this object.
//

typedef struct _TP_PACKET {
    CSHORT Type;                          // type of this structure
    USHORT Size;                          // size of this structure
    PNDIS_PACKET NdisPacket;            // ptr to owning Ndis Packet
    ULONG NdisIFrameLength;             // Length of NdisPacket

    LIST_ENTRY Linkage;                 // used to chain packets together.
    LONG ReferenceCount;                // activity count/this packet.
    BOOLEAN PacketSent;                 // packet completed by NDIS.
    BOOLEAN PacketNoNdisBuffer;         // chain on this packet was not allocated.

    UCHAR Action;                      // what to do when we're acked.
    BOOLEAN PacketizeConnection;       // restart packetizing when completed.

    PVOID Owner;                        // ptr to owning connection or IrpSp.
    PTP_LINK Link;                      // ptr to link it was sent on.
    PDEVICE_CONTEXT Provider;           // The owner of this packet.
    PKSPIN_LOCK ProviderInterlock;      // &Provider->Interlock.

    UCHAR Header[1];                    // the MAC, DLC, and NBF headers

} TP_PACKET, *PTP_PACKET;


//
// The following values are placed in the Action field in the TP_PACKET
// object to indicate what action, if any, should be taken when the packet
// is destroyed.
//

#define PACKET_ACTION_NULL        0     // no special action should be taken.
#define PACKET_ACTION_IRP_SP      1     // Owner is an IRP_SP, deref when done.
#define PACKET_ACTION_CONNECTION  2     // Owner is a TP_CONNECTION, deref when done.
#define PACKET_ACTION_END         3     // shutdown session (sent SESSION_END).
#define PACKET_ACTION_RR          5     // packet is an RR, put back in RR pool.

//
// Types used to hold information in the send and receive NDIS packets
//

typedef struct _SEND_PACKET_TAG {
    LIST_ENTRY Linkage;         // used for threading on loopback queue
    BOOLEAN OnLoopbackQueue;    // TRUE if the packet is on a loopback queue
    UCHAR LoopbackLinkIndex;    // index of other link for loopback packets
    USHORT Type;                // identifier for packet type
    PVOID Frame;                // backpointer to owning NBF structure
    PVOID Owner;                // backpointer for owning nbf construct
                                //  (like address, devicecontext, etc)
    } SEND_PACKET_TAG, *PSEND_PACKET_TAG;

//
// Packet types used in send completion
//

#define TYPE_I_FRAME        1
#define TYPE_UI_FRAME       2
#define TYPE_ADDRESS_FRAME 3

//
// LoopbackLinkIndex values.
//

#define LOOPBACK_TO_LISTENER    0
#define LOOPBACK_TO_CONNECTOR   1
#define LOOPBACK_UI_FRAME       2

//
// receive packet used to hold information about this receive
//

typedef struct _RECEIVE_PACKET_TAG {
    SINGLE_LIST_ENTRY Linkage;  // used for threading in pool
    PTP_CONNECTION Connection;  // connection this receive is occuring on
    ULONG BytesToTransfer;      // for I-frame, bytes in this transfer
    UCHAR PacketType;           // the type of packet we're processing
    BOOLEAN AllocatedNdisBuffer; // did we allocate our own NDIS_BUFFERs
    BOOLEAN EndOfMessage;       // does this receive complete the message
    BOOLEAN CompleteReceive;    // complete the receive after TransferData?
    BOOLEAN TransferDataPended; // TRUE if TransferData returned PENDING
    } RECEIVE_PACKET_TAG, *PRECEIVE_PACKET_TAG;

#define TYPE_AT_INDICATE     1
#define TYPE_AT_COMPLETE     2
#define TYPE_STATUS_RESPONSE 3

//
// receive buffer descriptor (built in memory at the beginning of the buffer)
//

typedef struct _BUFFER_TAG {
    LIST_ENTRY Linkage;         // thread in pool and on receive queue
    NDIS_STATUS NdisStatus;     // completion status for send
    PTP_ADDRESS Address;        // the address this datagram is for.
    PNDIS_BUFFER NdisBuffer;    // describes the rest of the buffer
    ULONG Length;               // the length of the buffer
    UCHAR Buffer[1];            // the actual storage (accessed through the NDIS_BUFFER)
    } BUFFER_TAG, *PBUFFER_TAG;

#endif // def _NBFTYPES_