WSOCK.C
//----------------------------------------------------------------------------- 
// This is a part of the Microsoft Source Code Samples.  
// Copyright 1993 - 1998 Microsoft Corporation. 
// All rights reserved.  
//   
// This source code is only intended as a supplement to  
// Microsoft Development Tools and/or WinHelp documentation. 
// See these sources for detailed information regarding the  
// Microsoft samples programs. 
//----------------------------------------------------------------------------- 
 
/****************************************************************************\ 
*  wsock.c -- sample program demonstrating Windows Sockets APIs. 
* 
*  Demonstrates basic sockets programming with the Windows Sockets API. 
*  Allows two occurances of the application to connect.  Also, displays 
*  information about a host computer. 
* 
****************************************************************************/ 
 
#include <windows.h>       /* required for all Windows applications */ 
#include <stdio.h>         /* for sprintf                           */ 
#include <string.h>        /* for strlen                            */ 
#include <memory.h> 
#include <process.h>       /* for _beginthread                      */ 
#include "wsock.h"         /* specific to this program              */ 
 
HANDLE hInst;              /* current instance                      */ 
 
SOCKET sock; 
u_short portno;            /* Which tcp port are we going to use?   */ 
 
char szBuff[ 80 ];         /* Temp buffer - used to pass strings    */ 
                           /* to and from dialog boxes, etc         */ 
 
char gpszHelloWorld[]= "Hello World."; 
 
#define MAX_PENDING_CONNECTS 4  /* The backlog allowed for listen() */ 
#define NO_FLAGS_SET         0  /* Used with recv()/send()          */ 
#define MY_MSG_LENGTH       80  /* msg buffer sent back and forth   */ 
 
/**************************************************************************** 
* 
*    FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int) 
* 
*    PURPOSE: calls initialization function, processes message loop 
* 
*\***************************************************************************/ 
 
WINAPI WinMain( 
    HINSTANCE hInstance, 
    HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, 
    int nCmdShow 
    ) 
{ 
 
    MSG msg; 
 
    UNREFERENCED_PARAMETER( lpCmdLine ); 
 
    if (!hPrevInstance)                  /* Other instances of app running? */ 
        if (!InitApplication(hInstance)) /* Initialize shared things        */ 
            return (FALSE);              /* Exits if unable to initialize   */ 
 
    /* 
    *   Perform initializations that apply to a specific instance 
    */ 
    if (!InitInstance(hInstance, nCmdShow)) 
        return (FALSE); 
 
    /* 
    *   Acquire and dispatch messages until a WM_QUIT message is received. 
    */ 
    while (GetMessage(&msg,        /* message structure                      */ 
            NULL,                  /* handle of window receiving the message */ 
            0,             /* lowest message to examine              */ 
            0))            /* highest message to examine             */ 
        { 
        TranslateMessage(&msg);    /* Translates virtual key codes           */ 
        DispatchMessage(&msg);     /* Dispatches message to window           */ 
   } 
    return (msg.wParam);           /* Returns the value from PostQuitMessage */ 
} 
 
 
/**************************************************************************** 
* 
*    FUNCTION: InitApplication(HANDLE) 
* 
*    PURPOSE: Initializes window data and registers window class 
* 
*\***************************************************************************/ 
 
BOOL InitApplication(HANDLE hInstance)       /* current instance             */ 
{ 
    WNDCLASS  wc; 
 
    /* Fill in window class structure with parameters that describe the       */ 
    /* main window.                                                           */ 
 
    wc.style = 0;                    /* Class style(s).                    */ 
    wc.lpfnWndProc = (WNDPROC)MainWndProc;       /* Function to retrieve messages for  */ 
                                        /* windows of this class.             */ 
    wc.cbClsExtra = 0;                  /* No per-class extra data.           */ 
    wc.cbWndExtra = 0;                  /* No per-window extra data.          */ 
    wc.hIcon = LoadIcon (hInstance, "wsockicon"); /* Icon name from .RC        */ 
    wc.hInstance = hInstance;          /* Application that owns the class.   */ 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName =  "WSockMenu";   /* Name of menu resource in .RC file. */ 
    wc.lpszClassName = "WSockWClass"; /* Name used in call to CreateWindow. */ 
 
    /* Register the window class and return success/failure code. */ 
 
    return (RegisterClass(&wc)); 
 
} 
 
 
/****************************************************************************\ 
* 
*    FUNCTION:  InitInstance(HANDLE, int) 
* 
*    PURPOSE:  Saves instance handle and creates main window 
* 
*\***************************************************************************/ 
 
BOOL InitInstance( 
    HANDLE          hInstance,          /* Current instance identifier.       */ 
    int             nCmdShow)           /* Param for first ShowWindow() call. */ 
{ 
    HWND            hWnd;               /* Main window handle.                */ 
 
    /* Save the instance handle in static variable, which will be used in  */ 
    /* many subsequence calls from this application to Windows.            */ 
 
    hInst = hInstance; 
 
    /* Create a main window for this application instance.  */ 
 
    hWnd = CreateWindow( 
        "WSockWClass",                  /* See RegisterClass() call.          */ 
        "Windows Sockets Sample Application",   /* Text for window title bar.         */ 
        WS_OVERLAPPEDWINDOW,            /* Window style.                      */ 
        CW_USEDEFAULT,                  /* Default horizontal position.       */ 
        CW_USEDEFAULT,                  /* Default vertical position.         */ 
        CW_USEDEFAULT,                  /* Default width.                     */ 
        CW_USEDEFAULT,                  /* Default height.                    */ 
        NULL,                           /* Overlapped windows have no parent. */ 
        NULL,                           /* Use the window class menu.         */ 
        hInstance,                      /* This instance owns this window.    */ 
        NULL                            /* Pointer not needed.                */ 
    ); 
 
    /* If window could not be created, return "failure" */ 
 
    if (!hWnd) 
        return (FALSE); 
 
    /* Make the window visible; update its client area; and return "success" */ 
 
    ShowWindow(hWnd, nCmdShow);  /* Show the window                        */ 
    UpdateWindow(hWnd);          /* Sends WM_PAINT message                 */ 
    return (TRUE);               /* Returns the value from PostQuitMessage */ 
 
} 
 
/****************************************************************************\ 
* 
*    FUNCTION: AcceptThreadProc(PTHREADPACK tp) 
* 
*    PURPOSE:  Use blocking accept() calls and display a message box when 
*              a connection is made. 
* 
*\***************************************************************************/ 
 
void AcceptThreadProc( PTHREADPACK ptp ) 
{ 
   SOCKADDR_IN acc_sin;    /* Accept socket address - internet style */ 
   int acc_sin_len;        /* Accept socket address length */ 
   int status; 
   char szMsg[ MY_MSG_LENGTH ]; 
 
 
   acc_sin_len = sizeof(acc_sin); 
 
   wsprintf( szBuff, "thread #%d created.", ptp->nThread); 
   MessageBox(ptp->hWnd, szBuff, "FYI", MB_OK); 
 
   sock = accept( sock,(struct sockaddr FAR *) &acc_sin, 
            (int FAR *) &acc_sin_len ); 
 
   if (sock < 0) { 
      sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
      MessageBox(ptp->hWnd, szBuff, "accept(sock) failed", MB_OK); 
 
   } 
 
   wsprintf( szBuff, "Thread #%d accepted something\n\nCheck for incoming messages?", ptp->nThread); 
 
   /* 
   *   Now have a connection -- 
   *   SetConnectMenus() grays/enables proper menu items 
   */ 
   SetConnectMenus( ptp->hWnd ); 
 
 
   while (1) { 
 
      /* 
      *   By default sockets are created in blocking mode. 
      *   Just keep reading until process destroyed. 
      */ 
      status = recv( sock, szMsg, MY_MSG_LENGTH, NO_FLAGS_SET ); 
 
      if (status == SOCKET_ERROR) { 
         wsprintf( szMsg, "Error %d", WSAGetLastError() ); 
         MessageBox( ptp->hWnd, szMsg, "Error with recv()", MB_OK); 
         _endthread(); 
      } 
          szMsg[status] = '\0';  /* NULL-terminate the string */ 
 
      if (status) 
         MessageBox( ptp->hWnd, szMsg, "From thread", MB_OK); 
      else  { 
         MessageBox( ptp->hWnd, "Connection broken", "Error", MB_OK); 
         _endthread(); 
      } 
 
   }    /* while (forever) */ 
} 
 
/****************************************************************************\ 
* 
*    FUNCTION:  FillAddr(HWND, PSOCKADDR_IN, BOOL) 
* 
*    PURPOSE:  Retrieves the IP address and port number. 
* 
*    COMMENTS: 
*        This function is called in two conditions. 
*            1.) When a client is preparing to call connect(), or 
*            2.) When a server host is going to call bind(), listen() and 
*                accept(). 
*        In both situations, a SOCKADDR_IN structure is filled. 
*        However, different fields are filled depending on the condition. 
* 
*   ASSUMPTION: 
*      szBuff is a global variable that contains the remote host name or NULL 
*      if local. 
*      bClient determines if this is being called by a client ( will be 
*         performing a connect ) or a server ( will be listening ) 
* 
* 
*\***************************************************************************/ 
 
BOOL FillAddr( 
        HWND hWnd, 
        PSOCKADDR_IN psin, 
        BOOL bClient) 
{ 
   DWORD dwSize; 
   PHOSTENT phe; 
   PSERVENT pse; 
   char szTemp[200]; 
   int status; 
 
 
   psin->sin_family = AF_INET; 
 
 
   /* 
   *   If we are setting up for a listen() call (bConnect = FALSE), 
   *   fill servent with our address. 
   */ 
   if (bClient) { 
      phe = gethostbyname(szBuff); 
      if (phe == NULL) { 
         sprintf(szTemp, "%d is the error. Make sure '%s' is listed in the hosts file.", WSAGetLastError(), szBuff); 
 
         MessageBox(hWnd, szTemp, "gethostbyname() failed.", MB_OK); 
         return FALSE; 
      } 
      memcpy((char FAR *)&(psin->sin_addr), phe->h_addr, 
         phe->h_length); 
 
      } 
   else { // server 
 
      /* 
      *   Retrieve my ip address.  Assuming the hosts file in 
      *   in %systemroot%/system/drivers/etc/hosts contains my computer name. 
      */ 
 
      dwSize = sizeof(szBuff); 
      gethostname(szBuff, dwSize); 
 
      psin->sin_addr.s_addr = INADDR_ANY; 
      } 
 
 
   /* 
   *   Retrieve the Port number 
   */ 
   status = DialogBox(hInst,             /* current instance         */ 
      "TCPPORTNUM",                      /* resource to use          */ 
      hWnd,                              /* parent handle            */ 
      GetTcpPort);                       /* instance address         */ 
 
   switch(status) { 
      case 0:               /* User cancelled request from prev. dialog box */ 
         return FALSE; 
 
      case 1:               /* actual port number entered */ 
         psin->sin_port = htons(portno);        /* Convert to network ordering */ 
         break; 
 
      case 2:               /* service name entereted */ 
         /* 
         *   Find the service name, szBuff, which is a type tcp protocol in 
         *   the "services" file. 
         */ 
         pse = getservbyname(szBuff, "tcp"); 
         if (pse == NULL)  { 
            sprintf(szBuff, "%d is the error. Make sure this is a valid TCP service.", WSAGetLastError()); 
            MessageBox(hWnd, szBuff, "getservbyname(sock) failed", MB_OK); 
            return FALSE; 
         } 
         psin->sin_port = pse->s_port; 
         break; 
 
      default: 
         return FALSE; 
   } 
   return TRUE; 
} 
 
/**************************************************************************** 
* 
*    FUNCTION: SetConnectMenus( HWND ) 
* 
*    PURPOSE: Gray/Enable the proper menu items after a connection has been 
*             established. 
* 
*\***************************************************************************/ 
 
void SetConnectMenus( HWND hWnd ) 
{ 
   /* 
   *   Disable/enable proper menu items. 
   */ 
   EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_ENABLED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED ); 
   EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED ); 
 
   /* 
   *   Reflect socket connection in title bar. 
   */ 
   SetWindowText( hWnd, "Connected"); 
} 
 
/****************************************************************************\ 
* 
*    FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG) 
* 
*    PURPOSE:  Processes main window messages 
* 
* MESSAGES: 
*  WM_CREATE   - call WSAStartUp() and display description message 
*  WSA_ACCEPT  - User-defined message used with WSAAsyncSelect().  Sent 
*                by the Windows Sockets DLL when a socket connection is 
*                pending. 
* 
*  WM_COMMAND 
*  IDM_CONNECT - Connect to a remote host. 
*  IDM_LISTEN  - Use the BSD-Style accept(). 
*  IDM_ALISTEN - Use the Windows Sockets Asynchronous APIs to detect when 
*                a connection is made. 
*  IDM_CANCEL  - Cancel the Asynchronous call above. 
*  IDM_TLISTEN - Uses two threads to accept network connections (using the 
*                BSD-Style accept(). 
*  IDM_HOSTNAME- Display information about a host. 
*  IDM_ABOUT   - About box. 
* 
*  WM_DESTROY  - destroy window and call the WSACleanUp() 
* 
*\***************************************************************************/ 
 
LONG APIENTRY MainWndProc( 
        HWND hWnd,                /* window handle                   */ 
        UINT message,             /* type of message                 */ 
        UINT wParam,              /* additional information          */ 
        LONG lParam)              /* additional information          */ 
{ 
   int status;             /* Status Code */ 
   SOCKADDR_IN local_sin;  /* Local socket - internet style */ 
   SOCKADDR_IN acc_sin;    /* Accept socket address - internet style */ 
   int acc_sin_len;        /* Accept socket address length */ 
 
 
   switch (message) { 
   case WM_CREATE: 
   { 
      WSADATA WSAData; 
      char szTemp[80]; 
 
      if ((status = WSAStartup(MAKEWORD(1,1), &WSAData)) == 0) { 
         MessageBox( hWnd, WSAData.szDescription, WSAData.szSystemStatus, MB_OK); 
      } 
      else { 
         sprintf(szTemp, "%d is the err", status); 
         MessageBox( hWnd, szTemp, "Error", MB_OK); 
      } 
   } 
   break;   /* WM_CREATE */ 
 
   /* 
   *    Notification if data is waiting on a socket.  This comes 
   *    from Windows Sockets (via WSAAsyncSelect()). 
   */ 
   case WSA_READ: 
   { 
      char szTemp[ MY_MSG_LENGTH ]; 
 
      if (WSAGETSELECTEVENT(lParam) == FD_READ) { 
         status = recv((SOCKET)wParam, szTemp, MY_MSG_LENGTH, NO_FLAGS_SET ); 
 
         if (status) { 
            szTemp[ status ] = '\0'; 
            MessageBox( hWnd, szTemp, "WSA_READ", MB_OK); 
         } 
         else 
            MessageBox( hWnd, "Connection broken", "Error", MB_OK); 
      } 
      else {    /* FD_CLOSE -- connection dropped */ 
         MessageBox( hWnd, "Connection lost", "WSA_READ", MB_OK); 
         EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED); 
      } 
 
 
   } 
   break;       /* WSA_READ*/ 
 
   case WSA_ACCEPT: /* Notification if a socket connection is pending. */ 
      /* 
      *   Disable/enable proper menu items. 
      */ 
      EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED); 
      EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED); 
      EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED); 
      EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED); 
      EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED); 
      EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED); 
 
      if (WSAGETSELECTERROR( lParam ) == 0) {   /* Success */ 
 
         /* 
         *   Accept the incoming connection. 
         */ 
         acc_sin_len = sizeof( acc_sin ); 
         sock = accept( sock,(struct sockaddr FAR *) &acc_sin, 
            (int FAR *) &acc_sin_len ); 
 
         if (sock < 0) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "accept(sock) failed", MB_OK); 
            break; 
         } 
 
         MessageBox(hWnd, "accept()", "Accepted a connection!", MB_OK); 
 
         /* 
         *   Now have a connection -- 
         *   SetConnectMenus() grays/enables proper menu items 
         */ 
         SetConnectMenus( hWnd ); 
 
         /* 
         *   Send main window a WSA_READ when either data is pending on 
         *   the socket (FD_READ) or the connection is closed (FD_CLOSE) 
         */ 
         if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) { 
            wsprintf(szBuff, "%d (0x%x)", status, status); 
            MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
            closesocket( sock ); 
         } 
      } 
      else { 
         MessageBox(hWnd, "accept()", "Error occured!", MB_OK); 
 
         /* 
         *   Cancel any further notifications. 
         */ 
         WSAAsyncSelect( sock, hWnd, 0, 0); 
         SetWindowText( hWnd, "Async Listen call canceled"); 
      } 
      break;   /* WSA_ACCEPT */ 
 
 
 
   case WM_COMMAND:        /* message: command from application menu */ 
      switch(LOWORD(wParam)) { 
      case IDM_CONNECT: /* Client - connect to remote host */ 
      { 
         /* 
 
         When a network client wants to connect to a server, 
         it must have: 
            1.) a TCP port number (gotten via getservbyname()) 
            and 
            2.) an IP address of the remote host (gotten via gethostbyname()). 
 
         The following summarizes the steps used to connect. 
         Make a dialog box (HostName) 
         Get the name of the remote host computer in which 
          to connect from the user (store string in "szBuff" global var) 
       * Check to see if the hosts file knows the computer (gethostbyname) 
       * Get the host information (hostent structure filled) 
       * Fill in the address of the remote host into the servent structure (memcpy) 
       * Make a dialog box (TCPPORTNUM) 
       * Get the NAME of the port to connect to on the remote host from the 
         user. 
       * Get the port number (getservbyname) 
       * Fill in the port number of the servent structure 
         Establish a connection (connect) 
 
         The * prefixed steps are done in the FillAddr() procedure. 
 
 
         */ 
         SOCKADDR_IN dest_sin;  /* DESTination Socket INternet */ 
 
 
 
         /* Get the name of the remote host. Store the string in szBuff. */ 
 
         status = DialogBox(hInst, 
            "HOSTNAME", 
            hWnd, 
            GetHostName); 
 
         if (!status)   /* User cancelled request from prev. dialog box */ 
            break; 
 
         sock = socket( AF_INET, SOCK_STREAM, 0); 
         if (sock == INVALID_SOCKET) { 
            MessageBox(hWnd, "socket() failed", "Error", MB_OK); 
            break; 
         } 
 
         /* 
         *    Retrieve the IP address and TCP Port number 
         *    Global variable szBuff contains the remote host name. 
         */ 
         if (!FillAddr( hWnd, &dest_sin, TRUE)) { 
            closesocket( sock ); 
            break; 
         } 
 
 
         if (connect( sock, (PSOCKADDR) &dest_sin, sizeof( dest_sin)) < 0) { 
            closesocket( sock ); 
            MessageBox(hWnd, "connect() failed", "Error", MB_OK); 
            break; 
         } 
         MessageBox(hWnd, "connect() worked!", "Success!", MB_OK); 
 
         /* 
         *   Now have a connection -- 
         *   SetConnectMenus() grays/enables proper menu items 
         */ 
         SetConnectMenus( hWnd ); 
 
         /* 
         *   Send main window a WSA_READ when either data is pending on 
         *   the socket (FD_READ) or the connection is closed (FD_CLOSE) 
         */ 
         if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) { 
            wsprintf(szBuff, "%d (0x%x)"); 
            MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
            closesocket( sock ); 
         } 
 
      } 
      break;   /* IDM_CONNECT */ 
 
      case IDM_CONNECTANDSEND: 
      { 
         // 
         // 
         //  In order to simulate a more typical real-world client, here 
         //   we make the connection, and then immediately send it data. 
         // 
         //  See IDM_CONNECT above for full comments. 
 
         SOCKADDR_IN dest_sin; 
 
         status = DialogBox(hInst, 
            "HOSTNAME", 
            hWnd, 
            GetHostName); 
 
         if (!status) 
            break; 
 
         sock = socket( AF_INET, SOCK_STREAM, 0); 
         if (sock == INVALID_SOCKET) { 
            MessageBox(hWnd, "socket() failed", "Error", MB_OK); 
            break; 
         } 
 
         if (!FillAddr( hWnd, &dest_sin, TRUE)) { 
            closesocket( sock ); 
            break; 
         } 
 
 
         if (connect( sock, (PSOCKADDR) &dest_sin, sizeof( dest_sin)) < 0) { 
            MessageBox(hWnd, "connect() failed", "Error", MB_OK); 
            closesocket( sock ); 
            break; 
         } 
 
         if (send (sock, gpszHelloWorld, lstrlen (gpszHelloWorld), 0 ) == SOCKET_ERROR) { 
            wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
            MessageBox( hWnd, szBuff, "Error on send()", MB_OK); 
            closesocket( sock ); 
            break; 
         } 
 
 
         MessageBox(hWnd, "connect() & send() worked!", "Success!", MB_OK); 
 
         SetConnectMenus( hWnd ); 
 
         if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) { 
            wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
            MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
            closesocket( sock ); 
         } 
 
      } 
      break;   // IDM_CONNECTANDSEND 
 
 
      case IDM_ACCEPTEX: 
      { 
        // 
        // Demonstrate the use of AcceptEx(). 
        // 
 
#define MAX_BYTES        2000 
#define PADDED_ADDR_SIZE sizeof(SOCKADDR_IN)+16 
        SOCKET sListenSocket; 
        SOCKET sAcceptSocket; 
        char   pData [MAX_BYTES]; 
        OVERLAPPED olResult; 
        DWORD dwBytes; 
 
 
        // 
        // For this API, we need to create two sockets ahead of time. 
        //  The listen socket goes through the standard bind/listen steps. 
        // 
 
        sListenSocket = socket( AF_INET, SOCK_STREAM, 0); 
        sAcceptSocket = socket( AF_INET, SOCK_STREAM, 0); 
        if ((sListenSocket == INVALID_SOCKET) || (sAcceptSocket == INVALID_SOCKET)) { 
           MessageBox(hWnd, "sock == INVALID_SOCKET", "socket() failed", MB_OK); 
           closesocket(sListenSocket); 
           closesocket(sAcceptSocket); 
           break; 
        } 
 
        // 
        //   Retrieve the IP address and TCP Port number 
        // 
 
        if (!FillAddr(hWnd, &local_sin, FALSE )) 
           break; 
 
        // 
        //   Associate an address with the socket 
        // 
 
        if (bind( sListenSocket, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) { 
           wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
           MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK); 
           break; 
        } 
 
        // 
        //   And go into the listening state. 
        // 
 
        if (listen( sListenSocket, MAX_PENDING_CONNECTS ) < 0) { 
           wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
           MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK); 
           break; 
        } 
 
        // 
        //   Disable/enable proper menu items. 
        // 
 
        EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED); 
        EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED); 
 
        SetWindowText( hWnd, "AcceptEx.."); 
 
        // 
        //  Create an event for our overlapped structure (required). 
        // 
 
        memset (&olResult,  0, sizeof(olResult)); 
        olResult.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
        dwBytes = 0; 
 
        // 
        //  AcceptEx makes the most sense when used with I/O 
        //   CompletionPorts and TransmitFile. 
        //   We show a very basic usage here... 
        // 
 
        if (AcceptEx( sListenSocket, 
                      sAcceptSocket, 
                      pData, 
                      MAX_BYTES - 2*PADDED_ADDR_SIZE, 
                      PADDED_ADDR_SIZE, 
                      PADDED_ADDR_SIZE, 
                      &dwBytes, 
                      &olResult) == FALSE) { 
 
            if (WSAGetLastError() != ERROR_IO_PENDING) { 
               wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
               MessageBox( hWnd, szBuff, "Error on AcceptEx()", MB_OK); 
               break; 
            } else { 
 
               // 
               // In our contrived scenario, we expect GetLastError to be 
               //  ERROR_IO_PENDING.  A real app would do other work. 
               //  Since this is a simple sample, we will just block waiting 
               //  for some input to come through the socket. 
               // 
 
               GetOverlappedResult ( (HANDLE) sAcceptSocket, 
                                     &olResult, 
                                     &dwBytes, 
                                     TRUE); 
               pData[dwBytes] = 0; 
               MessageBox(hWnd, pData, "AcceptEx received data", MB_OK); 
 
            } 
        } 
 
        // 
        //  As per the documentation, poke the new socket so that it will have 
        //   the correct properties and can be used by other functions. 
        // 
 
        if (setsockopt( sAcceptSocket, 
                        SOL_SOCKET, 
                        SO_UPDATE_ACCEPT_CONTEXT, 
                        (char *)&sListenSocket, 
                        sizeof(sListenSocket) )) { 
                wsprintf(szBuff, "WSAGetLastError: %d", WSAGetLastError()); 
                MessageBox( hWnd, szBuff, "Error in setsockopt()", MB_OK); 
                break; 
        } else { 
 
        // 
        //  sAcceptSocket is now OK for use by other functions. 
        //  set it into our global socket (sock) 
        // 
            sock = sAcceptSocket; 
        } 
 
        // 
        //  In any case, we are done with our listen socket 
        // 
 
        closesocket( sListenSocket ); 
 
        // 
        //  Now have a connection -- 
        //   SetConnectMenus() grays/enables proper menu items 
 
        SetConnectMenus( hWnd ); 
 
        // 
        //  Send main window a WSA_READ when either data is pending on 
        //  the socket (FD_READ) or the connection is closed (FD_CLOSE) 
 
        if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) { 
           wsprintf(szBuff, "%d (0x%x)"); 
           MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
           closesocket( sock ); 
        } 
      } 
      break;   /* IDM_ACCEPTEX */ 
 
 
      case IDM_LISTEN: 
      { 
         sock = socket( AF_INET, SOCK_STREAM, 0); 
         if (sock == INVALID_SOCKET) { 
            MessageBox(hWnd, "socket() failed", "Error", MB_OK); 
            closesocket(sock); 
            break; 
         } 
 
         /* 
         *   Retrieve the IP address and TCP Port number 
         */ 
 
         if (!FillAddr(hWnd, &local_sin, FALSE )) 
            break; 
         /* 
         *   Disable/enable proper menu items. 
         */ 
         EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED); 
 
         SetWindowText( hWnd, "Waiting for connection.."); 
 
 
         /* 
         *   Associate an address with a socket. (bind) 
         */ 
         if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK); 
            break; 
         } 
 
         if (listen( sock, MAX_PENDING_CONNECTS ) < 0) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK); 
            break; 
         } 
 
         acc_sin_len = sizeof(acc_sin); 
 
 
         sock = accept( sock,(struct sockaddr FAR *) &acc_sin, 
            (int FAR *) &acc_sin_len ); 
         if (sock < 0) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "accept(sock) failed", MB_OK); 
            break; 
         } 
 
         MessageBox(hWnd, "accept()", "Accepted a connection!", MB_OK); 
 
         /* 
         *   Now have a connection -- 
         *   SetConnectMenus() grays/enables proper menu items 
         */ 
         SetConnectMenus( hWnd ); 
 
         /* 
         *   Send main window a WSA_READ when either data is pending on 
         *   the socket (FD_READ) or the connection is closed (FD_CLOSE) 
         */ 
         if ((status = WSAAsyncSelect( sock, hWnd, WSA_READ, FD_READ | FD_CLOSE )) > 0) { 
            wsprintf(szBuff, "%d (0x%x)"); 
            MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
            closesocket( sock ); 
         } 
 
      } 
      break;   /* IDM_LISTEN */ 
 
      /* 
      *   Asynchronous Listen - Using WSA extensions. 
      */ 
      case IDM_ALISTEN: 
      { 
 
         sock = socket( AF_INET, SOCK_STREAM, 0); 
         if (sock == INVALID_SOCKET) { 
            MessageBox(hWnd, "socket() failed", "Error", MB_OK); 
            break; 
         } 
         /* 
         *   Retrieve the IP address and TCP Port number 
         */ 
 
         if (!FillAddr( hWnd, &local_sin, FALSE)) { 
            closesocket( sock ); 
            break; 
         } 
 
         /* 
         *   Disable/enable proper menu items. 
         */ 
         EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED); 
 
         SetWindowText( hWnd, "Waiting for connection.. (Async)"); 
 
 
         /* 
         *   Associate an address with a socket. (bind) 
         */ 
         if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK); 
            closesocket( sock ); 
            break; 
         } 
 
         if (listen( sock, MAX_PENDING_CONNECTS ) < 0) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK); 
            break; 
         } 
 
         /* 
         *   Send window a WSA_ACCEPT when something is trying to connect. 
         */ 
         if ((status = WSAAsyncSelect( sock, hWnd, WSA_ACCEPT, FD_ACCEPT)) > 0) { 
            wsprintf( szBuff, "%d (0x%x)"); 
            MessageBox( hWnd, "Error on WSAAsyncSelect()", szBuff, MB_OK); 
            SetWindowText( hWnd, "Async listen cancelled"); 
            closesocket( sock ); 
         } 
 
      } 
      break;   /* IDM_ALISTEN */ 
 
 
      /* 
      *   Cancel an asynchronous call. 
      */ 
      case IDM_CANCEL: 
         WSAAsyncSelect( sock, hWnd, 0, 0); 
         SetWindowText( hWnd, "Async Listen cancelled.."); 
 
         /* 
         *   Disable/enable proper menu items. 
         */ 
         EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CANCEL, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_ENABLED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_ENABLED); 
 
         break;   /* IDM_CANCEL */ 
 
      /* 
      * Listen in the main thread -- spawn and accept two network 
      *  connections inside two threads. 
      */ 
      case IDM_TLISTEN: 
      { 
         static THREADPACK tp; 
 
         sock = socket( AF_INET, SOCK_STREAM, 0); 
         if (sock == INVALID_SOCKET) { 
            MessageBox(hWnd, "socket() failed", "Error", MB_OK); 
            closesocket(sock); 
            break; 
         } 
 
         /* 
         *   Retrieve the IP address and TCP Port number 
         */ 
 
         if (!FillAddr(hWnd, &local_sin, FALSE )) 
            break; 
 
         /* 
         *   Disable/enable proper menu items. 
         */ 
         EnableMenuItem(GetMenu( hWnd ), IDM_HOSTNAME, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_LISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ALISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_TLISTEN, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECT, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_SENDTCP, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_ACCEPTEX, MF_GRAYED); 
         EnableMenuItem(GetMenu( hWnd ), IDM_CONNECTANDSEND, MF_GRAYED); 
 
         SetWindowText( hWnd, "Waiting for connection.."); 
 
 
         /* 
         *   Associate an address with a socket. (bind) 
         */ 
         if (bind( sock, (struct sockaddr FAR *) &local_sin, sizeof(local_sin)) == SOCKET_ERROR) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "bind(sock) failed", MB_OK); 
            break; 
         } 
 
         if (listen( sock, MAX_PENDING_CONNECTS ) < 0) { 
            sprintf(szBuff, "%d is the error", WSAGetLastError()); 
 
            MessageBox(hWnd, szBuff, "listen(sock) failed", MB_OK); 
            break; 
         } 
 
         tp.nThread = 0; 
         tp.hWnd = hWnd; 
 
         _beginthread(AcceptThreadProc, 0, &tp); 
 
         } 
         break;   /* IDM_TLISTEN */ 
 
 
      /* 
      *   Display host information. 
      */ 
      case IDM_HOSTNAME: 
 
         /* 
         *  Prompt the user and retrieve the text name of the host. 
         */ 
         status = DialogBox(hInst, 
            "HOSTNAME", 
            hWnd, 
            GetHostName); 
 
 
         if (status == TRUE) {   /* If user hit "OK" .. */ 
 
         /* 
         *   Get the host information 
         */ 
 
         if ((phe = gethostbyname( szBuff )) == NULL) { 
            MessageBox(hWnd, "gethostbyname() failed", "Error", MB_OK); 
            break; 
         } 
         else { 
 
         /* 
         *   Display the host information .. 
         */ 
            DialogBox(hInst, 
               "DISPLAYHOST", 
               hWnd, 
               DisplayHostEnt); 
         } 
      } 
      break;   /* IDM_HOSTNAME */ 
      /* 
      *   Send a message to (via TCP connection) to remote host. 
      */ 
      case IDM_SENDTCP: 
         DialogBox(hInst,                /* current instance         */ 
            "GetString",                 /* resource to use          */ 
            hWnd,                        /* parent handle            */ 
            GetSendString);              /* instance address         */ 
 
        /* 
        *   Assumption -- The GetString dialog box proc fills the global 
        *   string buffer, szBuff, with the desired string to send. 
        */ 
        send(sock, szBuff, strlen(szBuff), NO_FLAGS_SET ); 
 
        break;   /* IDM_SENDTCP */ 
 
 
 
      case IDM_ABOUT: 
         DialogBox(hInst,                /* current instance         */ 
            "AboutBox",                  /* resource to use          */ 
            hWnd,                        /* parent handle            */ 
            About);                      /* About() instance address */ 
 
         break;   /* IDM_ABOUT */ 
 
      default: 
         /* Lets Windows process it          */ 
         return (DefWindowProc(hWnd, message, wParam, lParam)); 
         break; 
      } 
   break; 
 
 
   /* 
   *   Clean up.  Takes care of any open socket descriptors. 
   */ 
   case WM_DESTROY: 
      WSACleanup(); 
      PostQuitMessage(0); 
      break; 
 
   default:                       /* Passes it on if unproccessed    */ 
      return (DefWindowProc(hWnd, message, wParam, lParam)); 
 
   } 
   return (0); 
 
}