home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / mag&info / msjv7_4.zip / NETBIOS2.ARJ / BROWSER.C < prev    next >
Text File  |  1992-07-01  |  42KB  |  1,205 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: BROWSER.C
  4.  
  5.     PURPOSE: Demonstrates NetBIOS programming in Windows.
  6.  
  7.     FUNCTIONS:
  8.  
  9.         WinMain()         - calls initialization function, processes message loop
  10.         InitApplication() - initializes window data and registers window
  11.         InitInstance()    - saves instance handle and creates main window
  12.         MainWndProc()     - processes messages
  13.         About()           - processes messages for "About" dialog box
  14.         Connect()         - presents dialog box for connecting to remote
  15.                             server
  16.         Config()          - presents dialog box for configuring locally
  17.         FillUpTheListBox()- a routine which calls remote versions of
  18.                             dos_findfirst() and dos_findnext to fill
  19.                             up the list box.
  20.         CopyName()        - creates a blank padded name for NetBIOS purposes
  21.         datestr()         - converts a date returned in struct find_t to a
  22.                             string.
  23.         timestr()         - converts a time returned in struct find_t to a
  24.                             string
  25.         ListProc()        - a procedure for handling list box messages
  26.         ErrorState()      - a simple procedure for popping up an error message
  27.         CleanupClient()   - NetBIOS related cleanup prior to ending program
  28.         HourGlass()       - A procedure to change cursor to an hour glass
  29.         MessageLoop()     - Processes incoming messages and basically
  30.                             allows this program to yield control so that
  31.                             other apps can run.
  32.     History:
  33.         January, 1992       Alok Sinha       Created
  34.  
  35. ****************************************************************************/
  36.  
  37. // Include Files
  38. #include "windows.h"
  39. #include "ncb.h"
  40. #include "common.h"
  41. #include "state.h"
  42. #include "browser.h"
  43. #include "netio.h"
  44. #include <stdio.h>
  45. #include <memory.h>
  46. #include <string.h>
  47.  
  48.  
  49. // Global variables and defines
  50. HANDLE hInst;                       /* instance handle       */
  51. HWND hwndMain;                      /* handle to main window */
  52.  
  53.                                     /* Remote Directory Name */
  54. #define CURRENT_DIR "Current Working Directory at: "
  55. char szRemoteDirectory[ NETBIOS_NAME_LENGTH+  _MAX_DIR + sizeof (CURRENT_DIR)];
  56. char szDirectory[_MAX_DIR];
  57.  
  58. char chRemoteName [NETBIOS_NAME_LENGTH+1];  /* Local  NetBIOS name */
  59. char chLocalName  [NETBIOS_NAME_LENGTH+1];  /* Remote NetBIOS name */
  60.  
  61. ClientFSM ClientState = C_UNINITIALIZED;         /* Client State. See Client FSM*/
  62. ServerFSM ServerState = S_UNINITIALIZED;         /* Server State. See Server FSM*/
  63.  
  64. CallStatus enumCallStatus;                      /* Client Call Status */
  65. SendStatus enumCSendStatus;                     /* Client Send Status */
  66. SendStatus enumSSendStatus;                     /* Server Send Status */
  67. ReceiveStatus enumCRecvStatus;                  /* Client Receive Status */
  68. ReceiveStatus enumSRecvStatus;                  /* Server Receive Status */
  69.  
  70. char szErrorBuffer [ERROR_BUFFER_LENGTH];       /* Error Buffer */
  71.  
  72. BOOL fHourGlass = FALSE ;                       /* Hour Glass Cursor if TRUE */
  73.  
  74.  
  75. BYTE bLsn     = 0;                  /* Local Session Number */
  76. BYTE bNameNum = 0;                  /* Name          Number */
  77.  
  78. char szBaseWindowTitle[] = "Remote Browser";
  79. char szWindowTitle[80];
  80.  
  81. // Functions
  82.  
  83. FARPROC lpfnOldList ;
  84. VOID FillUpTheListBox(HWND hwndList);
  85. VOID CopyName( char *pchLocalName, char *pchBuffer );
  86.  
  87. /****************************************************************************
  88.  
  89.     FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  90.  
  91.     PURPOSE: calls initialization function, processes message loop
  92.  
  93. ****************************************************************************/
  94.  
  95. MSG msg;
  96.  
  97. int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
  98. HANDLE hInstance;
  99. HANDLE hPrevInstance;
  100. LPSTR lpCmdLine;
  101. int nCmdShow;
  102. {
  103.  
  104.  
  105.     if (hPrevInstance)
  106.         return FALSE;
  107.  
  108.     if (!InitApplication(hInstance))
  109.         return (FALSE);
  110.  
  111.     if (!InitInstance(hInstance, nCmdShow))
  112.         return (FALSE);
  113.  
  114.     while ( TRUE )
  115.     {
  116.         if (MessageLoop ( (MSG FAR *) &msg))
  117.         {
  118.             break;
  119.         }
  120.     }
  121.  
  122.     /*
  123.      *    Any cleanup left remaining?
  124.      */
  125.  
  126.  
  127.     // Stop the Client
  128.     if (ClientState != C_UNINITIALIZED)
  129.         CleanupClient();
  130.  
  131.     // Stop the Server
  132.     if    (ServerState != S_UNINITIALIZED)
  133.         DeleteServer();
  134.  
  135.     // Return error to Windows
  136.     return (msg.wParam);
  137. }
  138.  
  139.  
  140. /****************************************************************************
  141.  
  142.     FUNCTION: MessageLoop( MSG )
  143.  
  144.     PURPOSE: Peeks at messages and thus allows yielding control.
  145.  
  146.     RETURNS:  TRUE if WM_QUIT has been received in the queue
  147.               FALSE otherwise.
  148.  
  149. ****************************************************************************/
  150. BOOL _loadds MessageLoop (MSG FAR * pmsgMSG)
  151. {
  152.  
  153.     if (PeekMessage(pmsgMSG, NULL, 0, 0, PM_REMOVE))
  154.     {
  155.         if (pmsgMSG->message==WM_QUIT)
  156.  
  157.         {
  158.             return (TRUE);
  159.         }
  160.         TranslateMessage( pmsgMSG );
  161.         DispatchMessage ( pmsgMSG );
  162.     }
  163.  
  164.     // Windows Idle time. At this time, some
  165.     // idle time activities can be accomplished
  166.  
  167.     Server(hwndMain);
  168.     return (FALSE);
  169. }
  170.  
  171. /****************************************************************************
  172.  
  173.     FUNCTION: InitApplication(HANDLE)
  174.  
  175.     PURPOSE: Initializes window data and registers window class
  176.  
  177. ****************************************************************************/
  178.  
  179. BOOL InitApplication(hInstance)
  180. HANDLE hInstance;
  181. {
  182.     WNDCLASS  wc;
  183.  
  184.     wc.style = CS_GLOBALCLASS;
  185.     wc.lpfnWndProc = MainWndProc;
  186.     wc.cbClsExtra = 0;
  187.     wc.cbWndExtra = 0;
  188.     wc.hInstance = hInstance;
  189.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  190.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  191.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
  192.     wc.lpszMenuName =  "BrowserMenu";
  193.     wc.lpszClassName = "BrowserWClass";
  194.  
  195.     return (RegisterClass(&wc));
  196. }
  197.  
  198.  
  199. /****************************************************************************
  200.  
  201.     FUNCTION:  InitInstance(HANDLE, int)
  202.  
  203.     PURPOSE:  Saves instance handle and creates main window
  204.  
  205. ****************************************************************************/
  206.  
  207. BOOL InitInstance(hInstance, nCmdShow)
  208.     HANDLE          hInstance;
  209.     int             nCmdShow;
  210. {
  211.  
  212.     hInst = hInstance;
  213.  
  214.     hwndMain = CreateWindow(
  215.         "BrowserWClass",
  216.         szBaseWindowTitle,
  217.         WS_OVERLAPPEDWINDOW,
  218.         CW_USEDEFAULT,
  219.         CW_USEDEFAULT,
  220.         CW_USEDEFAULT,
  221.         CW_USEDEFAULT,
  222.         NULL,
  223.         NULL,
  224.         hInstance,
  225.         NULL
  226.     );
  227.  
  228.     if (!hwndMain)
  229.         return (FALSE);
  230.  
  231.     ShowWindow(hwndMain, nCmdShow);
  232.     UpdateWindow(hwndMain);
  233.     return (TRUE);
  234.  
  235. }
  236.  
  237. /****************************************************************************
  238.  
  239.     FUNCTION: MainWndProc(HWND, unsigned, WORD, LONG)
  240.  
  241.     PURPOSE:  Processes messages
  242.  
  243.     MESSAGES:
  244.  
  245.         WM_COMMAND    - application menu
  246.         WM_COMMAND processing: (only special commands described)
  247.  
  248.             IDM_OPEN  - Get the NetBIOS name of remote "Server"
  249.                         and create a NetBIOS session.
  250.             IDM_CONFIG- Get local NetBIOS name and start the
  251.                         server.
  252.             IDM_EXIT  - User wants to terminate application
  253.             IDM_ABOUT - display "About" box.
  254.  
  255.         USER DEFINE COMMANDS
  256.             BW_CALL_BACK   -    message received when a NetBIOS 'CALL' command
  257.                                 completes. Calls are only posted by Client.
  258.             BW_LISTEN_BACK -    message received when a NetBIOS 'LISTEN' command
  259.                                 completes. Listens are only posted by Server.
  260.             BW_C_RECEIVE_BACK - message received when a NetBIOS 'RECEIVE' command
  261.                                 posted by Client completes.
  262.             BW_S_RECEIVE_BACK - message received when a NetBIOS 'RECEIVE' command
  263.                                 posted by Server completes.
  264.             BW_C_SEND_BACK    - message received when a NetBIOS 'SEND' command
  265.                                 posted by Client completes.
  266.             BW_S_SEND_BACK    - message received when a NetBIOS 'SEND' command
  267.                                 posted by Server completes.
  268.  
  269.             CLIENT_CONNECTED  - message posted when a Listen completes
  270.                                 The message is posted by ListenCompleted()
  271.                                 routine in server.c
  272.  
  273.     Notes:
  274. ****************************************************************************/
  275.  
  276. long FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
  277. HWND hWnd;
  278. unsigned message;
  279. WORD wParam;
  280. LONG lParam;
  281. {
  282.     FARPROC          lpProc;
  283.     static  HWND     hwndList, hwndText ;
  284.     static  RECT     rect ;
  285.     HDC              hDC  ;
  286.     TEXTMETRIC         tm   ;
  287.     PNCB             pncbNCB;
  288.     BYTE             bRc  ;
  289.  
  290.  
  291.  
  292.     switch (message)
  293.     {
  294.         case WM_COMMAND:
  295.             switch (wParam)
  296.             {
  297.                 case IDM_ABOUT:     // Show the about box
  298.  
  299.                     lpProc = MakeProcInstance(About, hInst);
  300.                     DialogBox(hInst, "AboutBox", hWnd, lpProc);
  301.                     FreeProcInstance(lpProc);
  302.                     break;
  303.  
  304.                 case IDM_CLOSE:    // Close any current sessions/connections
  305.  
  306.                     if (ClientState>=C_CONNECTED)
  307.                     {
  308.                         SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR)"Remote Browser" );
  309.                         Hangup ( bLsn);
  310.                         bLsn = 0;
  311.                         ClientState = C_INITIALIZED;
  312.                         DestroyWindow (hwndList);
  313.                         DestroyWindow (hwndText);
  314.                     }
  315.                     break;
  316.  
  317.                 case IDM_OPEN:  // Open a new session/connection with
  318.                                 // remote server.
  319.  
  320.                     if (ClientState< C_INITIALIZED)
  321.                     {
  322.                         ErrorState (hwndMain,
  323.                                     "Error! Use Config First"
  324.                                    );
  325.                     }
  326.                     else if (ClientState>= C_CONNECTED)
  327.                     {
  328.                         ErrorState (hwndMain,
  329.                                     "Error! Already Connected"
  330.                                    );
  331.  
  332.                     }
  333.                     else
  334.                     {   // Put up Connect Dialog box
  335.                         lpProc = MakeProcInstance(Connect, hInst);
  336.                         DialogBox(hInst, "Connect", hWnd, lpProc);
  337.                         FreeProcInstance(lpProc);
  338.  
  339.                         // if state is not set to C_CALLING in Connect Dialog
  340.                         // we are done
  341.                         if ( ClientState != C_CALLING)
  342.                             break;
  343.  
  344.                         // Tell the user we are connecting
  345.                         // Don't want to display 'A' in 16th place. Hence, the
  346.                         // NETBIOS_NAME_LENGTH -1 length restriction
  347.                         sprintf(szErrorBuffer,
  348.                                 "Remote Browser - Connecting to [%*.*s]",
  349.                                 NETBIOS_NAME_LENGTH -1,
  350.                                 NETBIOS_NAME_LENGTH -1,
  351.                                 chRemoteName
  352.                                );
  353.                         SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR) szErrorBuffer);
  354.  
  355.                         // Disable the menu
  356.                         EnableMenuItem ( GetMenu(hwndMain), IDM_OPEN , MF_GRAYED);
  357.                         EnableMenuItem ( GetMenu(hwndMain), IDM_CLOSE, MF_GRAYED);
  358.                         EnableMenuItem ( GetMenu(hwndMain), IDM_CONFIG , MF_GRAYED);
  359.  
  360.                         // Now, make NetBIOS 'CALL' asynchronously
  361.                         if ((bRc = Call(hwndMain,
  362.                                         (LPSTR)chLocalName,
  363.                                         (LPSTR)chRemoteName,
  364.                                         RECEIVE_NCB_RTO,
  365.                                         SEND_NCB_STO,
  366.                                         &bLsn
  367.                                         )) != NO_ERROR)
  368.                         {   // Error in connecting to remote server
  369.  
  370.                             ClientState = C_INITIALIZED;
  371.                             // Don't want to display 'A' in 16th place. Hence, the
  372.                             // NETBIOS_NAME_LENGTH -1 length restriction
  373.                             sprintf(szErrorBuffer,
  374.                                     "Error Creating Session with [%*.*s] Error [%x]",
  375.                                     NETBIOS_NAME_LENGTH -1,
  376.                                     NETBIOS_NAME_LENGTH -1,
  377.                                     chRemoteName,
  378.                                     bRc
  379.                                    );
  380.  
  381.                             MessageBox(hwndMain, (LPSTR)szErrorBuffer,
  382.                                             "Error", MB_OK);
  383.                             SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR) "Remote Browser" );
  384.                         }
  385.                         else // No Error in connecting to remote server
  386.                         {
  387.                             ClientState = C_CONNECTED;
  388.  
  389.                             // Don't want to display 'A' in 16th place. Hence, the
  390.                             // NETBIOS_NAME_LENGTH -1 length restriction
  391.                             sprintf(szErrorBuffer,
  392.                                     "Remote Browser - Connected to [%*.*s]",
  393.                                     NETBIOS_NAME_LENGTH - 1,
  394.                                     NETBIOS_NAME_LENGTH - 1,
  395.                                     chRemoteName
  396.                                    );
  397.                             SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR) szErrorBuffer );
  398.                         }
  399.  
  400.                         // Enable menu items
  401.                         EnableMenuItem ( GetMenu(hwndMain), IDM_OPEN ,   MF_ENABLED);
  402.                         EnableMenuItem ( GetMenu(hwndMain), IDM_CLOSE,   MF_ENABLED);
  403.                         EnableMenuItem ( GetMenu(hwndMain), IDM_CONFIG , MF_ENABLED);
  404.  
  405.  
  406.                         /* Create a List Box if session made*/
  407.                         if ( ClientState==C_CONNECTED)
  408.                         {
  409.                             hDC = GetDC (hWnd) ;
  410.                             GetTextMetrics (hDC, &tm) ;
  411.                             ReleaseDC (hWnd, hDC) ;
  412.  
  413.                             rect.left = 20 * tm.tmAveCharWidth ;
  414.                             rect.top  = 3  * tm.tmHeight ;
  415.  
  416.                             // create a list box
  417.                             hwndList = CreateWindow ("listbox", NULL,
  418.                                                       WS_CHILDWINDOW |
  419.                                                       WS_VISIBLE | LBS_STANDARD | LBS_USETABSTOPS,
  420.                                                       tm.tmAveCharWidth,
  421.                                                       tm.tmHeight * 3,
  422.                                                       tm.tmAveCharWidth * MAX_LINE_SIZE +
  423.                                                       GetSystemMetrics (SM_CXVSCROLL),
  424.                                                       tm.tmHeight * 10,
  425.                                                       hWnd,
  426.                                                       1,
  427.                                                       GetWindowWord (hWnd, GWW_HINSTANCE),
  428.                                                       NULL
  429.                                                      ) ;
  430.  
  431.                             // Get remote current working directory
  432.                             if ( R_getcwd (hwndMain, bLsn, szDirectory, _MAX_DIR) != NULL)
  433.                             {
  434.  
  435.  
  436.                                 strcpy  ( szRemoteDirectory, CURRENT_DIR);
  437.                                 strncat ( szRemoteDirectory, chRemoteName, NETBIOS_NAME_LENGTH - 1);
  438.                                 strcat  ( szRemoteDirectory, szDirectory);
  439.                             }
  440.                             else    // some error occured in remote getcwd()
  441.                                 strcpy  (szRemoteDirectory, CURRENT_DIR);
  442.  
  443.                             // create a simple window showing current
  444.                             // working directory at remote server site.
  445.                             hwndText = CreateWindow ("static",
  446.                                                      szRemoteDirectory,
  447.                                                      WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT,
  448.                                                      tm.tmAveCharWidth,
  449.                                                      tm.tmHeight,
  450.                                                      tm.tmAveCharWidth * MAXPATH,
  451.                                                      tm.tmHeight,
  452.                                                      hWnd,
  453.                                                      2,
  454.                                                      GetWindowWord (hWnd, GWW_HINSTANCE),
  455.                                                      NULL
  456.                                                     ) ;
  457.  
  458.                             lpfnOldList = (FARPROC) GetWindowLong (hwndList, GWL_WNDPROC) ;
  459.  
  460.                             SetWindowLong ( hwndList,
  461.                                             GWL_WNDPROC,
  462.                                             (LONG) MakeProcInstance ((FARPROC) ListProc,
  463.                                                                      GetWindowWord (hWnd, GWW_HINSTANCE)
  464.                                                                     )
  465.                                           ) ;
  466.  
  467.                              /* Fill up the list box with directory listing */
  468.  
  469.                              HourGlass(TRUE);
  470.                              FillUpTheListBox(hwndList);
  471.                              HourGlass(FALSE);
  472.                              break  ;
  473.  
  474.                         }   /* if C_CONNECTED    */
  475.                         break;
  476.                     }       /* if ! C_INITIALIZED */
  477.                     break;
  478.                 case IDM_CONFIG:        // User wants to configure local (client+server) machine
  479.  
  480.                     if (ClientState>= C_CONNECTED)
  481.                     {
  482.                         ErrorState (hwndMain,
  483.                                     "Error! Use Close to End Session First"
  484.                                    );
  485.                     }
  486.                     else if (ClientState==C_CALLING)
  487.                     {
  488.                         ErrorState (hwndMain,
  489.                                     "Error! Waiting to connect"
  490.                                    );
  491.                     }
  492.                     else    // Client has not been initialized
  493.                     {
  494.  
  495.                          /*
  496.                           * Check the state of Server
  497.                           */
  498.                         if (ServerState > S_LISTENING)
  499.                         {
  500.                             sprintf(szErrorBuffer,
  501.                                     "A remote user might be connected to you.\n %s",
  502.                                     "Do you want to cancel that connection?"
  503.                                    );
  504.  
  505.                             if (MessageBox(hwndMain, (LPSTR)szErrorBuffer,
  506.                                            "Warning", MB_YESNO) == IDNO)
  507.                                 break;
  508.  
  509.                         }
  510.  
  511.                         lpProc = MakeProcInstance(Config, hInst);
  512.                         DialogBox(hInst, "Config", hWnd, lpProc);
  513.                         FreeProcInstance(lpProc);
  514.  
  515.                        /*
  516.                         * Initialize the Server, if Client got started
  517.                         */
  518.  
  519.                         if (ClientState == C_INITIALIZED)
  520.                         {
  521.                             InitServer(hwndMain);
  522.                             sprintf(szErrorBuffer,
  523.                                     "Remote Browser - Local Name [%s]",
  524.                                     chLocalName
  525.                                    );
  526.                             SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR) szErrorBuffer );
  527.                         }
  528.  
  529.                     }      /* if ClientState >= C_CONNECTED */
  530.                     break;
  531.  
  532.                     case IDM_EXIT: // user wants to stop application
  533.  
  534.                         // Stop the Client
  535.                         CleanupClient();
  536.                         ClientState = C_UNINITIALIZED;
  537.                         // Stop the Server
  538.                         DeleteServer();
  539.                         ServerState = S_UNINITIALIZED;
  540.                         PostQuitMessage(0);
  541.  
  542.                         break;
  543.                    case LIST_PROCESSING:
  544.  
  545.                         // This is where future enhancements can be
  546.                         // made change of directory or display
  547.                         // a file content. See notes in ListProc()
  548.                         MessageBox (hwndMain, "Not Implemented",
  549.                                     "Action undefined\n Place Holder for future enhancement",
  550.                                     MB_OK
  551.                                    );
  552.                         break;
  553.  
  554.         }   // switch (wParam) upon WM_COMMAND
  555.         break;
  556.  
  557.         case WM_SETFOCUS:
  558.             if (ClientState >= C_CONNECTED)
  559.                 SetFocus (hwndList);       // set focus on directory listing
  560.         break;
  561.  
  562.         case WM_SETCURSOR:                 // Change cursor to hour glass
  563.                                            // if performing asynchronous
  564.                                            // activities
  565.  
  566.             if  ((wParam == hwndList) ||
  567.                 (wParam == hwndMain))
  568.  
  569.             {
  570.                 if (fHourGlass)             // Doing asynchronous activity
  571.                 {
  572.                     HourGlass (TRUE);
  573.                     ShowCursor(TRUE);
  574.                     SetActiveWindow(hWnd);
  575.                     return (TRUE);
  576.                 };
  577.             }
  578.             else
  579.             {
  580.                 return (DefWindowProc(hWnd, message, wParam, lParam));
  581.             }
  582.  
  583.         case WM_SIZE:
  584.             rect.right  = LOWORD (lParam) ;
  585.             rect.bottom = HIWORD (lParam) ;
  586.             return (DefWindowProc(hWnd, message, wParam, lParam));
  587.             break;
  588.  
  589.         case WM_DESTROY:
  590.  
  591.             // Stop the Client
  592.             CleanupClient();
  593.             ClientState = C_UNINITIALIZED;
  594.             // Stop the Server
  595.             DeleteServer();
  596.             ServerState = S_UNINITIALIZED;
  597.  
  598.             PostQuitMessage(0);
  599.             break;
  600.  
  601.        /*
  602.         *  User Defined messages are processed here
  603.         */
  604.         case CLIENT_CONNECTED:  // received when a client connected to server
  605.  
  606.             // Don't want to display the 16th byte from chRemoteName
  607.             sprintf(szErrorBuffer,
  608.                     "Remote Browser - [%*.*s] is Connected to us",
  609.                      NETBIOS_NAME_LENGTH -1,
  610.                      NETBIOS_NAME_LENGTH -1,
  611.                      chRemoteName
  612.                    );
  613.             SendMessage ( hwndMain, WM_SETTEXT, 0, (LONG) (LPSTR) szErrorBuffer );
  614.             break;
  615.  
  616.         case BW_CALL_BACK:  // received when a asynchronous  'CALL' completes
  617.                             // sent by post routine in wnetbios.dll
  618.  
  619.             // In this application, only Client end posts a 'CALL'
  620.             if (ClientState == C_CALLING)
  621.             {
  622.                 // lparam should contain NCB pointer
  623.                 pncbNCB = (PNCB) lParam;
  624.                 if ((pncbNCB != NULL) && (pncbNCB->ncb_retcode == NRC_GOODRET))
  625.                 {
  626.                     enumCallStatus = CALL_CMPLT;
  627.                 }
  628.                 else
  629.                 {
  630.                     enumCallStatus = CALL_ERROR;
  631.                 }
  632.             }
  633.             else
  634.             {
  635.                  // We should never come here
  636.                 ErrorState ( hwndMain,
  637.                              "Error! unexpected BW_CALL_BACK received");
  638.             }
  639.             break;
  640.  
  641.  
  642.         case BW_C_SEND_BACK: // received when a asynchronous  'SEND'
  643.                              // ,posted by Client, completes.
  644.                              // sent by post routine in wnetbios.dll
  645.  
  646.         if (ClientState == C_SENDING)
  647.         {
  648.             // lparam should contain NCB pointer
  649.             pncbNCB = (PNCB) lParam;
  650.             if ((pncbNCB != NULL) && (pncbNCB->ncb_retcode == NRC_GOODRET))
  651.             {
  652.                 enumCSendStatus = SEND_CMPLT;
  653.             }
  654.             else
  655.             {
  656.                 enumCSendStatus = SEND_ERROR;
  657.             }
  658.         }
  659.         else
  660.         {
  661.             // We should never come here
  662.             ErrorState( hwndMain,
  663.                         "Error! unexpected BW_C_SEND_BACK received"
  664.                       );
  665.         }
  666.  
  667.         break;
  668.         case BW_S_SEND_BACK: // received when a asynchronous  'SEND'
  669.                              // ,posted by Server, completes.
  670.                              // sent by post routine in wnetbios.dll
  671.  
  672.         if (ServerState == S_SENDING)
  673.         {
  674.             // lParam should contain NCB pointer
  675.             pncbNCB = (PNCB) lParam;
  676.             if ((pncbNCB != NULL) && (pncbNCB->ncb_retcode == NRC_GOODRET))
  677.             {
  678.                 enumSSendStatus = SEND_CMPLT;
  679.             }
  680.             else
  681.             {
  682.                 enumSSendStatus = SEND_ERROR;
  683.             }
  684.         }
  685.         else
  686.         {
  687.             // We should never come here
  688.             ErrorState( hwndMain,
  689.                         "Error! unexpected BW_S_SEND_BACK received"
  690.                       );
  691.         }
  692.  
  693.         break;
  694.         case BW_C_RECEIVE_BACK: // received when a asynchronous  'RECEIVE'
  695.                                 // ,posted by Client, completes.
  696.                                 // sent by post routine in wnetbios.dll
  697.  
  698.         if (ClientState == C_RECEIVING)
  699.         {
  700.             // lParam should contain NCB pointer
  701.             pncbNCB = (PNCB) lParam;
  702.             if ((pncbNCB != NULL) && (pncbNCB->ncb_retcode == NRC_GOODRET))
  703.             {
  704.                 enumCRecvStatus = RECEIVE_CMPLT;
  705.             }
  706.             else
  707.             {
  708.                 enumCRecvStatus = RECEIVE_ERROR;
  709.             }
  710.         }
  711.         else
  712.         {
  713.              // We should never come here
  714.              ErrorState( hwndMain,
  715.                          "Error! unexpected BW_C_RECEIVE_BACK received"
  716.                        );
  717.         }
  718.  
  719.         break;
  720.         case BW_S_RECEIVE_BACK:  // received when a asynchronous  'RECEIVE'
  721.                                  // ,posted by Server, completes.
  722.                                  // sent by post routine in wnetbios.dll
  723.         if (ServerState== S_RECEIVING)
  724.         {
  725.             ReceiveCompleted( hwndMain, (PNCB) lParam);
  726.         }
  727.         else
  728.         {
  729.             // We should never come here
  730.             ErrorState( hwndMain,
  731.                         "Error! unexpected BW_S_RECEIVE_BACK received"
  732.                       );
  733.  
  734.         }
  735.         break;
  736.         case BW_LISTEN_BACK:  // received when a asynchronous  'LISTEN' completes
  737.                               // sent by post routine in wnetbios.dll
  738.  
  739.             // In this application, only the Server posts a Listen
  740.             if (ServerState== S_LISTENING)
  741.             {
  742.                 // Process the 'LISTEN' Completion
  743.                 ListenCompleted( hwndMain, (PNCB) lParam);
  744.             }
  745.             else
  746.             {
  747.  
  748.                 // We should never come here
  749.                 ErrorState( hwndMain,
  750.                             "Error! unexpected BW_C_LISTEN_BACK received"
  751.                           );
  752.  
  753.             }
  754.             break;
  755.  
  756.         default:
  757.             return (DefWindowProc(hWnd, message, wParam, lParam));
  758.  
  759.     } // switch message
  760.  
  761.     return (NULL);
  762. }
  763.  
  764. /****************************************************************************
  765.  
  766.     FUNCTION: About(HWND, unsigned, WORD, LONG)
  767.  
  768.     PURPOSE:  Processes messages for "About" dialog box
  769.  
  770.     MESSAGES:
  771.  
  772.         WM_INITDIALOG - initialize dialog box
  773.         WM_COMMAND    - Input received
  774.  
  775. ****************************************************************************/
  776.  
  777. BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
  778. HWND hDlg;
  779. unsigned message;
  780. WORD wParam;
  781. LONG lParam;
  782. {
  783.     switch (message) {
  784.         case WM_INITDIALOG:
  785.             return (TRUE);
  786.  
  787.         case WM_COMMAND:
  788.         if (wParam == IDOK
  789.                 || wParam == IDCANCEL) {
  790.                 EndDialog(hDlg, TRUE);
  791.                 return (TRUE);
  792.             }
  793.             break;
  794.     }
  795.     return (FALSE);
  796. }
  797.  
  798. /****************************************************************************
  799.  
  800.     FUNCTION: Connect(HWND, unsigned, WORD, LONG)
  801.  
  802.     PURPOSE:  Allows connection to remote computer by presenting a dialog box
  803.  
  804.     MESSAGES:
  805.  
  806.         WM_INITDIALOG - initialize dialog box
  807.         WM_COMMAND    - Input received
  808.  
  809. ****************************************************************************/
  810.  
  811. BOOL FAR PASCAL Connect(hDlg, message, wParam, lParam)
  812. HWND hDlg;
  813. unsigned message;
  814. WORD wParam;
  815. LONG lParam;
  816. {
  817.     int  iCount;        /* Number of chars returned */
  818.     char chBuffer [ NETBIOS_NAME_LENGTH + 1 ];
  819.  
  820.     switch (message)
  821.     {
  822.         case WM_INITDIALOG:
  823.  
  824.             SendDlgItemMessage ( hDlg, IDD_RNAME, EM_LIMITTEXT, NETBIOS_NAME_LENGTH -1, 0L);
  825.             return (TRUE);
  826.  
  827.         case WM_COMMAND:
  828.             switch (wParam)
  829.             {
  830.                 case IDOK:
  831.                     iCount = GetDlgItemText(hDlg,
  832.                                             IDD_RNAME,
  833.                                             chBuffer,
  834.                                             NETBIOS_NAME_LENGTH
  835.                                            );
  836.  
  837.                     if (iCount != 0)
  838.                     {
  839.                         /* Inform the user that we are tyring to
  840.                          *  establish a session
  841.                          */
  842.                         // Prepare the name for remote server name
  843.                         CopyName ( chRemoteName, chBuffer);
  844.  
  845.                         // Can't call yourself
  846.                         if ( memcmp(chLocalName, chRemoteName, NETBIOS_NAME_LENGTH) == 0)
  847.                         {
  848.                             // Calling self not allowed
  849.                             MessageBox(hwndMain, "Can not call yourself",
  850.                                        "Error", MB_OK);
  851.                         }
  852.                         else
  853.                         {
  854.                             // We are ready to call
  855.                             chRemoteName[NETBIOS_NAME_LENGTH - 1] = SERVER_NAME_END;
  856.                             ClientState = C_CALLING;
  857.                             SetDlgItemText(hDlg, IDD_RNAME, "CONNECTING...");
  858.                         }
  859.                     } /* if (iCount != 0) */
  860.  
  861.                     EndDialog(hDlg, TRUE);
  862.                     return (TRUE);
  863.  
  864.                 case IDCANCEL:
  865.  
  866.                     EndDialog(hDlg, TRUE);
  867.                     return (TRUE);
  868.             }
  869.             break;
  870.     }
  871.     return (FALSE);
  872. }
  873.  
  874. /****************************************************************************
  875.  
  876.     FUNCTION: Config(HWND, unsigned, WORD, LONG)
  877.  
  878.     PURPOSE:  Gets local names and any other local configuration by presenting
  879.               a dialog box
  880.  
  881.     MESSAGES:
  882.  
  883.         WM_INITDIALOG - initialize dialog box
  884.         WM_COMMAND    - Input received
  885.  
  886. ****************************************************************************/
  887.  
  888. BOOL FAR PASCAL Config(hDlg, message, wParam, lParam)
  889. HWND hDlg;
  890. unsigned message;
  891. WORD wParam;
  892. LONG lParam;
  893. {
  894.     int  iCount;        /* Number of chars returned */
  895.     BYTE bRc;        /* Return Code */
  896.     char chBuffer [ NETBIOS_NAME_LENGTH + 1 ];
  897.  
  898.     switch (message)
  899.     {
  900.         case WM_INITDIALOG:
  901.  
  902.             SendDlgItemMessage ( hDlg, IDD_LNAME, EM_LIMITTEXT, NETBIOS_NAME_LENGTH -1, 0L);
  903.             return (TRUE);
  904.  
  905.         case WM_COMMAND:
  906.             switch (wParam)
  907.             {
  908.                 case IDOK:
  909.                     iCount = GetDlgItemText(hDlg,
  910.                                             IDD_LNAME,
  911.                                             chBuffer,
  912.                                             NETBIOS_NAME_LENGTH
  913.                                            );
  914.  
  915.                     if (iCount != 0)
  916.                     {
  917.                         /* Inform the user that we are tyring to
  918.                          *  establish a session
  919.                          */
  920.                         SetDlgItemText(hDlg, IDD_LNAME, "Configuring...");
  921.  
  922.                         /* First delete the name, if already exist
  923.                          *  then add the new name.
  924.                          */
  925.  
  926.                         HourGlass (TRUE);
  927.  
  928.                         (VOID) DeleteName( (LPSTR)chLocalName, bNameNum);
  929.                         bNameNum = 0;
  930.                         ClientState = C_UNINITIALIZED;
  931.                         CopyName( chLocalName, chBuffer );
  932.  
  933.                         if ((bRc = AddName((LPSTR)chLocalName,
  934.                                             &bNameNum)) != NO_ERROR)
  935.                         {
  936.                             sprintf(szErrorBuffer,
  937.                                      "Error Adding Name [%s] Error [%x]",
  938.                                      chLocalName,
  939.                                      bRc
  940.                                     );
  941.  
  942.                             MessageBox(hwndMain, (LPSTR)szErrorBuffer,
  943.                                        "Error", MB_OK);
  944.  
  945.                         }
  946.                         else
  947.                             ClientState = C_INITIALIZED;
  948.  
  949.                         HourGlass(FALSE);
  950.  
  951.                     } /* if (iCount ! =0) */
  952.                     EndDialog(hDlg, TRUE);
  953.                     return (TRUE);
  954.  
  955.                 case IDCANCEL:
  956.                     EndDialog(hDlg, TRUE);
  957.                     return (TRUE);
  958.  
  959.             } /* switch wParam */
  960.             break;
  961.     }   /* switch message  */
  962.  
  963.     return (FALSE);
  964. }
  965.  
  966.  
  967. /****************************************************************************
  968.  
  969.     FUNCTION: ListProc(HWND, unsigned, WORD, LONG)
  970.  
  971.     PURPOSE:  Processes List box
  972.  
  973.     Processes:
  974.  
  975.         WM_KEYDOWN - Do something upon selection
  976.  
  977.  
  978. ****************************************************************************/
  979.  
  980. long FAR PASCAL ListProc (hWnd, iMessage, wParam, lParam)
  981. HWND     hWnd ;
  982. unsigned iMessage ;
  983. WORD     wParam ;
  984. LONG     lParam ;
  985. {
  986.     short    n = GetWindowWord (hWnd, GWW_ID) ;
  987.  
  988.     // Currently we send a message  to main window if it wishes to
  989.     // process the command.
  990.  
  991.     // One can enhance the sample program.
  992.     // Suggested enhancements:
  993.     //      if a directory is selected,
  994.     //              show files in that (remote) directory by calling R_cwd()
  995.     //      else if a file has been selected
  996.     //              show contents of the file by calling
  997.     //                  R_open(), R_read(), and R_close() respectively
  998.     //
  999.     if (iMessage == WM_KEYDOWN && wParam == VK_RETURN)
  1000.         SendMessage (GetParent (hWnd), WM_COMMAND, LIST_PROCESSING,
  1001.                      MAKELONG (hWnd, LBN_DBLCLK)) ;
  1002.  
  1003.     // Call default list processing function
  1004.     return CallWindowProc (lpfnOldList, hWnd, iMessage, wParam, lParam) ;
  1005. }
  1006.  
  1007. /****************************************************************************
  1008.  
  1009.     FUNCTION: timestr
  1010.  
  1011.     PURPOSE: Takes unsigned time in the format:               fedcba9876543210
  1012.              s=2 sec incr, m=0-59, h=23                       hhhhhmmmmmmsssss
  1013.              Changes to a 9-byte string (ignore seconds):     hh:mm ?m
  1014.  
  1015. ****************************************************************************/
  1016.  
  1017. char *timestr( unsigned t, char *buf )
  1018. {
  1019.     int h = (t >> 11) & 0x1f, m = (t >> 5) & 0x3f;
  1020.  
  1021.     sprintf( buf, "%2.2d:%02.2d %cm", h % 12, m,  h > 11 ? 'p' : 'a' );
  1022.     return buf;
  1023. }
  1024.  
  1025. /****************************************************************************
  1026.  
  1027.     FUNCTION:  datestr
  1028.  
  1029.     PURPOSE: Takes unsigned date in the format:               fedcba9876543210
  1030.              d=1-31, m=1-12, y=0-119 (1980-2099)              yyyyyyymmmmddddd
  1031.              Changes to  a 9-byte string:                      mm/dd/yy
  1032. ****************************************************************************/
  1033.  
  1034. char *datestr( unsigned d, char *buf )
  1035. {
  1036.     sprintf( buf, "%2.2d/%02.2d/%02.2d",
  1037.              (d >> 5) & 0x0f, d & 0x1f, (d >> 9) + 80 );
  1038.     return buf;
  1039. }
  1040.  
  1041. /****************************************************************************
  1042.  
  1043.     FUNCTION: FillUpTheListBox()
  1044.  
  1045.     PURPOSE:  Fills up list box by calling the remote getfirst/getnext calls.
  1046.  
  1047.  
  1048. ****************************************************************************/
  1049.  
  1050.  
  1051. VOID FillUpTheListBox(HWND hwndList)
  1052. {
  1053.     struct find_t findFileInfo;
  1054.     char   chFileLine [ MAX_LINE_SIZE ],
  1055.            chTimebuf[10],
  1056.            chDatebuf[10];
  1057.  
  1058.     BYTE  bRc;
  1059.     int   j;
  1060.  
  1061.     bRc = R_dos_findfirst ( hwndMain,
  1062.                             bLsn,
  1063.                             "*.*",                                         // File Name
  1064.                             _A_ARCH | _A_HIDDEN |  _A_NORMAL |  _A_RDONLY|
  1065.                             _A_SUBDIR,                                     // File Type
  1066.                             &findFileInfo);                                // File Details
  1067.  
  1068.     if (bRc == NO_ERROR)
  1069.     {
  1070.         do
  1071.         {
  1072.             // Need to handle directories specially
  1073.             if (findFileInfo.attrib & _A_SUBDIR)
  1074.             {
  1075.                 j = sprintf(chFileLine, "%s",
  1076.                             findFileInfo.name
  1077.                            );
  1078.                 j += sprintf(chFileLine + j, "\t\t<DIR>");
  1079.             }
  1080.             else
  1081.                 j = sprintf(chFileLine, "%-12s\t%-8ld",
  1082.                             findFileInfo.name,
  1083.                             findFileInfo.size
  1084.                            );
  1085.  
  1086.             sprintf(chFileLine + j,
  1087.                     "\t%-9s\t%-9s",
  1088.                     timestr( findFileInfo.wr_time, chTimebuf),
  1089.                     datestr( findFileInfo.wr_date, chDatebuf )
  1090.                    );
  1091.             SendMessage ( hwndList, LB_ADDSTRING, -1 , (LONG) (LPSTR) chFileLine);
  1092.  
  1093.         }while ( R_dos_findnext ( hwndMain, bLsn, &findFileInfo) == NO_ERROR);
  1094.  
  1095.     }
  1096.  
  1097.     return;
  1098. }
  1099.  
  1100. /****************************************************************************
  1101.  
  1102.     FUNCTION: CleanupClient()
  1103.  
  1104.     PURPOSE:  End any session, if exists and remove local name.
  1105.  
  1106.  
  1107. ****************************************************************************/
  1108.  
  1109. VOID CleanupClient(VOID)
  1110. {
  1111.     HourGlass(TRUE);
  1112.  
  1113.     /* Disconnect Local Session with  remote Server */
  1114.     if (bLsn)
  1115.     {
  1116.         Hangup( bLsn);
  1117.         bLsn = 0;
  1118.     }
  1119.  
  1120.     /* Remove Local name from Name Table */
  1121.     if (bNameNum)
  1122.     {
  1123.        DeleteName( (LPSTR)chLocalName, bNameNum);
  1124.        bNameNum = 0;
  1125.     }
  1126.  
  1127.     HourGlass(FALSE);
  1128. }
  1129.  
  1130.  
  1131. /****************************************************************************
  1132.  
  1133.     FUNCTION: HourGlass()
  1134.  
  1135.     PURPOSE:  Coverts the cursor from normal arrow to Hour Glass type.
  1136.  
  1137.  
  1138. ****************************************************************************/
  1139.  
  1140. VOID HourGlass ( BOOL fShowHourGlass)
  1141. {
  1142.     POINT pt;        /* Location of the hour glass */
  1143.  
  1144.     if (fShowHourGlass)     // Caller wants to display hour glass
  1145.     {
  1146.  
  1147.         fHourGlass = TRUE;
  1148.         SetCursor( LoadCursor(NULL, IDC_WAIT));
  1149.         GetCursorPos ( (LPPOINT) &pt);
  1150.         SetCursorPos ( pt.x, pt.y);
  1151.  
  1152.     }
  1153.     else                    // Caller does not want to display hour glass
  1154.     {
  1155.  
  1156.         fHourGlass = FALSE;
  1157.         SetCursor ( LoadCursor(NULL, IDC_ARROW));
  1158.     }
  1159.  
  1160.  
  1161. }
  1162. /****************************************************************************
  1163.  
  1164.     FUNCTION: CopyName()
  1165.  
  1166.     PURPOSE:  Copies a name into pchLocalName from pchBuffer and pads
  1167.               the name with blanks (0x20). This is necessary
  1168.               for NetBIOS compliance.
  1169. ****************************************************************************/
  1170.  
  1171. VOID CopyName( char *pchLocalName, char *pchBuffer )
  1172. {
  1173.     size_t i;
  1174.     // Copy the characters first
  1175.     for ( i =0; i < strlen(pchBuffer) && i < NETBIOS_NAME_LENGTH; i++)
  1176.         pchLocalName [i] = pchBuffer [i];
  1177.  
  1178.     // Now blank pad it
  1179.     for ( ;  i < NETBIOS_NAME_LENGTH; i++)
  1180.         pchLocalName [i] = 0x20;
  1181.  
  1182.     // put '\0' after 16th byte for sprintf to work correctly
  1183.     pchLocalName [ NETBIOS_NAME_LENGTH ] = '\0';
  1184. }
  1185.  
  1186. /****************************************************************************
  1187.  
  1188.     FUNCTION: ErrorState
  1189.  
  1190.     PURPOSE:  A simple routine which takes a handle (hwnd) to a window and a
  1191.               string (lpError). It then displays the string using
  1192.               MessageBox()
  1193.  
  1194. ****************************************************************************/
  1195.  
  1196.  
  1197. VOID ErrorState (HWND hwnd, LPSTR lpError)
  1198. {
  1199.     sprintf(szErrorBuffer, "%s", lpError);
  1200.  
  1201.     MessageBox(hwnd, (LPSTR)szErrorBuffer, "Error", MB_OK);
  1202.  
  1203. }
  1204. 
  1205.