home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / chatwn.exe / CHAT.C < prev    next >
C/C++ Source or Header  |  1993-11-12  |  74KB  |  1,892 lines

  1. /* Brenda Wallace */
  2. /* This program uses the Client SDK for Windows version 1.0 to implement
  3.    a chat program.  The user can specify either IPX, SPX or TLI as the
  4.    comm protocol.
  5. */
  6.  
  7. #define WINDOWS 1
  8. #define NWWIN 1
  9.  
  10. #include <windows.h>
  11. #include <nwcalls.h>
  12. #include <nxtw.h>     /* IPX/SPX header */
  13. #include <tispxipx.h>  /* TLI - IPX/SPX specific structures */
  14. #include <tiuser.h>   /* TLI header */
  15. #include "chat.h"
  16. #include "dos.h"
  17.  
  18. #define LONG_LIVED 0xFF
  19. #define LISTEN_SOCKET 0x4545
  20. #define CONNECT_SOCKET 0x4646
  21. #define MAX_RECEIVE_ECBS 10
  22. #define MAX_SEND_ECBS 10
  23. #define MAX_ECBS MAX_RECEIVE_ECBS + MAX_SEND_ECBS + 1
  24. #define MAX_DATA_LENGTH 80
  25.  
  26. #define CONNECTED_MESSAGE WM_USER + 1 /*Message sent when connection in complete*/
  27. #define DATA_SENT_MESSAGE WM_USER + 2
  28. #define DATA_RECEIVED_MESSAGE WM_USER + 3
  29.  
  30. HWND mainHwnd; /* main parent window, used to send messages */
  31.  
  32. ECB
  33.  SPXReceiveECB[MAX_RECEIVE_ECBS],
  34.  SPXSendECB[MAX_SEND_ECBS],
  35.  SPXConnectECB,
  36.  SPXListenECB;
  37.  
  38. ECB
  39.  IPXReceiveECB[MAX_RECEIVE_ECBS],
  40.  IPXSendECB[MAX_SEND_ECBS];
  41.  
  42.  
  43. SPXHeader
  44.   receiveSPXHeader[MAX_RECEIVE_ECBS],
  45.   sendSPXHeader[MAX_SEND_ECBS],
  46.   connectSPXHeader,
  47.   listenSPXHeader;
  48.  
  49. IPXHeader
  50.   receiveIPXHeader[MAX_RECEIVE_ECBS],
  51.   sendIPXHeader[MAX_SEND_ECBS];
  52.  
  53. struct SPXBufferType
  54. {
  55.   int sequenceNumber;
  56.   char data[MAX_DATA_LENGTH];
  57. } SPXReceiveBuffer[MAX_RECEIVE_ECBS],
  58.   SPXSendBuffer[MAX_SEND_ECBS];
  59.  
  60. struct IPXBufferType
  61. {
  62.   int sequenceNumber;
  63.   char data[MAX_DATA_LENGTH];
  64. } IPXReceiveBuffer[MAX_RECEIVE_ECBS],
  65.   IPXSendBuffer[MAX_SEND_ECBS];
  66.  
  67. /* Which protocol to use - user selected */
  68. char bIPX, bTLI = 0;
  69.   /* set SPX as the default */
  70. char bSPX = 1;
  71.  
  72. NWNET_ADDR internetAddress[10]; /* Address to send to */
  73. char szLoginName[49];  /* Station name to send to */
  74. BYTE immediateAddress[6]; /* Immediate Address used with IPX */
  75.  
  76. /* SPX ESR handler functions */
  77. void FAR PASCAL SPXReceiveESRHandler (void);
  78. void FAR PASCAL SPXSendESRHandler (void);
  79. void FAR PASCAL SPXListenESRHandler (void);
  80. void FAR PASCAL SPXConnectESRHandler (void);
  81. void FAR PASCAL SPXTerminateESRHandler (void);
  82.  
  83. static FARPROC lpfnSPXReceiveESRHandler;
  84. static FARPROC lpfnSPXSendESRHandler;
  85. static FARPROC lpfnSPXListenESRHandler;
  86. static FARPROC lpfnSPXConnectESRHandler;
  87. static FARPROC lpfnSPXTerminateESRHandler;
  88.  
  89. /* IPX ESR handler functions */
  90. void FAR PASCAL IPXReceiveESRHandler (void);
  91. void FAR PASCAL IPXSendESRHandler (void);
  92.  
  93. static FARPROC lpfnIPXReceiveESRHandler;
  94. static FARPROC lpfnIPXSendESRHandler;
  95.  
  96. /* internal SPX connection functions */
  97. int  SPXListen (void);
  98. int  SPXConnect (void);
  99. int AmIFirst (void);
  100.  
  101. /* internal TLI connection functions */
  102. int TLIListen (void);
  103. int TLIConnect (void);
  104. void TLITestForReceive ();
  105.  
  106. /* user interface function */
  107. LONG FAR PASCAL WndProc (HWND, WORD, WORD, LONG);
  108. BOOL FAR PASCAL CallDialogBoxProc (HWND, WORD, WORD, LONG);
  109. BOOL FAR PASCAL ProtocolDialogBoxProc (HWND, WORD, WORD, LONG);
  110.  
  111. /* internal procedures */
  112. int InitializeProtocol ();
  113. int InitializeIPX ();
  114. int InitializeSPX ();
  115. int InitializeTLI ();
  116. void SendDataPacket (char *);
  117. void SendIPXDataPacket (char *);
  118. void SendSPXDataPacket (char *);
  119. void SendTLIDataPacket (char *);
  120. void ProcessReceivedData ();
  121. void ProcessIPXData ();
  122. void ProcessSPXData ();
  123. void ProcessTLIData ();
  124.  
  125. void TerminateConnection ();
  126. void TerminateIPX ();
  127. void TerminateSPX ();
  128. void TerminateTLI ();
  129.  
  130. void Draw3DRect(HDC  hDC,
  131.                 int  top,
  132.                 int  left,
  133.                 int  bottom,
  134.                 int  right,
  135.                 int  bInOut,
  136.                 int  RectWidth);
  137.  
  138. static HANDLE hInstance;
  139. static FARPROC lpfnCallDialogBoxProc;
  140. static FARPROC lpfnProtocolDialogBoxProc;
  141.  
  142. char szBuffer[300];
  143. NWCCODE NWCcode;
  144. char connectionIsInitialized = 0;
  145.  
  146. /* SPX Variables */
  147. DWORD IPXTaskID;
  148. WORD socket;
  149. WORD SPXConnectionID;
  150. struct SREGS sRegs;
  151. struct WORDREGS wordRegs;
  152. /* Global sequence number used sending and receiving packets to determine
  153.    which ECB should be used next and which sequenceNumber the app is waiting
  154.    for */
  155. int sendSequenceNumber,
  156.     receiveSequenceNumber;
  157.  
  158. /* IPX Variables */
  159. WORD destinationSocket;
  160.  
  161. /* TLI Variables */
  162. int fh;   /* file handle for sending and receiving */
  163.  
  164. /* semaphore and internet address variables */
  165. NWCONN_HANDLE conn;  /* connection handle to chosen server */
  166. NWSEM_HANDLE semaphoreHandle;
  167.  
  168. HBRUSH  hBkgndBrush = NULL;  /* pattern brush used to paint window background */
  169. HBITMAP hBkgndBitmap = NULL; /* bitmap used to paint window background */
  170.  
  171. WORD MySegment;
  172. WORD far *I;
  173.  
  174. int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
  175.                     LPSTR lpszCmdLine, int nCmdShow)
  176.  
  177.     {
  178.     static char szAppName[] = "Chat";
  179.     HWND    hwnd;
  180.     MSG     msg;
  181.     WNDCLASS wndclass;
  182.  
  183.     if (!hPrevInstance)
  184.         {
  185.         /* load the bitmap resource used to create our background patten brush */
  186.         hBkgndBitmap = LoadBitmap(hInstance, "bmpBkgnd");
  187.       
  188.         /* create a brush from the background pattern bitmap */
  189.         hBkgndBrush = CreatePatternBrush(hBkgndBitmap);
  190.  
  191.         wndclass.style          = CS_HREDRAW | CS_VREDRAW;
  192.         wndclass.lpfnWndProc    = (WNDPROC) WndProc;
  193.         wndclass.cbClsExtra     = 0;
  194.         wndclass.cbWndExtra     = 0; 
  195.         wndclass.hInstance      = hInstance;
  196.         wndclass.hIcon          = LoadIcon (hInstance, szAppName);
  197.         wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
  198.         wndclass.hbrBackground  = hBkgndBrush;
  199.         wndclass.lpszMenuName   = szAppName;
  200.         wndclass.lpszClassName  = szAppName;
  201.  
  202.         RegisterClass (&wndclass);
  203.         }
  204.  
  205.      hwnd = CreateWindow (szAppName, "Chat Program",
  206.                          CS_HREDRAW | CS_VREDRAW | WS_SYSMENU | WS_MINIMIZEBOX,
  207.                          50,          // initial x position
  208.                          50,          // initial y position
  209.                          550,          // initial x size
  210.                          350,          // initial y size
  211.                          NULL,                   // parent window handle
  212.                          NULL,                   // window menu handle
  213.                          hInstance,              // program instance handle
  214.                          NULL);                  // create parameters
  215.  
  216.  
  217.     ShowWindow (hwnd, nCmdShow);
  218.     UpdateWindow (hwnd);
  219.  
  220.  
  221.     while (GetMessage (&msg, NULL, 0, 0))
  222.         {
  223.         TranslateMessage (&msg);
  224.         DispatchMessage (&msg);
  225.         }
  226.     return msg.wParam;
  227.  
  228.     } /* end WinMain */
  229.  
  230.  
  231. /**************************************************************************/
  232. /*                                                                        */
  233. /* MAIN WINDOW PROCEDURE - WndProc                                        */
  234. /*                                                                        */
  235. /**************************************************************************/
  236.  
  237. long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  238.     {
  239.  
  240.     WORD index;  /* index returned when inserting into listbox */
  241.  
  242.     static HWND hwndMessageList;
  243.     static HWND hwndCallButton;
  244.     static HWND hwndHangUpButton;
  245.     static HWND hwndProtocolButton;
  246.     static HWND hwndSendButton;
  247.     static HWND hwndMessageTitle;
  248.     static HWND hwndMessageText;
  249.  
  250.     char data[MAX_DATA_LENGTH];
  251.  
  252.     HDC         hDC;
  253.     PAINTSTRUCT ps;
  254.     RECT        Rect;
  255.  
  256.     switch (message)
  257.         {
  258.         case WM_PAINT:
  259.             /* begin screen painting */
  260.             hDC = BeginPaint(hwnd, &ps);
  261.  
  262.             /* draw the 3D rect around the message history list box */
  263.             Draw3DRect(hDC, 10, 5, 230, 425, 0, 1);
  264.  
  265.             Draw3DRect(hDC, 0, 437, 300, 438, 0, 1);
  266.  
  267.             /* draw the 3D rect around the message-to-send edit field */
  268.             GetClientRect(hwnd, &Rect);
  269.             Draw3DRect(hDC, Rect.bottom - 30, -1, Rect.bottom, Rect.right, 1, 1);
  270.  
  271.             /* label the message-to-send with the word "message" */
  272.             /*  drawn in transparent text */
  273.             SetBkMode(hDC, TRANSPARENT);
  274.             TextOut(hDC, 15, 287, "Message:", 8);
  275.  
  276.             /* end screen painting */
  277.             EndPaint(hwnd, &ps);
  278.             return 0;
  279.             break;
  280.  
  281.           case WM_CTLCOLOR:
  282.             /* change the background of the main screen push buttons to */
  283.             /*  light gray to match the color of the background */
  284.             if ((LOWORD(lParam) != hwndMessageText) &&
  285.                 (LOWORD(lParam) != hwndMessageList))
  286.               return((DWORD)GetStockObject(LTGRAY_BRUSH));
  287.             return(0);
  288.             break;
  289.  
  290.           case WM_CREATE:
  291.                  /* Lock the data segment containing the ECBs */
  292.                    __asm mov MySegment, ds;
  293.                    NWCcode =  GlobalPageLock (MySegment);
  294.                    if (NWCcode == 0)
  295.                     { /* GlobalPageLock failed */
  296.                        MessageBox (hwnd, "GlobalPageLock failed", "Error", MB_OK); 
  297.                     }
  298.  
  299.                    mainHwnd = hwnd;
  300.                    hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
  301.                    lpfnCallDialogBoxProc = MakeProcInstance
  302.                                                 (CallDialogBoxProc,
  303.                                                  hInstance);
  304.                    lpfnProtocolDialogBoxProc = MakeProcInstance
  305.                                                 (ProtocolDialogBoxProc,
  306.                                                  hInstance);
  307.  
  308.                    /* intialize NWCALLS */
  309.                    NWCcode = NWCallsInit ( (void NWFAR *) NULL, (void NWFAR *) NULL);
  310.                    if (NWCcode)
  311.                     {
  312.                       sprintf (szBuffer, "Error intializing NWCALLS = %0X", NWCcode);
  313.                       MessageBox (hwnd, szBuffer, "ERROR", MB_OK); 
  314.                     }
  315.  
  316.                     /* Create the main window components */
  317.                     
  318.                     /* Create the messsage listbox */
  319.                     hwndMessageList = CreateWindow("listbox",
  320.                                     NULL,  
  321.                                     WS_VISIBLE | WS_CHILD |
  322.                                     LBS_STANDARD | WS_HSCROLL
  323.                                     | LBS_NOINTEGRALHEIGHT,
  324.                                     15,
  325.                                     20,
  326.                                     400,
  327.                                     200,
  328.                                     hwnd,
  329.                                     MESSAGE_LISTBOX,
  330.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  331.                                     NULL);
  332.  
  333.                     /* Create the Call... Button */
  334.                     hwndCallButton = CreateWindow("button",
  335.                                     "Call...",  
  336.                                     WS_VISIBLE | WS_CHILD,
  337.                                     450,
  338.                                     20,
  339.                                     80,
  340.                                     30,
  341.                                     hwnd,
  342.                                     CALL_BUTTON,
  343.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  344.                                     NULL);
  345.  
  346.                     /* Create the Hang Up Button */
  347.                     hwndHangUpButton = CreateWindow("button",
  348.                                     "Hang Up",  
  349.                                     WS_VISIBLE | WS_CHILD
  350.                                     | WS_DISABLED,
  351.                                     450,
  352.                                     70,
  353.                                     80,
  354.                                     30,
  355.                                     hwnd,
  356.                                     HANGUP_BUTTON,
  357.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  358.                                     NULL);
  359.  
  360.                     /* Create the Protocol Button */
  361.                     hwndProtocolButton = CreateWindow("button",
  362.                                     "Protocol...",  
  363.                                     WS_VISIBLE | WS_CHILD,
  364.                                     450,
  365.                                     120,
  366.                                     80,
  367.                                     30,
  368.                                     hwnd,
  369.                                     PROTOCOL_BUTTON,
  370.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  371.                                     NULL);
  372.  
  373.                     /* Create the Send Button */
  374.                     hwndSendButton = CreateWindow("button",
  375.                                     "Send",  
  376.                                     WS_VISIBLE | WS_CHILD | WS_DISABLED,
  377.                                     450,
  378.                                     283,
  379.                                     80,
  380.                                     24,
  381.                                     hwnd,
  382.                                     SEND_BUTTON,
  383.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  384.                                     NULL);
  385.  
  386.                     /* Create the Message edit text */
  387.                     hwndMessageText = CreateWindow("edit",
  388.                                     NULL,  
  389.                                     WS_VISIBLE | WS_CHILD | WS_BORDER
  390.                                     | WS_DISABLED,
  391.                                     85,
  392.                                     283,
  393.                                     330,
  394.                                     24,
  395.                                     hwnd,
  396.                                     ETEXT_MESSAGE,
  397.                                     ((LPCREATESTRUCT) lParam) -> hInstance,
  398.                                     NULL);
  399.  
  400.                    return 0;
  401.                break;
  402.  
  403.          case WM_COMMAND:
  404.             switch (wParam)
  405.                 {
  406.                 case IDM_EXIT:
  407.                     SendMessage(hwnd, WM_CLOSE, 0, 0L);
  408.                     return 0;
  409.                 break;
  410.  
  411.                 case CALL_BUTTON:
  412.                    /* If a user to send to was not chosen (the cancel button
  413.                       was pushed), do nothing.  Else, continue by calling
  414.                       InitializeProtocol */
  415.                     if(DialogBox (hInstance, "CallDialogBox", hwnd,
  416.                          lpfnCallDialogBoxProc) == FALSE)
  417.                         return 0;
  418.                         /* If IntializeProtocol fails, terminate the
  419.                            connection, else, activate the hangup button and
  420.                            disable the call and protocol buttons.*/
  421.                         else if (!(InitializeProtocol()))
  422.                             TerminateConnection();
  423.                             else
  424.                                 {
  425.                                 EnableWindow (hwndCallButton, FALSE);
  426.                                 EnableWindow (hwndProtocolButton, FALSE);
  427.                                 EnableWindow (hwndHangUpButton, TRUE);
  428.                                 }
  429.  
  430.                     return 0;
  431.                 break; /* end case CALL_BUTTON */
  432.  
  433.                case PROTOCOL_BUTTON:
  434.                     /* Call the dialog to let the user select a protocol */
  435.                     DialogBox (hInstance, "ProtocolDialogBox", hwnd,
  436.                                lpfnProtocolDialogBoxProc);
  437.                     return TRUE; 
  438.                break; /* end case PROTOCOL_BUTTON */
  439.  
  440.                 case HANGUP_BUTTON:
  441.                     TerminateConnection();
  442.                     /* After terminating, enable the call and protocol
  443.                     buttons and disable the hang up and send buttons and the
  444.                     message title and edit text */
  445.                     EnableWindow (hwndCallButton, TRUE);
  446.                     EnableWindow (hwndProtocolButton, TRUE);
  447.                     EnableWindow (hwndHangUpButton, FALSE);
  448.                     EnableWindow (hwndSendButton, FALSE);
  449.                     EnableWindow (hwndMessageTitle, FALSE);
  450.                     EnableWindow (hwndMessageText, FALSE);
  451.                     /* Clear the message edit text and the list box */
  452.                     SetDlgItemText (hwnd, ETEXT_MESSAGE, "");
  453.                     SendMessage (hwndMessageList, LB_RESETCONTENT, 0, 0L);
  454.                     connectionIsInitialized = FALSE;
  455.                     return 0;
  456.                 break;  /* end case HANGUP_BUTTON */
  457.  
  458.                case SEND_BUTTON:
  459.                     /* Get the message to send */
  460.                     GetDlgItemText (hwnd, ETEXT_MESSAGE, data, sizeof(data));
  461.                     SendDataPacket (data);
  462.                     /* Set the send message edit text to blank */
  463.                     SetDlgItemText (hwnd, ETEXT_MESSAGE, "");
  464.                     return TRUE; 
  465.                break; /* end case SEND_BUTTON */
  466.  
  467.  
  468.                 } 
  469.          break; /* end switch case WM_COMMAND */
  470.  
  471.         case CONNECTED_MESSAGE:
  472.           /* When the 2 sides are connected, enable the send buttons and the
  473.              message title and edit text */
  474.              EnableWindow (hwndSendButton, TRUE);
  475.              EnableWindow (hwndMessageTitle, TRUE);
  476.              EnableWindow (hwndMessageText, TRUE);
  477.             /* Add the connected string to the list box */
  478.             index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  479.                                        LB_INSERTSTRING, -1,
  480.                                        (LONG)(LPSTR) "Ready to Chat.");
  481.             
  482.             /* set the list box selection to the string inserted */
  483.             SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  484.                                LB_SETCURSEL, index,
  485.                                (LONG)(LPSTR) 0);
  486.  
  487.           return TRUE;
  488.         break; /* end case CONNECTED_MESSAGE */
  489.  
  490.         case DATA_SENT_MESSAGE:
  491.             /* check the status of the send here */
  492.           return TRUE;
  493.         break; /* case DATA_SENT_MESSAGE */
  494.  
  495.         case DATA_RECEIVED_MESSAGE:
  496.             /* process received data call the appropriate procedure
  497.                to place the received data in the list box */
  498.             ProcessReceivedData ();
  499.             return TRUE;
  500.         break; /* end case DATA_RECEIVED_MESSAGE */
  501.  
  502.         case WM_TIMER:
  503.             TLITestForReceive();
  504.             return TRUE;
  505.         break; /* end case WM_TIMER */
  506.  
  507.         case WM_DESTROY:
  508.             if (connectionIsInitialized)
  509.                 TerminateConnection();
  510.  
  511.             /* release the GDI objects that are used for the main */
  512.             /*  window background pattern */
  513.             if (hBkgndBrush != NULL)
  514.               DeleteObject(hBkgndBrush);
  515.             if (hBkgndBitmap != NULL)
  516.               DeleteObject(hBkgndBitmap);
  517.  
  518.             /* force Windows to send a WM_QUIT to end the message loop */
  519.             PostQuitMessage (0);
  520.             return 0;
  521.         break; /* end case WM_DESTROY */
  522.  
  523.         } /* end switch for message */
  524.  
  525.     return DefWindowProc (hwnd, message, wParam, lParam);
  526.     } /*end WndProc*/
  527.  
  528.  
  529. /**************************************************************************/
  530. /*                                                                        */
  531. /* CHAT DIALOG BOX PROCEDURE - CallDialogBoxProc                          */
  532. /*                                                                        */
  533. /**************************************************************************/
  534.  
  535. BOOL FAR PASCAL CallDialogBoxProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  536.     {
  537.     /* server list retrieval variables */
  538.     WORD i,j, reserved=0;
  539.     NWLOCAL_MODE reserved1;
  540.     NWLOCAL_SCOPE reserved2;
  541.     NWCONN_HANDLE connListBuffer[8];
  542.     WORD connListBufferSize, numConnections, connStatusBufferSize;
  543.     CONNECT_INFO connStatusBuffer;
  544.     char szServerName[49];
  545.  
  546.     /* User list retrieval variables */
  547.     char objectName[49];
  548.     NWOBJ_TYPE objectType;
  549.     NWOBJ_ID objectID;
  550.     BYTE loginTime[7];
  551.  
  552.     WORD index;
  553.     static WORD connNumberArray[1000]; /* Array to hold upto 1000 connection
  554.                                           numbers for a file server */
  555.  
  556.     HWND hServerListBox;  /* Handle to the serverListBox */
  557.     HWND hOKButton;       /* Handle to the OKButton */
  558.  
  559.     switch (message)
  560.         {
  561.         case WM_INITDIALOG:
  562.  
  563.             /* Get list of servers to which currently attached */
  564.             connListBufferSize = sizeof (connListBuffer);
  565.             NWCcode = NWGetConnectionList (reserved,
  566.                                      (NWCONN_HANDLE NWFAR *) connListBuffer,
  567.                                      connListBufferSize,
  568.                                      (WORD NWFAR *) &numConnections);
  569.             if (NWCcode)
  570.              {
  571.                sprintf (szBuffer, "Error on NWGetConnectionList = %0X",
  572.                         NWCcode);
  573.                MessageBox (hwnd, szBuffer, "ERROR", MB_OK); 
  574.              }
  575.  
  576.             /* Fill the server list box with the servers currently attached */
  577.             for (i=0;i<numConnections;i++)
  578.                 {
  579.                  NWCcode = NWGetConnectionStatus (connListBuffer[i],
  580.                                     (CONNECT_INFO NWFAR *) &connStatusBuffer,
  581.                                     connStatusBufferSize);
  582.                  SendDlgItemMessage (hwnd, SERVER_LISTBOX,
  583.                                 LB_ADDSTRING, 0,
  584.                                 (LONG) (LPSTR) connStatusBuffer.serverName);
  585.  
  586.                 } /* end for */
  587.  
  588.             return TRUE;
  589.         break; /* case WM_INITDIALOG */
  590.  
  591.         case WM_COMMAND:
  592.             switch (wParam)
  593.              {
  594.  
  595.               case SERVER_LISTBOX:
  596.                    switch (HIWORD (lParam))
  597.                     {
  598.                      case LBN_SELCHANGE:
  599.                          /* clear the user list box */
  600.                          SendDlgItemMessage (hwnd, USER_LISTBOX,
  601.                                              LB_RESETCONTENT, 0,
  602.                                              (LONG) (LPSTR) NULL);
  603.   
  604.                          /* Disable the USER_LISTBOX from redrawing while
  605.                             filling it with users */
  606.                          SendDlgItemMessage (hwnd, USER_LISTBOX,
  607.                                              WM_SETREDRAW, FALSE, 0L);
  608.  
  609.                          /* Get the server name changed to */
  610.                          index = (WORD) SendDlgItemMessage (hwnd,
  611.                                                  SERVER_LISTBOX,
  612.                                                  LB_GETCURSEL, 0, 0L);
  613.                          (WORD) SendDlgItemMessage (hwnd, SERVER_LISTBOX,
  614.                                                 LB_GETTEXT, index,
  615.                                                (LONG) (LPSTR) szServerName);
  616.  
  617.                          /* Disable the OK Button until a user is selected */
  618.                          hOKButton = GetDlgItem (hwnd, OK_BUTTON);
  619.                          EnableWindow (hOKButton, FALSE);
  620.  
  621.                          /* Disable the server list box while collecting */
  622.                          hServerListBox = GetDlgItem (hwnd, SERVER_LISTBOX);
  623.                          EnableWindow (hServerListBox, FALSE);
  624.  
  625.                          /* Specify in the status text to wait, while collecting */
  626.                          SetDlgItemText (hwnd, STEXT_COLLECTING,
  627.                                          (LPSTR) "Please Wait. Collecting User Names...");
  628.                          
  629.                          /* Get the connection handle of the server from which
  630.                             to choose a user */
  631.                          NWCcode = NWGetConnectionHandle (
  632.                                          (BYTE NWFAR *) szServerName,
  633.                                          reserved1,
  634.                                          (NWCONN_HANDLE NWFAR *) &conn,
  635.                                          (NWLOCAL_SCOPE NWFAR *) &reserved2);
  636.  
  637.                         /* Fill the user list box with users logged into
  638.                            the selected server */
  639.                         j=0;
  640.                         for (i=1; i<=1000; i++)
  641.                         {
  642.                             NWCcode = NWGetConnectionInformation(conn, i,
  643.                                             (char NWFAR *) objectName,
  644.                                             (NWOBJ_TYPE NWFAR *) &objectType,
  645.                                             (NWOBJ_ID NWFAR *) &objectID,
  646.                                             (BYTE NWFAR *) loginTime);
  647.                                         
  648.                             if (NWCcode == SUCCESSFUL &&
  649.                                objectType == OT_USER  &&
  650.                                strcmp (objectName, "NOT-LOGGED-IN"))
  651.                             {
  652.  
  653.                                /* Add the user to the list box */
  654.                                sprintf (szBuffer, "%d %s", i, objectName);
  655.                                SendDlgItemMessage (hwnd, USER_LISTBOX,
  656.                                             LB_INSERTSTRING, -1,
  657.                                             (LONG) (LPSTR) szBuffer);
  658.                                /* Update the parallel array */
  659.                                connNumberArray[j] = i;
  660.                                j++;
  661.  
  662.                             } /* end if */
  663.                         }  /* end for */
  664.  
  665.                         /* Specify in the status text to blank, after collecting */
  666.                         SetDlgItemText (hwnd, STEXT_COLLECTING,
  667.                                         (LPSTR) "");
  668.  
  669.                         /* Enable the server list box after collecting */
  670.                         hServerListBox = GetDlgItem (hwnd, SERVER_LISTBOX);
  671.                         EnableWindow (hServerListBox, TRUE);
  672.  
  673.                          /* Enable the redraw of the USER_LISTBOX after
  674.                             filling it with users */
  675.                          SendDlgItemMessage (hwnd, USER_LISTBOX,
  676.                                              WM_SETREDRAW, TRUE, 0L);
  677.  
  678.                         return TRUE;
  679.                      break; /* case LBN_SELCHANGE */
  680.                     } /* end switch (wParam) */
  681.  
  682.                break; /* case SERVER_LISTBOX */
  683.  
  684.               case USER_LISTBOX:
  685.                    switch (HIWORD (lParam))
  686.                     {
  687.                      case LBN_SELCHANGE:
  688.                         /* Enable the OK Button when a user is selected */
  689.                         hOKButton = GetDlgItem (hwnd, OK_BUTTON);
  690.                         EnableWindow (hOKButton, TRUE);
  691.                         return TRUE;
  692.                      break; /* case LBN_SELCHANGE */
  693.                     } /* end switch (wParam) */
  694.                break; /* case SERVER_LISTBOX */
  695.  
  696.                case OK_BUTTON:
  697.  
  698.                     /* Get the LoginName of the chat partner */
  699.                     index = (WORD) SendDlgItemMessage (hwnd,
  700.                                                        USER_LISTBOX,
  701.                                                        LB_GETCURSEL, 0, 0L);
  702.                     (WORD) SendDlgItemMessage (hwnd, USER_LISTBOX,
  703.                                                LB_GETTEXT, index,
  704.                                                (LONG) (LPSTR) szBuffer);
  705.  
  706.                     /* cut the connection number out of the user string */
  707.                     strcpy (szLoginName, (strchr (szBuffer, ' ') + 1));
  708.  
  709.                     /* Get the address of the station to send to */
  710.                     /* Sets global internetAddress to address */
  711.                     /* if successfully retrieved the internetAddress,
  712.                        end the dialog with TRUE, else end the dialog
  713.                        with false */
  714.  
  715.                     NWCcode = NWGetInternetAddress (conn,
  716.                                     connNumberArray[index],
  717.                                     (NWNET_ADDR NWFAR *) internetAddress);
  718.                     if (NWCcode)
  719.                      {
  720.                        sprintf (szBuffer,
  721.                              "Error on NWGetInternetAddress = %0X", NWCcode);
  722.                        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  723.                        EndDialog (hwnd, FALSE);
  724.                      }
  725.                      else
  726.                         EndDialog (hwnd, TRUE);
  727.                     return TRUE;
  728.                break; /* case OK_BUTTON */
  729.  
  730.  
  731.                case CANCEL_BUTTON:
  732.                     EndDialog (hwnd, FALSE);
  733.                     return TRUE;
  734.                break; /* end CANCEL_BUTTON */
  735.  
  736.                
  737.              }  /*end switch for wParam */
  738.  
  739.         break; /* case WM_COMMAND */
  740.  
  741.         } /* end switch for message */
  742.  
  743.     return FALSE;
  744.     } /*end CallDialogBoxProc*/
  745.  
  746. /**************************************************************************/
  747. /*                                                                        */
  748. /* PROTOCOL DIALOG BOX PROCEDURE - ProtocolCallDialogBoxProc              */
  749. /*                                                                        */
  750. /**************************************************************************/
  751.  
  752. BOOL FAR PASCAL ProtocolDialogBoxProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  753.     {
  754.  
  755.     switch (message)
  756.         {
  757.         case WM_INITDIALOG:
  758.  
  759.              /* set the default protocol to whichever is currently chosen.
  760.                 SPX is the default before one is chosen by the user. */
  761.             if (bIPX)
  762.                 SendDlgItemMessage(hwnd, RB_IPX, BM_SETCHECK, TRUE, 0L);
  763.             else if (bSPX)
  764.                 SendDlgItemMessage(hwnd, RB_SPX, BM_SETCHECK, TRUE, 0L);
  765.             else
  766.                 SendDlgItemMessage(hwnd, RB_TLI, BM_SETCHECK, TRUE, 0L);
  767.  
  768.             return TRUE;
  769.         break; /* case WM_INITDIALOG */
  770.  
  771.         case WM_COMMAND:
  772.             switch (wParam)
  773.              {
  774.                case OK_BUTTON:
  775.  
  776.                     /* Get the protocol to use */
  777.                     if (SendDlgItemMessage(hwnd, RB_IPX, BM_GETCHECK, TRUE, 0L))
  778.                         {
  779.                         bIPX = 1;
  780.                         bSPX = 0;
  781.                         bTLI = 0;
  782.                         }
  783.                     else
  784.                     if (SendDlgItemMessage(hwnd, RB_SPX, BM_GETCHECK, TRUE, 0L))
  785.                         {
  786.                         bSPX = 1;
  787.                         bIPX = 0;
  788.                         bTLI = 0;
  789.                         }
  790.                     else
  791.                         {
  792.                         bTLI =1;
  793.                         bIPX = 0;
  794.                         bSPX = 0;
  795.                         }
  796.  
  797.                     EndDialog (hwnd, TRUE);
  798.                break; /* case OK_BUTTON */
  799.  
  800.  
  801.                case CANCEL_BUTTON:
  802.                     EndDialog (hwnd, TRUE);
  803.                     return TRUE;
  804.                break; /* end CANCEL_BUTTON */
  805.  
  806.                
  807.              }  /*end switch for wParam */
  808.  
  809.         break; /* case WM_COMMAND */
  810.  
  811.         } /* end switch for message */
  812.  
  813.     return FALSE;
  814.     } /*end CallDialogBoxProc*/
  815.  
  816.  
  817. /**************************************************************************/
  818. /*                                                                        */
  819. /* Protocol Initialization Procedure - Initialize Protocol                */
  820. /*                                                                        */
  821. /**************************************************************************/
  822. int InitializeProtocol ()
  823.     {
  824.       WORD index; /* index of string inserted into list box */
  825.  
  826.       /* Prepare the initialization string based on the chosen protocol */
  827.       if (bIPX)
  828.           sprintf (szBuffer, "IPX Init... Preparing to chat with %s",
  829.                        szLoginName);
  830.       else if (bSPX)
  831.           sprintf (szBuffer, "SPX Init... Connecting with %s ....",
  832.                        szLoginName);
  833.       else
  834.           sprintf (szBuffer, "TLI(SPXII) Init...Connecting with %s ....",
  835.                        szLoginName);
  836.  
  837.       /* Add the prepared string to the list box */
  838.       index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  839.                                  LB_INSERTSTRING, -1,
  840.                                 (LONG)(LPSTR) szBuffer);
  841.       /* set the list box selection to the string inserted */
  842.       SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  843.                          LB_SETCURSEL, index,
  844.                          (LONG)(LPSTR) 0);
  845.  
  846.       connectionIsInitialized = TRUE;
  847.  
  848.       if (bIPX)
  849.           return InitializeIPX();
  850.       else if (bSPX)
  851.           return InitializeSPX();
  852.       else
  853.           return InitializeTLI();
  854.  
  855.     } /*end InitializeProtocol */
  856.  
  857.  
  858. /**************************************************************************/
  859. /*                                                                        */
  860. /* Data Packet Sending Procedure - SendDataPacket                         */
  861. /*                                                                        */
  862. /**************************************************************************/
  863. void SendDataPacket (char *dataToSend)
  864.     {
  865.      WORD index;  /* index into list box */
  866.  
  867.      strcpy (szBuffer, "YOU: ");
  868.      strcat (szBuffer, dataToSend);
  869.      index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  870.                         LB_INSERTSTRING, -1,
  871.                         (LONG)(LPSTR) szBuffer);
  872.      /* set the list box selection to the string inserted */
  873.      SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  874.                         LB_SETCURSEL, index,
  875.                         (LONG)(LPSTR) 0);
  876.  
  877.       if (bIPX)
  878.           SendIPXDataPacket (dataToSend);
  879.       else if (bSPX)
  880.           SendSPXDataPacket (dataToSend);
  881.       else
  882.           SendTLIDataPacket (dataToSend);
  883.  
  884.     } /*end InitializeProtocol */
  885.  
  886.  
  887. /**************************************************************************/
  888. /*                                                                        */
  889. /* Procedure to Process Received Data - ProcessReceivedData               */
  890. /*                                                                        */
  891. /**************************************************************************/
  892. void ProcessReceivedData ()
  893.     {
  894.       if (bIPX)
  895.         ProcessIPXData ();
  896.       else if (bSPX)
  897.         ProcessSPXData ();
  898.       else
  899.         ProcessTLIData ();
  900.  
  901.     } /*end ProcessReceiveData */
  902.  
  903.  
  904.  
  905.  
  906. /**************************************************************************/
  907. /*                                                                        */
  908. /* Protocol Termination - TerminateConnection                             */
  909. /*                                                                        */
  910. /**************************************************************************/
  911. void TerminateConnection ()
  912.     {
  913.       /* close the semaphore used in intialization to determine the first
  914.          instance in the function AmIFirst */
  915.       NWCcode = NWCloseSemaphore (conn, semaphoreHandle);
  916.       if (NWCcode)
  917.       {
  918.          sprintf (szBuffer, "Error on NWCloseSemaphore = %0X", NWCcode);
  919.          MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  920.       }
  921.  
  922.       if (bIPX)
  923.           TerminateIPX();
  924.       else if (bSPX)
  925.           TerminateSPX();
  926.       else
  927.           TerminateTLI();
  928.  
  929.     } /*end InitializeProtocol */
  930.  
  931.  
  932.  
  933. /**************************************************************************/
  934. /*                                                                        */
  935. /* IPX Protocol Initialization Procedure - InitializeIPX                  */
  936. /*                                                                        */
  937. /**************************************************************************/
  938. int InitializeIPX ()
  939.     {
  940.   WORD maxPacketSize;
  941.   int i,
  942.       imFirst; /* to determine which socket to use */
  943.   int transportTime;
  944.  
  945.      maxPacketSize = sizeof(IPXHeader) + sizeof(IPXReceiveBuffer[0]);
  946.      IPXTaskID = 0x00;
  947.      NWCcode = IPXInitialize ( (DWORD FAR *) &IPXTaskID,
  948.                               (WORD) MAX_ECBS,
  949.                               (WORD) maxPacketSize);
  950.  
  951.     if (NWCcode != SUCCESSFUL)
  952.      {
  953.        sprintf (szBuffer, "Error on IPXInitialize = %0X", NWCcode);
  954.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  955.        return FALSE;
  956.      }
  957.  
  958.     imFirst = AmIFirst();
  959.  
  960.     /* if you are the first to run the program, use the listen socket, else
  961.          use the connect socket */
  962.     if (imFirst)
  963.         {
  964.         socket = LISTEN_SOCKET;
  965.         destinationSocket = CONNECT_SOCKET;
  966.         }
  967.             else
  968.                 {
  969.                 socket = CONNECT_SOCKET;
  970.                 destinationSocket = LISTEN_SOCKET;
  971.                 }
  972.  
  973.     NWCcode = IPXOpenSocket (IPXTaskID, (WORD *) &socket,
  974.                              (BYTE) LONG_LIVED);
  975.     if (NWCcode)
  976.      {
  977.        sprintf (szBuffer, "Error on IPXOpenSocket = %0X", NWCcode);
  978.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  979.        return FALSE;
  980.      }
  981.  
  982.     /* Get a handle to the send ESR to be used later on sends in
  983.        the SendIPXDataPacket function */
  984.     lpfnIPXSendESRHandler = MakeProcInstance ((FARPROC) IPXSendESRHandler,
  985.                                               hInstance);
  986.  
  987.     /* Pre-Post all receive ECBs */
  988.     lpfnIPXReceiveESRHandler = MakeProcInstance (
  989.                                              (FARPROC) IPXReceiveESRHandler,
  990.                                              hInstance);
  991.  
  992.     NWCcode = IPXGetLocalTarget (IPXTaskID, (BYTE FAR *) internetAddress,
  993.                                  (BYTE FAR *) immediateAddress,
  994.                                  (int FAR *) &transportTime);
  995.     if (NWCcode)
  996.      {
  997.        sprintf (szBuffer, "Error on IPXGetLocalTarget = %0X", NWCcode);
  998.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  999.        return FALSE;
  1000.      }
  1001.  
  1002.     for (i=0; i<MAX_RECEIVE_ECBS; i++)
  1003.         {
  1004.         IPXReceiveECB[i].ESRAddress =
  1005.                                  (void (far *) ()) lpfnIPXReceiveESRHandler;
  1006.         IPXReceiveECB[i].socketNumber = socket;
  1007.         memcpy (&IPXReceiveECB[i].immediateAddress, immediateAddress, 6);
  1008.         IPXReceiveECB[i].fragmentCount = 2;
  1009.         IPXReceiveECB[i].fragmentDescriptor[0].address = &receiveIPXHeader[i];
  1010.         IPXReceiveECB[i].fragmentDescriptor[0].size = sizeof(IPXHeader);
  1011.         IPXReceiveBuffer[i].sequenceNumber = 0xFF;
  1012.         IPXReceiveECB[i].fragmentDescriptor[1].address = &IPXReceiveBuffer[i];
  1013.         IPXReceiveECB[i].fragmentDescriptor[1].size = sizeof(IPXReceiveBuffer[0]);
  1014.         IPXListenForPacket (IPXTaskID, &IPXReceiveECB[i]);
  1015.         }
  1016.     
  1017.     PostMessage (mainHwnd, CONNECTED_MESSAGE, 0, 0);
  1018.     return TRUE;
  1019.     } /*end InitializeIPX */
  1020.  
  1021. /**************************************************************************/
  1022. /*                                                                        */
  1023. /* Send IPX Data Packet Procedure - SendIPXDataPacket                     */
  1024. /*                                                                        */
  1025. /**************************************************************************/
  1026. void SendIPXDataPacket (char *dataToSend)
  1027.     {
  1028.     int i;
  1029.  
  1030.     i = sendSequenceNumber;
  1031.  
  1032.     /* If this ECB is currently in use, put up a message box and do not
  1033.        send */
  1034.     if (IPXSendECB[i].inUseFlag) 
  1035.         {
  1036.     /*     MessageBox (NULL, "All ECBs are in Use.\nData not sent.",
  1037.                     "Try Again", MB_OK);
  1038.     */
  1039.     /*     return; */
  1040.            IPXRelinquishControl();
  1041.            Yield();
  1042.         }
  1043.  
  1044.     IPXSendECB[i].ESRAddress =
  1045.                              (void (far *) ()) lpfnIPXSendESRHandler;
  1046.     IPXSendECB[i].socketNumber = socket;
  1047.     memcpy (&IPXSendECB[i].immediateAddress, immediateAddress, 6);
  1048.     * (WORD *) sendIPXHeader[i].destination.socket = destinationSocket;
  1049.     memcpy (&sendIPXHeader[i].destination.network, internetAddress, 10);
  1050.     sendIPXHeader[i].packetType = 4;  /* IPX packet type */
  1051.     IPXSendECB[i].fragmentCount = 2;
  1052.     IPXSendECB[i].fragmentDescriptor[0].address = &sendIPXHeader[i];
  1053.     IPXSendECB[i].fragmentDescriptor[0].size = sizeof(IPXHeader);
  1054.     IPXSendBuffer[i].sequenceNumber = i;
  1055.     strcpy (IPXSendBuffer[i].data, dataToSend);
  1056.     IPXSendECB[i].fragmentDescriptor[1].address = &IPXSendBuffer[i];
  1057.     IPXSendECB[i].fragmentDescriptor[1].size = sizeof(IPXSendBuffer[i]);
  1058.  
  1059.     IPXSendPacket (IPXTaskID, (ECB far *) &IPXSendECB[i]);
  1060.     sendSequenceNumber = (sendSequenceNumber + 1) % MAX_SEND_ECBS;
  1061.  
  1062.     } /*end SendIPXDataPacket */
  1063.  
  1064. /**************************************************************************/
  1065. /*                                                                        */
  1066. /* IPX Data Processing Procedure - ProcessIPXData                         */
  1067. /*                                                                        */
  1068. /**************************************************************************/
  1069. void ProcessIPXData ()
  1070.     {
  1071.     WORD index;
  1072.     int i;
  1073.  
  1074.     for (i=0; i < MAX_RECEIVE_ECBS; i++)
  1075.         {
  1076.         if (IPXReceiveBuffer[i].sequenceNumber == receiveSequenceNumber)
  1077.             {
  1078.               /* Add the person that sent the string to the data before adding
  1079.               it to the list box */
  1080.               sprintf (szBuffer, "%s: ", szLoginName);
  1081.               strcat (szBuffer, IPXReceiveBuffer[i].data);
  1082.  
  1083.               receiveSequenceNumber = (receiveSequenceNumber + 1) %
  1084.                                        MAX_RECEIVE_ECBS;
  1085.               index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1086.                                      LB_INSERTSTRING, -1,
  1087.                                      (LONG)(LPSTR) szBuffer);
  1088.  
  1089.               if (index == LB_ERRSPACE)
  1090.                 {
  1091.                  MessageBox (mainHwnd, "No more space in list box.",
  1092.                              "End program", MB_OK);
  1093.                  PostMessage (mainHwnd, WM_COMMAND, HANGUP_BUTTON, 0);
  1094.                 }
  1095.               /* set the list box selection to the string inserted */
  1096.               SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1097.                                 LB_SETCURSEL, index,
  1098.                                 (LONG)(LPSTR) 0);
  1099.  
  1100.               /* Repost the ECB */
  1101.               IPXReceiveECB[i].ESRAddress =
  1102.                                   (void (far *) ()) lpfnIPXReceiveESRHandler;
  1103.               IPXReceiveECB[i].socketNumber = socket;
  1104.               IPXReceiveECB[i].fragmentCount = 2;
  1105.               IPXReceiveECB[i].fragmentDescriptor[0].address =
  1106.                                                         &receiveIPXHeader[i];
  1107.               IPXReceiveECB[i].fragmentDescriptor[0].size = sizeof(IPXHeader);
  1108.               IPXReceiveBuffer[i].sequenceNumber = 0xFF;
  1109.               IPXReceiveECB[i].fragmentDescriptor[1].address =
  1110.                                                        &IPXReceiveBuffer[i];
  1111.               IPXReceiveECB[i].fragmentDescriptor[1].size =
  1112.                                                  sizeof(IPXReceiveBuffer[i]);
  1113.               IPXListenForPacket (IPXTaskID, &IPXReceiveECB[i]);
  1114.  
  1115.               /* set the count back to 0 to search through the list for the
  1116.                  next message */
  1117.               i = 0;
  1118.             } /* end if */
  1119.         } /*end for */
  1120.  
  1121.     } /*end ProcessIPXData */
  1122.  
  1123. /**************************************************************************/
  1124. /*                                                                        */
  1125. /* IPX Terminate Connection Procedure - TerminateIPX                      */
  1126. /*                                                                        */
  1127. /**************************************************************************/
  1128. void TerminateIPX ()
  1129.     {
  1130.  
  1131.    IPXCloseSocket (IPXTaskID, socket);
  1132.  
  1133.    NWCcode = IPXSPXDeinit (IPXTaskID);
  1134.  
  1135.    if (NWCcode)
  1136.     {
  1137.       sprintf (szBuffer, "Error on IPXSPXDeinit = %0X", NWCcode);
  1138.       MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  1139.     }
  1140.  
  1141.    MessageBox(NULL, "Terminated IPX session", "goodbye", MB_OK); 
  1142.  
  1143.    } /* end TerminateIPX */
  1144.  
  1145. /**************************************************************************/
  1146. /*                                                                        */
  1147. /* IPX Receive ESR Handler function - IPXReceiveESRHandler                */
  1148. /*                                                                        */
  1149. /**************************************************************************/
  1150. void FAR PASCAL IPXReceiveESRHandler ()
  1151.     {
  1152.  
  1153.       PostMessage (mainHwnd, DATA_RECEIVED_MESSAGE, 0, 0);
  1154.  
  1155.     } /* end IPXReceiveESRHandler */
  1156.  
  1157. /**************************************************************************/
  1158. /*                                                                        */
  1159. /* IPX Send ESR Handler function - IPXSendESRHandler                      */
  1160. /*                                                                        */
  1161. /**************************************************************************/
  1162. void FAR PASCAL IPXSendESRHandler ()
  1163.     {
  1164.  
  1165.       PostMessage (mainHwnd, DATA_SENT_MESSAGE, 0, 0);
  1166.  
  1167.     } /* end IPXSendESRHandler */
  1168.  
  1169.  
  1170. /**************************************************************************/
  1171. /*                                                                        */
  1172. /* SPX Protocol Initialization Procedure - InitializeSPX                  */
  1173. /*                                                                        */
  1174. /**************************************************************************/
  1175. int InitializeSPX ()
  1176.     {
  1177.   int i,
  1178.       imFirst; /* to determine whether to listen or connect */
  1179.   BYTE
  1180.      majorRevisionNumber,
  1181.      minorRevisionNumber;
  1182.    WORD
  1183.      maxSPXConnections,    
  1184.      availableConnections,
  1185.      maxPacketSize;
  1186.  
  1187.      maxPacketSize = sizeof(SPXHeader) + sizeof(SPXReceiveBuffer[0]);
  1188.      IPXTaskID = 0x00;
  1189.      NWCcode = SPXInitialize ( (DWORD FAR *) &IPXTaskID,
  1190.                               (WORD) MAX_ECBS,
  1191.                               (WORD) maxPacketSize,
  1192.                               (BYTE FAR *) &majorRevisionNumber,
  1193.                               (BYTE FAR *) &minorRevisionNumber,
  1194.                               (WORD FAR *) &maxSPXConnections,
  1195.                               (WORD FAR *) &availableConnections);
  1196.  
  1197.     if (NWCcode != SPX_INSTALLED)
  1198.      {
  1199.        sprintf (szBuffer, "Error on SPXInitialize = %0X", NWCcode);
  1200.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  1201.        return FALSE;
  1202.      }
  1203.  
  1204.     imFirst = AmIFirst();
  1205.  
  1206.     /* if you are the first to run the program, listen, else connect */
  1207.     if (imFirst)
  1208.         socket = LISTEN_SOCKET;
  1209.             else socket = CONNECT_SOCKET;
  1210.  
  1211.     NWCcode = IPXOpenSocket (IPXTaskID, (WORD *) &socket,
  1212.                              (BYTE) LONG_LIVED);
  1213.     if (NWCcode)
  1214.      {
  1215.        sprintf (szBuffer, "Error on IPXOpenSocket = %0X", NWCcode);
  1216.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  1217.        return FALSE;
  1218.      }
  1219.  
  1220.     /* Get a handle to the send ESR to be used later on sends in
  1221.        the SendSPXDataPacket function */
  1222.     lpfnSPXSendESRHandler = MakeProcInstance ((FARPROC) SPXSendESRHandler,
  1223.                                               hInstance);
  1224.  
  1225.     /* Pre-Post all receive ECBs */
  1226.     lpfnSPXReceiveESRHandler = MakeProcInstance ((FARPROC) SPXReceiveESRHandler,
  1227.                                               hInstance);
  1228.     for (i=0; i<MAX_RECEIVE_ECBS; i++)
  1229.         {
  1230.         SPXReceiveECB[i].ESRAddress =
  1231.                                  (void (far *) ()) lpfnSPXReceiveESRHandler;
  1232.         SPXReceiveECB[i].socketNumber = socket;
  1233.         SPXReceiveECB[i].fragmentCount = 2;
  1234.         SPXReceiveECB[i].fragmentDescriptor[0].address = &receiveSPXHeader[i];
  1235.         SPXReceiveECB[i].fragmentDescriptor[0].size = sizeof(SPXHeader);
  1236.         SPXReceiveBuffer[i].sequenceNumber = 0xFF;
  1237.         SPXReceiveECB[i].fragmentDescriptor[1].address = &SPXReceiveBuffer[i];
  1238.         SPXReceiveECB[i].fragmentDescriptor[1].size = sizeof(SPXReceiveBuffer[0]);
  1239.         SPXListenForSequencedPacket (IPXTaskID, &SPXReceiveECB[i]);
  1240.         }
  1241.  
  1242.     /* listen or connect */
  1243.     if (imFirst)
  1244.         return SPXListen();
  1245.          else return SPXConnect();
  1246.     } /*end InitializeSPX */
  1247.  
  1248. /**************************************************************************/
  1249. /*                                                                        */
  1250. /* Function to determine first instance of application - AmIFirst         */
  1251. /*                                                                        */
  1252. /**************************************************************************/
  1253. int AmIFirst ()
  1254.     {
  1255.  
  1256.    /* variables for opening semaphore */
  1257.    char semaphoreName[20] = "CommSema";
  1258.    NWSEM_INT initialValue;
  1259.    NWNUMBER semaphoreOpenCount;
  1260.    NWTICKS timeOutValue;
  1261.  
  1262.     /* Open semaphore.  If first to get the semaphore, use the LISTEN_SOCKET,
  1263.     if second, use the CONNECT_SOCKET */
  1264.     initialValue = 1;  /* one handle to the resource allowed */
  1265.     NWCcode = NWOpenSemaphore (conn,
  1266.                                (char NWFAR *) semaphoreName,
  1267.                                initialValue,
  1268.                                (NWSEM_HANDLE NWFAR *) &semaphoreHandle,
  1269.                                (NWNUMBER NWFAR *) &semaphoreOpenCount);
  1270.     if (NWCcode != 0)
  1271.        {
  1272.          sprintf (szBuffer, "Open Semaphore, %s, failed", semaphoreName);
  1273.          MessageBox (NULL, szBuffer, "Open Failure", MB_OK);
  1274.          return FALSE;
  1275.        }
  1276.  
  1277.     /* Wait on the Semaphore */
  1278.     timeOutValue = 0;  /* no wait */
  1279.     NWCcode = NWWaitOnSemaphore (conn,
  1280.                                  semaphoreHandle,
  1281.                                  timeOutValue);
  1282.  
  1283.     if (NWCcode != 0) /* You're not first, semaphore already in use */
  1284.        {
  1285.          return FALSE;
  1286.        }
  1287.     else  /* You're first */
  1288.        {
  1289.          return TRUE;
  1290.         }
  1291.  
  1292.     } /*end AmIFirst */
  1293.  
  1294. /**************************************************************************/
  1295. /*                                                                        */
  1296. /* SPX Listen for Connection Function - SPXListen                         */
  1297. /*                                                                        */
  1298. /**************************************************************************/
  1299. int SPXListen ()
  1300.     {
  1301.     lpfnSPXListenESRHandler = MakeProcInstance ((FARPROC) SPXListenESRHandler,
  1302.                                               hInstance);
  1303.     SPXListenECB.ESRAddress = (void (far *) ()) lpfnSPXListenESRHandler;
  1304.     SPXListenECB.socketNumber = LISTEN_SOCKET;
  1305.     SPXListenECB.fragmentCount = 1;
  1306.     SPXListenECB.fragmentDescriptor[0].address = &listenSPXHeader;
  1307.     SPXListenECB.fragmentDescriptor[0].size = sizeof(SPXHeader);
  1308.  
  1309.     /* Listen for connection */
  1310.     SPXListenForConnection (IPXTaskID, 0x00, 0xFF,
  1311.                             (ECB FAR *) &SPXListenECB);
  1312.     return TRUE;
  1313.  
  1314.     }
  1315. /**************************************************************************/
  1316. /*                                                                        */
  1317. /* SPX Connect to the listening side Function - SPXConnect                */
  1318. /*                                                                        */
  1319. /**************************************************************************/
  1320. int SPXConnect ()
  1321.     {
  1322.     lpfnSPXConnectESRHandler = MakeProcInstance (
  1323.                                              (FARPROC) SPXConnectESRHandler,
  1324.                                              hInstance);
  1325.     SPXConnectECB.ESRAddress = (void (far *) ()) lpfnSPXConnectESRHandler;
  1326.     SPXConnectECB.socketNumber = CONNECT_SOCKET;
  1327.     SPXConnectECB.fragmentCount = 1;
  1328.     SPXConnectECB.fragmentDescriptor[0].address = &connectSPXHeader;
  1329.     SPXConnectECB.fragmentDescriptor[0].size = sizeof(SPXHeader);
  1330.     /* Copy network (4) and node (6) to the destination address */
  1331.     memcpy (connectSPXHeader.destination.network, internetAddress, 10);
  1332.     * (WORD *) connectSPXHeader.destination.socket = LISTEN_SOCKET;
  1333.     /* Establish connection */
  1334.     NWCcode = SPXEstablishConnection (IPXTaskID, 0x00, 0xFF,
  1335.                                       (WORD FAR *) &SPXConnectionID,
  1336.                                       (ECB far *) &SPXConnectECB);
  1337.     if (NWCcode)
  1338.      {
  1339.        sprintf (szBuffer, "Error on SPXEstablishConnection = %0X", NWCcode);
  1340.        MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  1341.        return FALSE;
  1342.      }
  1343.     return TRUE;
  1344.  
  1345.     }
  1346.  
  1347. /**************************************************************************/
  1348. /*                                                                        */
  1349. /* Send SPX Data Packet Procedure - SendSPXDataPacket                     */
  1350. /*                                                                        */
  1351. /**************************************************************************/
  1352. void SendSPXDataPacket (char *dataToSend)
  1353.     {
  1354.  
  1355.     #define END_OF_MESSAGE 0x10     /* End of message marker for SPX */
  1356.  
  1357.     int i;
  1358.  
  1359.     i = sendSequenceNumber;
  1360.  
  1361.     /* If this ECB is currently in use, put up a message box and do not
  1362.        send */
  1363.     if (SPXSendECB[i].inUseFlag) 
  1364.         {
  1365.     /*     MessageBox (NULL, "All ECBs are in Use.\nData not sent.",
  1366.                     "Try Again", MB_OK);
  1367.     */
  1368.     /*     return; */
  1369.            IPXRelinquishControl();
  1370.            Yield();
  1371.         }
  1372.  
  1373.     SPXSendECB[i].ESRAddress = (void (far *) ()) lpfnSPXSendESRHandler;
  1374.     SPXSendECB[i].fragmentCount = 2;
  1375.     SPXSendECB[i].fragmentDescriptor[0].address = &sendSPXHeader[i];
  1376.     SPXSendECB[i].fragmentDescriptor[0].size = sizeof(SPXHeader);
  1377.     SPXSendBuffer[i].sequenceNumber = i;
  1378.     strcpy (SPXSendBuffer[i].data, dataToSend);
  1379.     SPXSendECB[i].fragmentDescriptor[1].address = &SPXSendBuffer[i];
  1380.     SPXSendECB[i].fragmentDescriptor[1].size = sizeof(SPXSendBuffer[i]);
  1381.     sendSPXHeader[i].connectionControl = END_OF_MESSAGE;
  1382.     sendSPXHeader[i].dataStreamType = 0x00;
  1383.  
  1384.     SPXSendSequencedPacket (IPXTaskID, SPXConnectionID,
  1385.                             (ECB far *) &SPXSendECB[i]);
  1386.  
  1387.     sendSequenceNumber = (sendSequenceNumber + 1) % MAX_SEND_ECBS;
  1388.     } /*end SendSPXDataPacket */
  1389.  
  1390. /**************************************************************************/
  1391. /*                                                                        */
  1392. /* SPX Data Processing Procedure - ProcessSPXData                         */
  1393. /*                                                                        */
  1394. /**************************************************************************/
  1395. void ProcessSPXData ()
  1396.     {
  1397.     int i;
  1398.     WORD index;
  1399.  
  1400.     for (i=0; i < MAX_RECEIVE_ECBS; i++)
  1401.         {
  1402.         if (SPXReceiveBuffer[i].sequenceNumber == receiveSequenceNumber)
  1403.             {
  1404.               /* Add the person that sent the string to the data before adding
  1405.               it to the list box */
  1406.               sprintf (szBuffer, "%s: ", szLoginName);
  1407.               strcat (szBuffer, SPXReceiveBuffer[i].data);
  1408.  
  1409.               receiveSequenceNumber = (receiveSequenceNumber + 1) %
  1410.                                        MAX_RECEIVE_ECBS;
  1411.               index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1412.                                      LB_INSERTSTRING, -1,
  1413.                                      (LONG)(LPSTR) szBuffer);
  1414.  
  1415.               if (index == LB_ERRSPACE)
  1416.                 {
  1417.                  MessageBox (mainHwnd, "No more space in list box.",
  1418.                              "End program", MB_OK);
  1419.                  PostMessage (mainHwnd, WM_COMMAND, HANGUP_BUTTON, 0);
  1420.                 }
  1421.               /* set the list box selection to the string inserted */
  1422.               SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1423.                                  LB_SETCURSEL, index,
  1424.                                 (LONG)(LPSTR) 0);
  1425.  
  1426.               /* Repost the ECB */
  1427.               SPXReceiveECB[i].ESRAddress =
  1428.                                  (void (far *) ()) lpfnSPXReceiveESRHandler;
  1429.               SPXReceiveECB[i].socketNumber = socket;
  1430.               SPXReceiveECB[i].fragmentCount = 2;
  1431.               SPXReceiveECB[i].fragmentDescriptor[0].address =
  1432.                                                      &receiveSPXHeader[i];
  1433.               SPXReceiveECB[i].fragmentDescriptor[0].size = sizeof(SPXHeader);
  1434.               SPXReceiveBuffer[i].sequenceNumber = 0xFF;
  1435.               SPXReceiveECB[i].fragmentDescriptor[1].address =
  1436.                                                         &SPXReceiveBuffer[i];
  1437.               SPXReceiveECB[i].fragmentDescriptor[1].size =
  1438.                                                  sizeof(SPXReceiveBuffer[0]);
  1439.               SPXListenForSequencedPacket (IPXTaskID, &SPXReceiveECB[i]);
  1440.  
  1441.               /* set the count back to 0 to search through the list for the
  1442.                  next message */
  1443.               i = 0;
  1444.             } /* end if */
  1445.         } /*end for */
  1446.  
  1447.     } /*end ProcessSPXData */
  1448.  
  1449.  
  1450. /**************************************************************************/
  1451. /*                                                                        */
  1452. /* SPX Terminate Connection Procedure - TerminateSPX                      */
  1453. /*                                                                        */
  1454. /**************************************************************************/
  1455. void TerminateSPX ()
  1456.     {
  1457.  
  1458.     lpfnSPXTerminateESRHandler = MakeProcInstance (
  1459.                                          (FARPROC) SPXTerminateESRHandler,
  1460.                                           hInstance);
  1461.     SPXConnectECB.ESRAddress = (void (far *) ()) lpfnSPXTerminateESRHandler;
  1462.     SPXConnectECB.fragmentCount = 1;
  1463.     SPXConnectECB.fragmentDescriptor[0].address = &connectSPXHeader;
  1464.     SPXConnectECB.fragmentDescriptor[0].size = sizeof(SPXHeader);
  1465.     SPXTerminateConnection (IPXTaskID, SPXConnectionID,
  1466.                             (ECB FAR *) &SPXConnectECB);
  1467.  
  1468.     IPXCloseSocket (IPXTaskID, socket);
  1469.  
  1470.     NWCcode = IPXSPXDeinit (IPXTaskID);
  1471.  
  1472.    if (NWCcode)
  1473.     {
  1474.       sprintf (szBuffer, "Error on IPXSPXDeinit = %0X", NWCcode);
  1475.       MessageBox (NULL, szBuffer, "ERROR", MB_OK);
  1476.     }
  1477.  
  1478.     } /* end TerminateSPX */
  1479.  
  1480. /**************************************************************************/
  1481. /*                                                                        */
  1482. /* SPX Receive ESR Handler function - SPXReceiveESRHandler                */
  1483. /*                                                                        */
  1484. /**************************************************************************/
  1485. void FAR PASCAL SPXReceiveESRHandler ()
  1486.     {
  1487.      
  1488.       PostMessage (mainHwnd, DATA_RECEIVED_MESSAGE, 0, 0);
  1489.  
  1490.     } /* end SPXReceiveESRHandler */
  1491.  
  1492. /**************************************************************************/
  1493. /*                                                                        */
  1494. /* SPX Send ESR Handler function - SPXSendESRHandler                      */
  1495. /*                                                                        */
  1496. /**************************************************************************/
  1497. void FAR PASCAL SPXSendESRHandler ()
  1498.     {
  1499.       
  1500.       PostMessage (mainHwnd, DATA_SENT_MESSAGE, 0, 0);
  1501.  
  1502.     } /* end SPXSendESRHandler */
  1503.  
  1504. /**************************************************************************/
  1505. /*                                                                        */
  1506. /* SPX Listen ESR Handler function - SPXListenESRHandler                  */
  1507. /*                                                                        */
  1508. /**************************************************************************/
  1509. void FAR PASCAL SPXListenESRHandler ()
  1510.     {
  1511. WORD ECBSegment, ECBOffset;
  1512. ECB far *ECBIn;
  1513.  
  1514.       __asm mov ECBSegment, es;
  1515.       __asm mov ECBOffset, si;
  1516.  
  1517.       /* Macros for Building an address with Microsoft C*/
  1518.       _FP_OFF(ECBIn) = ECBOffset;
  1519.       _FP_SEG(ECBIn) = ECBSegment;
  1520.  
  1521.       /* Macro for building an address with Borland C*/
  1522.      /* ECBIn = MK_FP (ECBSegment, ECBOffset);*/
  1523.  
  1524.  
  1525.       /* Set the SPX connection ID to the established connection */
  1526. /*      SPXConnectionID = *(WORD *) SPXListenECB.IPXWorkspace; */
  1527.       SPXConnectionID = *(WORD FAR *) (ECBIn->IPXWorkspace); 
  1528.  
  1529.       PostMessage (mainHwnd, CONNECTED_MESSAGE, 0, 0);
  1530.     } /* end SPXListenESRHandler */
  1531.  
  1532. /**************************************************************************/
  1533. /*                                                                        */
  1534. /* SPX Connect ESR Handler function - SPXConnectESRHandler                */
  1535. /*                                                                        */
  1536. /**************************************************************************/
  1537. void FAR PASCAL SPXConnectESRHandler ()
  1538.     {
  1539.       PostMessage (mainHwnd, CONNECTED_MESSAGE, 0, 0);
  1540.     } /* end SPXConnectESRHandler */
  1541.  
  1542. /**************************************************************************/
  1543. /*                                                                        */
  1544. /* SPXTerminate ESR Handler function - SPXTerminateESRHandler             */
  1545. /*                                                                        */
  1546. /**************************************************************************/
  1547. void FAR PASCAL SPXTerminateESRHandler ()
  1548.     {
  1549.       MessageBox(NULL, "Connection Terminated", "goodbye", MB_OK);  
  1550.  
  1551.     } /* end SPXTerminateESRHandler */
  1552.  
  1553. /**************************************************************************/
  1554. /*                                                                        */
  1555. /* TLI Protocol Initialization Procedure - InitializeTLI                  */
  1556. /*                                                                        */
  1557. /**************************************************************************/
  1558. int InitializeTLI ()
  1559.     {
  1560.     int initStatus;
  1561.     int imFirst;
  1562.  
  1563.     fh = t_open ("/dev/nspx", O_RDWR, (struct t_info far *) NULL);
  1564.     if (fh == -1)
  1565.        {
  1566.      t_error ("t_open failed");
  1567.      return FALSE;
  1568.        }
  1569.  
  1570.     /* if you are the first to run the program, listen, else connect */
  1571.     imFirst = AmIFirst();
  1572.  
  1573.     /* Listen or Connect */
  1574.     if (imFirst)
  1575.       initStatus = TLIListen();
  1576.            else initStatus = TLIConnect();
  1577.  
  1578.     /* if the initialization is successful, put the connection into
  1579.        non-blocking mode (for semi-asynchronous receiving), start a
  1580.        receive timer and send a connected message */
  1581.     if (initStatus)
  1582.         {
  1583.          t_nonblocking (fh);
  1584.  
  1585.          if (!SetTimer (mainHwnd, TLI_RECEIVE_TIMER, 1000, NULL))
  1586.            {
  1587.              MessageBox (NULL, "No More timers available", "ERROR", MB_OK);
  1588.              return FALSE;
  1589.            }
  1590.  
  1591.          PostMessage (mainHwnd, CONNECTED_MESSAGE, 0, 0);
  1592.         }
  1593.  
  1594.     return initStatus;
  1595.  
  1596.     } /*end InitializeTLI */
  1597.  
  1598. /**************************************************************************/
  1599. /*                                                                        */
  1600. /* TLI Listen for Connection Procedure - TLIListen                        */
  1601. /*                                                                        */
  1602. /**************************************************************************/
  1603. int TLIListen ()
  1604.     {
  1605.     IPX_ADDR spx_addr;
  1606.     SPX_OPTS spx_opts;
  1607.     struct t_bind tbind;
  1608.     struct t_call tcall;
  1609.  
  1610.     *(WORD *) spx_addr.ipxa_socket = LISTEN_SOCKET;
  1611.     tbind.addr.maxlen = sizeof(spx_addr);
  1612.     tbind.addr.len = sizeof(spx_addr);
  1613.     tbind.addr.buf = (char *) &spx_addr;
  1614.     tbind.qlen = 1;  /* Only 1 connection allowed */
  1615.  
  1616.     if (t_bind (fh, (struct t_bind far *) &tbind,
  1617.         (struct t_bind far *) &tbind) == -1)
  1618.  
  1619.        {
  1620.      t_error ("t_bind failed");
  1621.          return FALSE;
  1622.        }
  1623.  
  1624.     tcall.addr.maxlen = sizeof(spx_addr);
  1625.     tcall.addr.len = sizeof(spx_addr);
  1626.     tcall.addr.buf = (char *) &spx_addr;
  1627.  
  1628.     spx_opts.spx_connectionID[0] = 0;
  1629.     spx_opts.spx_connectionID[1] = 0;
  1630.     spx_opts.spx_allocationNumber[0] = 0;
  1631.     spx_opts.spx_allocationNumber[1] = 0;
  1632.  
  1633.     tcall.opt.maxlen = 0;
  1634.     tcall.opt.len = 0;
  1635.     tcall.opt.buf = (char *) NULL;
  1636.      
  1637.     tcall.udata.maxlen = 0;
  1638.     tcall.udata.len = 0;
  1639.     tcall.udata.buf = (char *) NULL;
  1640.  
  1641.     if (t_listen (fh, (struct t_call far *) &tcall) == -1)
  1642.        {
  1643.         t_error ((char far *) "t_listen failed");
  1644.         return FALSE;
  1645.        }
  1646.  
  1647.     if (t_accept (fh, fh, (struct t_call far *) &tcall) == -1)
  1648.        {
  1649.         t_error ((char far *) "t_accept failed");
  1650.         return FALSE;
  1651.        }
  1652.     return TRUE;
  1653.     } /* end TLIListen */
  1654.  
  1655. /**************************************************************************/
  1656. /*                                                                        */
  1657. /* TLI Connect Procedure - TLIConnect                                     */
  1658. /*                                                                        */
  1659. /**************************************************************************/
  1660. int TLIConnect ()
  1661.     {
  1662.     IPX_ADDR spx_addr;
  1663.     SPX_OPTS spx_opts;
  1664.     struct t_bind tbind;
  1665.     struct t_call tcall;
  1666.  
  1667.     *(WORD *) spx_addr.ipxa_socket = CONNECT_SOCKET;
  1668.     tbind.addr.len = sizeof(spx_addr);
  1669.     tbind.addr.maxlen = sizeof(spx_addr);
  1670.     tbind.addr.buf = (char *) &spx_addr;
  1671.  
  1672.  
  1673.     if (t_bind (fh, (struct t_bind far *) &tbind,
  1674.         (struct t_bind far *) &tbind) == -1)
  1675.  
  1676.        {
  1677.      t_error ("t_bind failed");
  1678.          return FALSE;
  1679.        }
  1680.  
  1681.     *(WORD *) spx_addr.ipxa_socket = LISTEN_SOCKET;
  1682.     /* copy network (4) and node (6) to the destination address */
  1683.     memcpy (&spx_addr.ipxa_net, internetAddress, 10);
  1684.     tcall.addr.maxlen = sizeof (spx_addr);
  1685.     tcall.addr.len = sizeof (spx_addr);
  1686.     tcall.addr.buf = (char *) &spx_addr;
  1687.  
  1688.     spx_opts.spx_connectionID[0] = 0;
  1689.     spx_opts.spx_connectionID[1] = 0;
  1690.     spx_opts.spx_allocationNumber[0] = 0;
  1691.     spx_opts.spx_allocationNumber[1] = 0;
  1692.  
  1693.     tcall.opt.maxlen = 0;
  1694.     tcall.opt.len = 0;
  1695.     tcall.opt.buf = (char *) NULL;
  1696.      
  1697.     tcall.udata.maxlen = 0;
  1698.     tcall.udata.len = 0;
  1699.     tcall.udata.buf = (char *) NULL;
  1700.  
  1701.     if (t_connect (fh, (struct t_call far *) &tcall, 
  1702.                    (struct t_call far *) &tcall) == -1)
  1703.        {
  1704.         t_error ((char far *) "t_connect failed");
  1705.         return FALSE;
  1706.        }
  1707.      
  1708.     return TRUE;
  1709.     } /* end TLIConnect */
  1710.  
  1711.  
  1712. /**************************************************************************/
  1713. /*                                                                        */
  1714. /* Send TLI Data Packet Procedure - SendTLIDataPacket                     */
  1715. /*                                                                        */
  1716. /**************************************************************************/
  1717. void SendTLIDataPacket (char *dataToSend)
  1718.     {
  1719.  
  1720.     SPXSendBuffer[0].sequenceNumber = sendSequenceNumber;
  1721.     strcpy (SPXSendBuffer[0].data, dataToSend);
  1722.  
  1723.     if (t_snd (fh, (char far *) &SPXSendBuffer[0], sizeof(SPXSendBuffer[0]),
  1724.                                  0) == -1)
  1725.       {
  1726.         t_error ("t_snd Failed ");
  1727.       }
  1728.  
  1729.       else
  1730.         sendSequenceNumber = (sendSequenceNumber + 1) % MAX_SEND_ECBS;
  1731.  
  1732.     } /*end SendTLIDataPacket */
  1733.  
  1734.  
  1735. /**************************************************************************/
  1736. /*                                                                        */
  1737. /* TLI Test for Receive Procedure - TLITestForReceive                     */
  1738. /*                                                                        */
  1739. /**************************************************************************/
  1740. void TLITestForReceive ()
  1741.     {
  1742.     WORD index;
  1743.     int flags;
  1744.     int i;
  1745.  
  1746.     i = receiveSequenceNumber;
  1747.  
  1748.  
  1749.     /* if data has been received, add it to the list box */
  1750.     if (t_rcv (fh, (char far *) &SPXReceiveBuffer[i],
  1751.                  sizeof(SPXReceiveBuffer[i]), (int far *) &flags) != -1)
  1752.        {
  1753.  
  1754.          /* Add the person that sent the string to the data before adding
  1755.             it to the list box */
  1756.          sprintf (szBuffer, "%s: ", szLoginName);
  1757.          strcat (szBuffer, SPXReceiveBuffer[i].data);
  1758.  
  1759.          receiveSequenceNumber = (receiveSequenceNumber + 1) %
  1760.                                   MAX_RECEIVE_ECBS;
  1761.          index = SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1762.                                 LB_INSERTSTRING, -1,
  1763.                                 (LONG)(LPSTR) szBuffer);
  1764.  
  1765.          if (index == LB_ERRSPACE)
  1766.             {
  1767.              MessageBox (mainHwnd, "No more space in list box.",
  1768.                         "End program", MB_OK);
  1769.              PostMessage (mainHwnd, WM_COMMAND, HANGUP_BUTTON, 0);
  1770.              }
  1771.          /* set the list box selection to the string inserted */
  1772.          SendDlgItemMessage(mainHwnd, MESSAGE_LISTBOX,
  1773.                             LB_SETCURSEL, index,
  1774.                             (LONG)(LPSTR) 0);
  1775.  
  1776.        }
  1777.     } /*end TLITestForReceive */
  1778.  
  1779. /**************************************************************************/
  1780. /*                                                                        */
  1781. /* TLI Data Processing Procedure - ProcessTLIData                         */
  1782. /*                                                                        */
  1783. /**************************************************************************/
  1784. void ProcessTLIData ()
  1785.     {
  1786.  
  1787.     } /*end ProcessTLIData */
  1788.  
  1789. /**************************************************************************/
  1790. /*                                                                        */
  1791. /* TLI Terminate Connection Procedure - TerminateTLI                      */
  1792. /*                                                                        */
  1793. /**************************************************************************/
  1794. void TerminateTLI ()
  1795.    {
  1796.  
  1797.    KillTimer (mainHwnd, TLI_RECEIVE_TIMER);
  1798.  
  1799.    if (t_close (fh) == -1)
  1800.       {
  1801.         t_error ("t_close Failed ");
  1802.       }
  1803.  
  1804.  
  1805.    } /* end TerminateTLI */
  1806.  
  1807. /***************************************************************************/
  1808. /* Draw3DRect                                                              */
  1809. /*  This routine draws a 3D rectangle as described                         */
  1810. /***************************************************************************/
  1811. void Draw3DRect(HDC  hDC,
  1812.                 int  top,
  1813.                 int  left,
  1814.                 int  bottom,
  1815.                 int  right,
  1816.                 int  bInOut,    /* 0 = 3D IN, 1 = 3D OUT */
  1817.                 int  RectWidth)
  1818. {
  1819. RECT   OurRect;
  1820. RECT   TempRECT;
  1821. short  i;
  1822. HPEN   hDkGrayPen;
  1823.  
  1824.   /* create a dark gray pen for drawing 3D box shadows */
  1825.   hDkGrayPen = CreatePen(PS_SOLID,            /* style */
  1826.                          0,                   /* width (0 = 1 pixel) */
  1827.                          RGB(128, 128, 128)); /* color */
  1828.  
  1829.   /* make a copy of the RECT */
  1830.   OurRect.top = top;
  1831.   OurRect.left = left;
  1832.   OurRect.bottom = bottom;
  1833.   OurRect.right = right;
  1834.  
  1835.   /* set the brush to light gray */
  1836.   SelectObject(hDC, GetStockObject(NULL_PEN));
  1837.   SelectObject(hDC, GetStockObject(LTGRAY_BRUSH));
  1838.  
  1839.   /* copy the rect coordinates for the 3D rect */
  1840.   memcpy(&TempRECT, &OurRect, sizeof(TempRECT));
  1841.  
  1842.   /* adjust coordinates to always fill only interior of rect */
  1843.   TempRECT.left++;
  1844.   TempRECT.top++;
  1845.   TempRECT.right++;
  1846.  
  1847.   /* clear the area of the 3D box */
  1848.   Rectangle(hDC, TempRECT.left, TempRECT.top,
  1849.                  TempRECT.right, TempRECT.bottom+1);
  1850.  
  1851.   /* draw as many 3D boxes as specified */
  1852.   for (i = 0; i < RectWidth; i++)
  1853.   {
  1854.     /* set the line color for left and top edges */
  1855.     if (bInOut == 0)
  1856.       SelectObject(hDC, hDkGrayPen);
  1857.     else
  1858.       SelectObject(hDC, GetStockObject(WHITE_PEN));
  1859.  
  1860.     /* draw the left edge from bottom to top */
  1861.     MoveTo(hDC, OurRect.left, OurRect.bottom);
  1862.     LineTo(hDC, OurRect.left, OurRect.top);
  1863.  
  1864.     /* draw the top edge from left to right */
  1865.     LineTo(hDC, OurRect.right, OurRect.top);
  1866.  
  1867.     /* set the line color for right and bottom edges */
  1868.     if (bInOut == 0)
  1869.       SelectObject(hDC, GetStockObject(WHITE_PEN));
  1870.     else
  1871.       SelectObject(hDC, hDkGrayPen);
  1872.  
  1873.     /* draw the right edge from top to bottom */
  1874.     LineTo(hDC, OurRect.right, OurRect.bottom);
  1875.  
  1876.     /* draw the bottom edge from right to left */
  1877.     LineTo(hDC, OurRect.left, OurRect.bottom);
  1878.  
  1879.     /* adjust rect coordinates to draw next 3D rect inside */
  1880.     /*  this rect */
  1881.     OurRect.left++;
  1882.     OurRect.top++;
  1883.     OurRect.right--;
  1884.     OurRect.bottom--;
  1885.   }
  1886.  
  1887.   /* release our dark gray pen */
  1888.   DeleteObject(hDkGrayPen);
  1889. }
  1890.  
  1891.  
  1892.