< Another NetBIOS Example | Winsock2 Supported Protocols Main | NetBIOS Client Example >


 

 

Winsock 2: Other Supported Protocols 4 Part 5

 

 

What do we have in this chapter 4 part 5?

  1. Finding the NetBIOS Name Example

  2. The NetBIOS Client-Server Program Example

  3. The NetBIOS Server

 

Finding the NetBIOS Name Example

 

Create a new empty Win32 console mode application and add the project/solution name.

 

 

Add the following source code.

 

// Description:

//    This sample performs an NCBFINDNAME to discover whether a given

//    NetBIOS name is in use on the network. This NetBIOS command is

//    specific to NT 4 and greater.

//

// Command Line Options:

//    NetbiosFindname NAME [16th-BYTE]

//

//    NAME    - NetBIOS name to find

//    16-BYTE - Integer value of 16th byte of NetBIOS (in case its

//              non-printable

//

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include "nbcommon.h"

 

#define MAX_SESSIONS   254

#define MAX_NAMES         254

 

// Each response will return a FIND_NAME_HEADER followed by

// a FIND_NAME_BUFFER

typedef struct _FIND_NAME_STRUCT {

    FIND_NAME_HEADER  header;

    FIND_NAME_BUFFER   buffers[254];

} FIND_NAME_STRUCT;

 

// Function: PrintFindNameHeader

// Description:

//    Print out the characteristics of the NetBIOS name (i.e whether

//    it is a group name or unique name) 

void PrintFindNameHeader(FIND_NAME_HEADER *header)

{

    if (header->unique_group == 0)

            printf("\t         Name Type: UNIQUE\n");

    else if (header->unique_group == 1)

            printf("\t         Name Type: GROUP\n");

}

 

// Function: PrintFindNameBuffers

// Description:

//    This prints out the location of where the name is registered.

//    Because there is the possibility of more that one computer

//    registering the name there is an array.  Each FIND_NAME_BUFFER

//    returns the local hosts MAC address as well as the MAC address

//    that has the name registered. Also, per Q137916, performing

//    an NCBFINDNAME on LANAs that correspond to TCP/IP returns

//    unexpected results (i.e. bogus MAC addresses).

void PrintFindNameBuffers(FIND_NAME_BUFFER *buffers, WORD count)

{

    WORD        i;

 

    for(i=0; i < count ;i++)

    {

        printf("\t       MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",

                buffers[i].destination_addr[0],

                buffers[i].destination_addr[1],

                buffers[i].destination_addr[2],

                buffers[i].destination_addr[3],

                buffers[i].destination_addr[4],

                buffers[i].destination_addr[5]);

                printf("\tName registered at: %02X:%02X:%02X:%02X:%02X:%02X\n\n",

                buffers[i].source_addr[0],

                buffers[i].source_addr[1],

                buffers[i].source_addr[2],

                buffers[i].source_addr[3],

                buffers[i].source_addr[4],

                buffers[i].source_addr[5]);

    }

}

 

// Function: FindName

// Description:

//    This performs the actual find name command.  The last byte is a

//    separate integer parameter as you can't specify special characters

//    as arguments to the command line.

int FindName(int lana, char *name, int lastbyte)

{

    NCB            ncb;

    FIND_NAME_STRUCT    namestruct;

 

    ZeroMemory(&ncb, sizeof(NCB));

    ncb.ncb_command = NCBFINDNAME;

    ncb.ncb_lana_num = lana;

    ncb.ncb_buffer = (PUCHAR)&namestruct;

    ncb.ncb_length = sizeof(FIND_NAME_STRUCT);

 

    memset(ncb.ncb_callname, ' ', NCBNAMSZ);

    strncpy_s(ncb.ncb_callname, sizeof(ncb.ncb_callname),name, strlen(name));

 

    ncb.ncb_callname[NCBNAMSZ-1] = lastbyte;

 

    if (Netbios(&ncb) != NRC_GOODRET)

    {

           printf("Netbios: NCBFINDNAME failed with error code %d\n", ncb.ncb_retcode);

           return ncb.ncb_retcode;

    }

    else

          printf("Netbios: NCBFINDNAME command is OK!\n");

 

     PrintFindNameHeader(&namestruct.header);

     if (namestruct.header.node_count > 0)

          PrintFindNameBuffers(namestruct.buffers, namestruct.header.node_count);

     else

          printf("Name not registered on network!\n");

 

    return NRC_GOODRET;

}

 

// Function: main

// Description:

//    Initialize the NetBIOS interface, parse the arguments, and issue

//    the find name command. Upon return print the name information.

int main(int argc, char **argv)

{

    LANA_ENUM        lenum;

    char        szFindName[NCBNAMSZ+1];

    int         i, iLastChar=(int)' ';

    DWORD       dwNum;

 

    // Check usage parameters, enumerate LANAs, and reset them

    if ((argc != 2) && (argc != 3))

    {

            printf("Usage: %s NAME\n", argv[0]);

            return 0;

    }

    if (argc == 3)

        iLastChar = atoi(argv[2]);

    if (LanaEnum(&lenum) != NRC_GOODRET)

            return 0;

    if (ResetAll(&lenum, (UCHAR)MAX_SESSIONS, (UCHAR)MAX_NAMES,

                FALSE) != NRC_GOODRET)

     return 0;

 

    // Format the supplied name to find so we can print it out as it should look

    memset(szFindName, ' ', NCBNAMSZ);

    strncpy_s(szFindName, sizeof(szFindName),argv[1], strlen(argv[1]));

    szFindName[NCBNAMSZ-1] = iLastChar;

    szFindName[NCBNAMSZ] = 0;

    FormatNetbiosName(szFindName, szFindName);

 

    // Add a name to each name table first..otherwise the FindName fails.

    for(i=0; i < lenum.length ;i++)

    {

        printf("LANA: %d Searching for name '%s'\n",

        lenum.lana[i], szFindName);

 

        AddName(lenum.lana[i], "FINDNAME-TEST", &dwNum);

        FindName(lenum.lana[i], argv[1], iLastChar);

    }

    return 1;

}

 

Copy the previously created nbcommon files (nbcommon.h and its definition, nbcommon.cpp) and then paste them into this project folder. By using the Add > Existing Item does not import those files (as in the .NET IDE).

 

NetBIOS program Example: copying the header and its definition files.

 

Next, Add > Existing Item for both files.

 

NetBIOS program Example: adding the header and its definition files to the existing project.

 

Take note that you can do the multiple select by holding the Shift key.

 

NetBIOS program Example: selecting the header and its definition files.

 

Those added files should be visible in the Solution Explorer.

 

NetBIOS program Example: the added header and its definition files seen in Solution explorer.

 

Don’t forget to link to the project to Netapi32.lib (for nb30.h). Then, build and run the program.

 

NetBIOS program Example: A sample output

 

The Netbios Client-Server Program Example

 

The Netbios Server

 

This following sample illustrates creating a Winsock server using the AF_NETBIOS address family.  The server creates a listening socket for each LANA number of the given socket type. For datagrams, each listening socket waits for incoming data. For connection-oriented communication, the server waits for client connections at which point a thread is created to service the connection. The following examples try to demonstrate the Netbios client and server program. Create a new empty Win32 console mode application and add the project/solution name.

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, creating new project

 

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, adding an emtpy source file

 

Add the following code.

 

// Description:

//    This sample illustrates creating a Winsock server using

//    the AF_NETBIOS address family.  The server creates a listening

//    socket for each LANA number of the given socket type.

//    For datagrams, each listening socket waits for incoming data.

//For connection-oriented communication, the server waits

//    for client connections at which point a thread is created

//    to service the connection.

//

// Command Line Parameters/Options:  

//    NetbiosServer [-n str] [-p int] [-l int] [-t char] [-c int] [-b int]

//                                                          -n NAME        Our NetBIOS name

//                                                          -p PORT        The 16th byte qualifier of our name

//                                                          -l LANA        Specifies to listen on this LANA only

//                                                                                                 By default listen on all LANAs

//                                                          -t TYPE        Specifies datagram (d) or seqpacket (s)

//                                                          -c COUNT       Number of types to receive per client

//                                                          -b SIZE        Size of buffer to receive

// Link to ws2_32.lib

#include <winsock2.h>

#include <wsnetbs.h>

#include <stdio.h>

 

// A couple of common definitions used between client and server

// stored in custom made header file

#include "wsnbdef.h"

 

// Global variables for the name of our server and its 16th byte qualifier

char    szServerName[NETBIOS_NAME_LENGTH];   // Our NetBIOS name

int     iPort,                                                                          // Our 16th byte

iLana,                                                                                 // LANA to listen on

iSocketType=SOCK_SEQPACKET;                             // Socket type

DWORD   dwCount=DEFAULT_COUNT,                     // How many packets

dwSize = MAX_BUFFER;                                               // Receive buffer size

BOOL    bOneLana=FALSE;                                          // Listen on one lana only

 

// Function: usage

// Description: Print out usage information.

int usage()

{

    printf("Usage: NetbiosServer -n [str] -p [int] -l [int] -t [char] -c [int] -b [int]\n");

    printf("       -n NAME        Our NetBIOS name\n");

    printf("       -p PORT        The 16th byte qualifier of our name\n");

    printf("       -l LANA        Specifies to listen on this LANA only\n");

    printf("                       By default listen on all LANAs\n");

    printf("       -t TYPE        Specifies datagram (d) or seqpacket (s)\n");

    printf("       -c COUNT       Number of types to receive per client\n");

    printf("       -b SIZE        Size of buffer to receive (make sure it is big enough!)\n");

    printf("Example: NetbiosServer -n MIKEBLUR -p 7172 -l 3 -t s -c 5 -b 64\n");

    printf("\n");

    return 0;

 }

 

// Function: ValidateArgs

// Description

//    Parse the argument list for our NetBIOS name and whether

//    we want to operate on all LANAs or just one

int ValidateArgs(int argc, char **argv)

{

   int i;

 

   printf("Argument(s) supplied...\n");

   if (argc > 1)

   {

       for (i = 1; i < argc; i++)

       {

           if ( (argv[i][0] == '-') || (argv[i][0] == '/')  )

            {

                switch (tolower(argv[i][1]) )

               {

               case '?':

                   usage();

                   break;

                case 'n':   // use a unique name

                    if (i+1 < argc)

                    {

                         strncpy_s(szServerName, sizeof(szServerName), argv[i+1],NETBIOS_NAME_LENGTH);

                         if (0 != strlen(szServerName))

                                    ++i;

                    }

                   break;

                                                case 'p':   // set the 16th byte

                    if (i+1 < argc)

                   {

                      iPort = atoi(argv[i+1]);

                       ++i;

                    }

                   break;

                                                case 'l':   // listen on one lana only

                   if (i+1 < argc)

                   {

                       bOneLana = TRUE;

                       iLana = atoi(argv[i+1]);

                      ++i;

                   }

                  break;

                                                case 't':   // datagram or stream socket?

                   if (i+1 < argc)

                   {

                       if ('s' == tolower(argv[i+1][0]))

                                                                           iSocketType = SOCK_SEQPACKET;

                       else if ('d' == tolower(argv[i+1][0]))

                           iSocketType = SOCK_DGRAM;

                       else

                           usage();

                      ++i;

                   }

                   break;

                case 'c':   // number of messages to send

                  if (i+1 < argc)

                   {

                       dwCount = atol(argv[i+1]);

                       ++i;

                   }

                   break;

                case 'b':   // size of send buffer

                   if (i+1 < argc)

                   {

                       dwSize = (atol(argv[i+1]) > MAX_BUFFER ? MAX_BUFFER : atol(argv[i+1]));

                       ++i;

                   }

                   break;

                default:

                  usage();

                   break;

                                }

                           }

                        }

   }

   return 0;  

}

 

// Function: ClientThread

// Description:

//    This thread is spawned for each incoming client connection to

//    handle the echo server responsibilities

DWORD WINAPI ClientThread(LPVOID lpParam)

{

    SOCKET        sock = (SOCKET)lpParam;

    char          szRecvBuff[MAX_BUFFER];

    DWORD         dwRet, dwErr;

    unsigned long iOptVal = 1L;

 

    // Make the client connection non-blocking  

    if(ioctlsocket(sock, FIONBIO, &iOptVal) == SOCKET_ERROR)

    {

       printf("ioctlsocket(FIONBIO) failed with error code %d\n", WSAGetLastError());

       return 1;

    }

    else

       printf("ioctlsocket(FIONBIO) is OK!\n");

 

   // In a loop read and write the data from and to the client

   while (1)

   {

       dwRet = recv(sock, szRecvBuff, MAX_BUFFER, 0);

       if (dwRet == 0)

       {

           printf("recv() with graceful close...\n");

           return 0;

       }

       else if (dwRet == SOCKET_ERROR)

       {

            // If we get a WSAEWOULDBLOCK just keep going

            if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)

               continue;

            else if (dwErr == WSAECONNRESET)

            {

                     printf("Client aborted the connection...\n");

                     return 0;

            }

            else

            {

                      printf("recv() failed with error code %d\n", dwErr);

                      return 1;

             }

         }

               szRecvBuff[dwRet] = 0;

               printf("Read %d bytes...\n", dwRet);

               printf("Received money: %s\n", szRecvBuff);

              

               while (1)

               {

                           dwRet = send(sock, szRecvBuff, dwRet, 0);

                           if (dwRet == SOCKET_ERROR)

                           {

                                       if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)

                                                   // Just continue

                                                   continue;

                                       else if (dwErr == WSAECONNRESET)

                                                   // Exit loop

                                                   break;

                                       printf("send() failed with error code %d\n", dwErr);

                                       return 1;

                           }

                           break;

               }

   }

   closesocket(sock);

   return 0;

}

 

// Function: main

// Description:

//    Parse the command line parameters, load the Winsock library,

//    enumerate the LANAs, and listen according to what is specified

//    by the command line. By default, a listen will be posted on

//    every available LANA. Once a client connection is made, spawn

//    a thread to handle that connection

int main(int argc, char **argv)

{

            WSADATA           wsd;

            HANDLE            hThread;

            DWORD             dwThreadId, dwNumProtocols, dwIndex, dwErr, i;

            int               iLastByte, addrlen = sizeof(SOCKADDR_NB), iEvents;

            WSAPROTOCOL_INFO *wsapi=NULL;

            SOCKET           *sockListen=NULL,     // array of listening sockets

                                        sockClient;

            WSAEVENT         *hEvents=NULL;      // one event for each LANA

            SOCKADDR_NB       nbaddr,               // our NetBIOS address

                                                  nbclient;              // client's NetBIOS address

            BOOL              bDone;

 

            // Parse command line and load Winsock library

            if(argc < 2)

            {

                        usage();

                        return 1;

            }

            else

            {

                        printf("Validating argument(s)...\n");

                        ValidateArgs(argc, argv);

                       

                        // These all just another verification for debugging purpose!

                        printf("iLana = %d\n", iLana);

                        printf("szServerName = %s\n", szServerName);

                        printf("iPort = %d\n", iPort);

                        printf("iSocketType = %d\n", iSocketType);

                        printf("dwCount = %d\n", dwCount);

                        printf("dwSize = %d\n", dwSize);

                        printf("\n");      }

 

            if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)

            {

                        printf("Unable to load Winsock! Error code is %ld\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSAStartup() is OK, Winsock lib loaded!\n");

 

            // If we are listening on all LANAs enumerate them  

           if (!bOneLana)

           {

               if (FindProtocol(&wsapi, &dwNumProtocols) != TRUE)

               {

                           printf("FindProtocol(): Unable to find correct protocol!\n");

                           // Just exit

                           return 1;

               }

               else

                           printf("FindProtocol(): Correct protocol found!\n");

 

               if (dwNumProtocols == 0)

               {

                           printf("FindProtocol(): No NetBIOS capable providers found!\n");

                           // Just exit

                           return 1;

               }

               else

                           printf("FindProtocol(): NetBIOS capable providers found!\n");

   }

   else

   {

               dwNumProtocols = 1;

   }

 

   SET_NETBIOS_SOCKADDR(&nbaddr, NETBIOS_UNIQUE_NAME, szServerName, iPort);

 

   // Allocate a SOCKET handle for each LANA we are going to listen on

   sockListen = (SOCKET *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(SOCKET) * dwNumProtocols);

   if (sockListen == NULL)

   {

               printf("Out of memory!\n");

               return 1;

   }

 

   // Allocate an event handle for each LANA we are going to listen on

   hEvents = (WSAEVENT *) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,sizeof(WSAEVENT) * dwNumProtocols);

   if (hEvents == NULL)

   {

               printf("Out of memory!\n");

               return 1;

   }

 

   // For each service provider create a ServerThread except for

   // the last provider which we'll start in this main thread

   for (i=0; i < dwNumProtocols ;i++)

   {

               if (!bOneLana)

                           printf("Transport: '%S'\n", wsapi[i].szProtocol);

               else

                           printf("Transport: LANA # is %d\n", iLana);

 

               hEvents[i] = WSACreateEvent();

               if (hEvents[i] == NULL)

               {

                           printf("WSACreateEvent() failed with error code %d\n", WSAGetLastError());

                           continue;

               }

 

               // Create socket(s)

               if (!bOneLana)

                           sockListen[i] = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,

                           FROM_PROTOCOL_INFO, &wsapi[i], 0, WSA_FLAG_OVERLAPPED);

               else

                           sockListen[i] = WSASocket(AF_NETBIOS, SOCK_SEQPACKET, -iLana, NULL, 0, WSA_FLAG_OVERLAPPED);

               if (sockListen[i] == SOCKET_ERROR)

               {

                           printf("WSASocket() failed with error code %d\n", WSAGetLastError());

                           continue;

               }

 

               // Bind and listen each socket to our server name

               if (bind(sockListen[i], (SOCKADDR *)&nbaddr, sizeof(nbaddr)) == SOCKET_ERROR)

               {

                           printf("bind() failed: %d\n", WSAGetLastError());

                           return 1;

               }

               else

                           printf("bind() looks OK!\n");

 

               listen(sockListen[i], 10);

               printf("listen() also seems fine, so I\'m listening...\n");

 

               // We're only interested in FD_ACCEPT events for our server sockets

               if (iSocketType == SOCK_SEQPACKET)

                           iEvents = FD_ACCEPT;

               else

                           iEvents = FD_READ;

 

               if (WSAEventSelect(sockListen[i], hEvents[i], iEvents) == SOCKET_ERROR)

               {

                           printf("WSAEventSelect() failed with error code %d\n", WSAGetLastError());

                           return 1;

               }

               else

                           printf("WSAEventSelect() pretty damn OK!\n");

   }

 

   bDone = FALSE;

   while (!bDone)

   {

               // Wait until a client connection is pending

               dwIndex = WSAWaitForMultipleEvents(dwNumProtocols, hEvents, FALSE,WSA_INFINITE, FALSE);

               if (dwIndex == WSA_WAIT_FAILED)

               {

                           printf("WSAWaitForEvents() failed with error code %d\n", WSAGetLastError());

                           return 1;

               }

               else

                  printf("WSAWaitForEvents() is OK dude!\n");

 

               addrlen = sizeof(nbclient);

               if (iSocketType == SOCK_SEQPACKET)

               {

                           sockClient = accept(sockListen[dwIndex], (SOCKADDR *)&nbclient,&addrlen);

                           if (sockClient == INVALID_SOCKET)

                           {

                                       if ((dwErr = WSAGetLastError()) != WSAEWOULDBLOCK)

                                       {

                                                   printf("accept() failed with error code %d\n", dwErr);

                                                   return 1;

                                       }

                                       else

                                       {

                                                   continue;

                                       }

                           }

                           printf("accept() seems working...\n");

 

                           // Print out the client name who connected

                           // However this retard code failed miserabily!!!:-(

                           iLastByte = nbclient.snb_name[NETBIOS_NAME_LENGTH-1];

                           nbclient.snb_name[NETBIOS_NAME_LENGTH-1];

                           printf("Client '%s (%02d)' got connected...\n", nbclient.snb_name, iLastByte);

 

                           // Create a thread to handle the connection, jump to CreateThread()

                           hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)sockClient,0, &dwThreadId);

                           if (hThread == NULL)

                           {

                                       printf("CreateThread() failed with error code %d\n", GetLastError());

                                       return 1;

                           }

                           else

                                       printf("CreateThread() is OK!\n");

 

                           CloseHandle(hThread);

                           sockClient = INVALID_SOCKET;

               }

               // iSocketType == SOCK_DGRAM

               else

               {

                           char    recvBuff[MAX_BUFFER];

                           DWORD   dwRet;

                          

                           dwRet = recvfrom(sockListen[dwIndex], recvBuff, MAX_BUFFER, 0,(SOCKADDR *)&nbclient, &addrlen);

                           if (dwRet == SOCKET_ERROR)

                           {

                                       if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)

                                                   continue;

                                       printf("recvfrom() failed with error code %d\n", dwErr);

                                       return 1;

                           }

                           else

                                       printf("recvfrom() is OK!\n");

 

                           printf("Read %d bytes...\n", dwRet);

                           printf("Received money: %s\n", recvBuff);

 

                           iLastByte = nbclient.snb_name[NETBIOS_NAME_LENGTH-1];

                           nbclient.snb_name[NETBIOS_NAME_LENGTH-1];

 

                           printf("Read %d bytes from '%s'(%02d)\n", dwRet, nbclient.snb_name, iLastByte);

                          

                           dwRet = sendto(sockListen[dwIndex], recvBuff, dwRet, 0, (SOCKADDR *)&nbclient, sizeof(nbclient));

                           if (dwRet == SOCKET_ERROR)

                           {

                                       if ((dwErr = WSAGetLastError()) == WSAEWOULDBLOCK)

                                                   continue;

                                       printf("sendto() failed with error code %d\n", dwErr);

                                       return 1;

                           }

                           else

                                       printf("sendto() is OK...\n");

 

                           printf("Wrote %d bytes successfully...\n", dwRet);

               }

               WSAResetEvent(hEvents[dwIndex]);

   }

   // Clean up things

   printf("Cleaning-up and de-allocating all the rubbish...\n");

   for (i=0; i < dwNumProtocols ;i++)

   {

               closesocket(sockListen[i]);

               WSACloseEvent(hEvents[i]);

   }

 

   GlobalFree(wsapi);

   GlobalFree(hEvents);

   GlobalFree(sockListen);

   WSACleanup();

   return 0;

 }

 

Next, add a custom made header file.

 

---------------------------------------------------------

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, adding new header file

 

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, adding wsnbdef header file

 

Add the code shown below.

 

// Description:

// This file contains common defines and function prototype

// used by the NetBIOS Winsock samples.

//

#define MAX_BUFFER 16000

#define DEFAULT_COUNT 20

#define INVALID_LANA 0x80000000

 

BOOL FindProtocol(WSAPROTOCOL_INFO **wsapi, DWORD *dwCount);

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, code snippet

 

Add the definition file for the previously created header file.

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs, adding wsnbdef.cpp definition file

 

Add the following source code.

 

// Description:

//    This file contains common definitions and functions used by all the NetBIOS Winsock samples

#include <winsock2.h>

#include <stdio.h>

#include "wsnbdef.h"

 

extern int iSocketType;

 

// Function: FindProtocol

// Description:

//    Search through the available network service providers for

//    AF_NETBIOS compatible protocols. The number of providers

//    returned will be equal to 2 times the number of LANAs we

//    would have in NetBIOS. This is because there is two providers

//    for each LANA: one datagram and one session oriented provider.

BOOL FindProtocol(WSAPROTOCOL_INFO **wsapi, DWORD *dwCount)

{

    WSAPROTOCOL_INFO *lpProtocolBuf=NULL;

    DWORD            dwErr, dwRet, dwBufLen=0;

    DWORD              i;

 

    *dwCount = 0;

    if (SOCKET_ERROR != WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen))

    {

        // This should never happen as there is a NULL buffer

        printf("WSAEnumProtocols() failed!\n");

        return FALSE;

    }

    else if (WSAENOBUFS != (dwErr = WSAGetLastError()))

    {

         // We failed for some reason not relating to buffer size - also odd

         printf("WSAEnumProtocols() failed with error code %d\n", dwErr);

         return FALSE;

    }

    else

        printf("WSAEnumProtocols() is OK!\n");

 

    // Allocate the correct buffer size for WSAEnumProtocols as well as the buffer to return

    lpProtocolBuf = (WSAPROTOCOL_INFO *)GlobalAlloc(GMEM_FIXED, dwBufLen);

    *wsapi = (WSAPROTOCOL_INFO *)GlobalAlloc(GMEM_FIXED, dwBufLen);

 

    if ((lpProtocolBuf == NULL) || (*wsapi == NULL))

    {

           printf("GlobalAlloc() failed with error code %d\n", GetLastError());

           return FALSE;

    }

    printf("GlobalAlloc() is working...\n");

 

    dwRet = WSAEnumProtocols(NULL, lpProtocolBuf, &dwBufLen);

    if (dwRet == SOCKET_ERROR)

    {

           printf("WSAEnumProtocols() failed with error code %d\n", WSAGetLastError());

           GlobalFree(lpProtocolBuf);

           return FALSE;

    }

    printf("WSAEnumProtocols() is OK\n");

 

    // Loop through the returned protocol information looking for those

    // that are in the AF_NETBIOS address family.

    for (i=0; i<dwRet;i++)

    {

           if (lpProtocolBuf[i].iAddressFamily == AF_NETBIOS)

           {

            if (iSocketType == SOCK_SEQPACKET)

            {

                if ( (lpProtocolBuf[i].dwServiceFlags1 & XP1_GUARANTEED_DELIVERY) &&

                    (lpProtocolBuf[i].dwServiceFlags1 & XP1_GUARANTEED_ORDER) &&

                    ((lpProtocolBuf[i].dwServiceFlags1 & XP1_CONNECTIONLESS) == 0) &&

                    (lpProtocolBuf[i].iSocketType == iSocketType))

                {

                    (*wsapi)[(*dwCount)++] = lpProtocolBuf[i];

                }

            }

            else if (iSocketType == SOCK_DGRAM)

            {

                if ( !(lpProtocolBuf[i].dwServiceFlags1 & XP1_GUARANTEED_DELIVERY) &&

                    !(lpProtocolBuf[i].dwServiceFlags1 & XP1_GUARANTEED_ORDER) &&

                    ((lpProtocolBuf[i].dwServiceFlags1 & XP1_CONNECTIONLESS) != 0) &&

                    (lpProtocolBuf[i].iSocketType == iSocketType))

                {

                    (*wsapi)[(*dwCount)++] = lpProtocolBuf[i];

                }

            }

           }

    }

    GlobalFree(lpProtocolBuf);

    return TRUE;

}

 

Build and run the whole Netbios server program.

 

Winsock 2, Other Supported Protocols: The Netbios Client-Server Program Example - Demonstrating the Netbios client and server programs - runnig the program showing a sample output

 

 

 


< Another NetBIOS Example | Winsock2 Supported Protocols Main | NetBIOS Client Example >