B.8.4 Using Paired NetBIOS Providers

A NetBIOS provider must closely couple its connection-oriented services with its connectionless services. However, through TPI, a STREAMS stack must declare itself as either a connection-oriented (T_COTS) or a connectionless (T_CLTS) provider. Therefore a STREAMS NetBIOS provider has to be implemented via two drivers: a T_COTS driver and a T_CTLS driver. For example, NetBIOS over TCP/IP is provided by the following STREAMS drivers:

    \Device\Streams\nbt

    \Device\Streams\nbdg

Example: DriverEntry Routine for nbt.sys

#include <ntddk.h>
#include <tdi.h>
#include <stream.h>
#include <xti.h>
 
**********************
extern struct streamtab nbtinfo, nbdginfo;
 
static struct nbaddr BroadcastName = {
    NBBROADCAST | NBGROUPNM,
    "*"
};
 
static STREAMS_TDI_ADDRESS_INFO AddressInfo = {
    sizeof(BroadcastName),                  // Broadcast address length
    TDI_ADDRESS_TYPE_NETBIOS,               // TDI address type
    TRUE,                                   // Directed message goes farther
                                            // than broadcast or multicast
    &BroadcastName                          // Broadcast address
};
 

STREAMS_TDI_INFO NbtTdiInfo = {
    T_COTS_ORD,                             // SERV_type
    &nbdginfo,                              // Partner streamtab
    T_CLTS,                                 // Partner SERV_type
    0,                                      // Option length
    NULL,                                   // Option pointer
    TRUE,                                   // Reuseaddr set by default
    1,                                      // One address info structure
    &AddressInfo                            // AddressInfo
};
 
STREAMS_TDI_INFO NbdgTdiInfo = {
    T_CLTS,                                 // SERV_type
    &nbtinfo,                               // Partner streamtab
    T_COTS_ORD,                             // Partner SERV_type
    0,                                      // Option length
    NULL,                                   // Option pointer
    TRUE,                                   // Reuseaddr set by default
    1,                                      // One address info structure
    &AddressInfo                            // AddressInfo
};
 

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT driver,
    PUNICODE_STRING description
    )
{
    NTSTATUS status;
 
    status = ExtractRegistry();
 
    if (status != STATUS_SUCCESS) {
        return(status);
    }
 
    if (nbtinit()) {
        return(STATUS_NO_MEMORY);
    }
 
    status = StrmRegisterDriver(driver, &nbtinfo, NULL, &NbtTdiInfo);
 
    if (status != STATUS_SUCCESS) {
        return(status);
    }
    status = StrmRegisterDriver(driver, &nbdginfo, NULL, &NbdgTdiInfo);
 
    if (status != STATUS_SUCCESS) {
        return(status);
    }
 
    return(status);
 
}