home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / mag&info / msjv7_4.zip / NETBIOS2.ARJ / NETIO.C < prev    next >
C/C++ Source or Header  |  1992-07-01  |  35KB  |  1,149 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: NETIO.C
  4.  
  5.     PURPOSE: Contains function calls which call NetBIOS commands
  6.              as well as Remote Browser "Client" calls. The
  7.              Remote Browser "Server" code resides in Server.c
  8.  
  9.  
  10.     NOTE:    1.  ALL NETBIOS FUNCTIONS ASSUME SINGLE LAN ADAPTOR
  11.                  HENCE, ncb_lana IS ALWAYS SET TO 0.
  12.              2. Client can only connect to one remote Server
  13.                 at a time.
  14.  
  15.     FUNCTIONS:
  16.                 AddName    - Adds a unique name to local name table.
  17.                              (uses NCB.ADD.NAME )
  18.                 DeleteName - Deletes a unique name to local name table.
  19.                              (uses NCB.DELETE.NAME )
  20.                 Listen     - Posts a listen. Does not wait for completion
  21.                              (uses NCB.LISTEN | ASYNCH )
  22.                 Call       - Posts a call. Waits for completion, but yields
  23.                              control for other apps to run
  24.                              (uses NCB.CALL | ASYNCH )
  25.                 Send       - Posts a send. Waits for completion, but yields
  26.                              control for other apps to run
  27.                              (uses NCB.SEND | ASYNCH )
  28.                 Receive    - Posts a receive any. For client
  29.                              applications, waits for completion,
  30.                              but yields control for other apps to run.
  31.                              For server application, does not wait
  32.                              for completion
  33.                              (uses NCB.RECEIVE.ANY | ASYNCH )
  34.                 Hangup     - Hangs up a local session. Synchronous
  35.                              (uses NCB.HANGUP)
  36.                 Cancel     - Cancels a sumitted NCB. Synchronous
  37.                              (uses NCB.CANCEL)
  38.                 R_getcwd   - It performs a remote "get current
  39.                              working directory". Caller is assumed to
  40.                              be a client. A session must have been
  41.                              set up already with remote server.
  42.                 R_dos_findfirst   - It performs a remote "dos find first"
  43.                              Caller is assumed to be a client. A session must have been
  44.                              set up already with remote server.
  45.  
  46.                 R_dos_findnext   - It performs a remote "dos find next"
  47.                              Caller is assumed to be a client. A session must have been
  48.                              set up already with remote server. Furthermore,
  49.                              a R_dos_findfirst must have been called
  50.                              prior to calling this routine.
  51.  
  52.     History:
  53.         January, 1992       Alok Sinha       Created
  54.  
  55. ****************************************************************************/
  56.  
  57.  
  58. // Include Files
  59. #include <windows.h>
  60.  
  61. #include "ncb.h"
  62. #include "state.h"
  63. #include "common.h"
  64. #include "netio.h"
  65. #include "wnetbios.h"
  66. #include <time.h>
  67. #include <string.h>
  68.  
  69.  
  70. // Global data
  71.  
  72. extern CallStatus    enumCallStatus;
  73. extern ReceiveStatus enumCRecvStatus;
  74. extern ReceiveStatus enumSRecvStatus;
  75. extern ClientFSM     ClientState;
  76. extern SendStatus    enumCSendStatus;
  77.  
  78. // Internal functions
  79.  
  80.  
  81. BOOL TimeOut( clock_t ctStart, double dbWaitTime);
  82.  
  83.  
  84. /****************************************************************************
  85.  
  86.     FUNCTION: AddName
  87.  
  88.     PURPOSE:  Adds a unique name (in lpLocalName) in name table and
  89.               returns a name number if successful.
  90.  
  91. ****************************************************************************/
  92.  
  93. BYTE AddName   ( LPSTR lpLocalName, BYTE * pbNameNum)
  94. {
  95.  
  96.     PNCB pncbNCB;   /* Pointer to an NCB */
  97.     BYTE bRc;
  98.     int  iRc;
  99.  
  100.     // Allocate a NCB
  101.     pncbNCB = NcbAlloc( 1 );
  102.     if (pncbNCB==NULL)
  103.         return (ERROR_OUT_OF_MEMORY);
  104.  
  105.     /*
  106.      * Submit a Synchronous NCB.ADD.NAME
  107.      */
  108.     pncbNCB->ncb_command  = NCBADDNAME;     /* Synchronous add name */
  109.     pncbNCB->ncb_lana_num = 0;              /* assume single net    */
  110.     _fmemcpy( (LPVOID) pncbNCB->ncb_name,
  111.               (LPVOID) lpLocalName,
  112.               NETBIOS_NAME_LENGTH
  113.             );
  114.  
  115.     /*
  116.      * Check immediate return code and NCB_RETCODE as well
  117.      * as this is sync. call.
  118.      */
  119.  
  120.     iRc =  NetBiosPostMessage(0,          /* No Handle   */
  121.                               NO_MESSAGE, /* No Message  */
  122.                               NOTIFY_OFF, /* No Notify   */
  123.                               pncbNCB     /* Ptr. to NCB */
  124.                              );
  125.  
  126.  
  127.     if (iRc == -1)
  128.         bRc  = WNETBIOS_ERROR;
  129.     else
  130.         bRc  = pncbNCB->ncb_retcode;
  131.  
  132.     if (bRc != NRC_GOODRET )
  133.     {
  134.         NcbFree((LPVOID) pncbNCB);
  135.         return (bRc);
  136.     }
  137.  
  138.     // Return the Name Number
  139.     *pbNameNum =    pncbNCB->ncb_num;
  140.  
  141.     // Free the NCB
  142.     NcbFree((LPVOID) pncbNCB);
  143.     return (NRC_GOODRET);
  144.  
  145. }
  146.  
  147. /****************************************************************************
  148.  
  149.     FUNCTION: DeleteName
  150.  
  151.     PURPOSE:  Deletes a local name (in lpLocalName) from
  152.               name table. Name number is specified in bNameNum.
  153.  
  154. ****************************************************************************/
  155.  
  156. BYTE DeleteName( LPSTR lpLocalName, BYTE bNameNum)
  157. {
  158.     PNCB pncbNCB;   /* Pointer to an NCB */
  159.     BYTE bRc;
  160.     int  iRc;
  161.  
  162.     // Allocate a NCB
  163.     pncbNCB = NcbAlloc( 1 );
  164.     if (pncbNCB==NULL)
  165.         return (ERROR_OUT_OF_MEMORY);
  166.  
  167.     /*
  168.      *    Submit a synchronous NCB.DEL.NAME
  169.      */
  170.  
  171.     pncbNCB->ncb_command  = NCBDELNAME;     /* Synchronous delete name */
  172.     pncbNCB->ncb_lana_num = 0;            /* assume single net       */
  173.     pncbNCB->ncb_num      = bNameNum  ;     /* Name Number           */
  174.  
  175.  
  176.     _fmemcpy( (LPVOID)  pncbNCB->ncb_name,
  177.               (LPVOID)  lpLocalName,
  178.               NETBIOS_NAME_LENGTH
  179.           );
  180.  
  181.     iRc = NetBiosPostMessage(0,
  182.                              NO_MESSAGE,
  183.                              NOTIFY_OFF,
  184.                              pncbNCB
  185.                             );
  186.     if (iRc == -1)
  187.         bRc  = WNETBIOS_ERROR;
  188.     else
  189.         bRc  = pncbNCB->ncb_retcode;
  190.  
  191.     /*
  192.      * Check immediate return code and NCB_RETCODE as well
  193.      * as this is sync. call.
  194.      */
  195.  
  196.     if ( bRc != NRC_GOODRET )
  197.     {
  198.         NcbFree((LPVOID) pncbNCB);
  199.         return (bRc);
  200.     }
  201.  
  202.     // Free the NCB
  203.     NcbFree((LPVOID) pncbNCB);
  204.     return NRC_GOODRET;
  205.  
  206. }
  207.  
  208. /****************************************************************************
  209.  
  210.     FUNCTION: Call
  211.  
  212.     PURPOSE:  Tries to set up a connection(session) between local name
  213.               (in lpLocalName) and remote name (in lpRemoteName).
  214.               Upon successful completion, returns a local session
  215.               number in 'pbLsn'. Callers must set receive time out
  216.               and send time out values in 'bRto' and 'bSto'
  217.               respectively.
  218.  
  219.     Effects/Requirements:
  220.               The function sets enumCallStatus to CALL_START after
  221.               submitting a NCB.CALL |ASYNCH.
  222.               After completion of the call command, the post
  223.               routine sends a call completion message to
  224.               window identified by 'hWnd'.
  225.  
  226.               In browser sample program, the message goes to main window
  227.               (browser.c) where enumCallStatus gets set to either
  228.               CALL_CMPLT (no erro) or CALL_ERROR.
  229. ****************************************************************************/
  230.  
  231. BYTE Call (      HWND    hWnd,
  232.               LPSTR lpLocalName,
  233.               LPSTR lpRemoteName,
  234.               BYTE  bRto,
  235.               BYTE  bSto,
  236.               BYTE  *pbLsn
  237.           )
  238.  
  239. {
  240.  
  241.     PNCB pncbNCB;   /* Pointer to an NCB */
  242.     BYTE bRc;
  243.     MSG  msg;       /* Window Message    */
  244.     clock_t ctStart;
  245.     int  iRc;
  246.  
  247.     // Allocate a NCB
  248.     pncbNCB = NcbAlloc( 1 );
  249.     if (pncbNCB==NULL)
  250.         return (ERROR_OUT_OF_MEMORY);
  251.  
  252.  
  253.     /*
  254.      *    Make a asynchronous NCB.CALL
  255.      */
  256.  
  257.     pncbNCB->ncb_command  = NCBCALL | ASYNCH;      /* Asynchronous call       */
  258.     pncbNCB->ncb_lana_num = 0;              /* assume single net       */
  259.     pncbNCB->ncb_rto      = bRto;          /* Receice Time out       */
  260.     pncbNCB->ncb_sto      = bSto;          /* Send    Time out       */
  261.  
  262.     // Copy the local name. Assumes correct sized (NETBIOS_NAME_LENGTH) buffer
  263.     _fmemcpy( (LPVOID)pncbNCB->ncb_name,
  264.               (LPVOID)lpLocalName,
  265.               NETBIOS_NAME_LENGTH
  266.             );
  267.  
  268.     // Copy the remote name. Assumes correct sized (NETBIOS_NAME_LENGTH) buffer
  269.     _fmemcpy( (LPVOID) pncbNCB->ncb_callname,
  270.               (LPVOID) lpRemoteName,
  271.               NETBIOS_NAME_LENGTH
  272.             );
  273.  
  274.     iRc =  NetBiosPostMessage(hWnd,
  275.                               BW_CALL_BACK,
  276.                               NOTIFY_IF_ASYNC,
  277.                               pncbNCB
  278.                              );
  279.     // Only if internal error happens, wnetbios returns -1. Else
  280.     // it will always post the message. However, sometimes a
  281.     // call can complete successfully right away
  282.  
  283.     if (iRc == -1)
  284.         bRc = WNETBIOS_ERROR;
  285.     else
  286.         bRc = pncbNCB->ncb_retcode;
  287.     if (( bRc != NRC_PENDING) && (bRc != NRC_GOODRET))
  288.     {
  289.  
  290.         NcbFree ((LPVOID) pncbNCB);
  291.         return (bRc);
  292.     }
  293.  
  294.     /*
  295.      *    Set up timer and a timeout for this call
  296.      */
  297.     ctStart = clock();
  298.  
  299.     /*
  300.      *    Yield control and let other applications work
  301.      *    while we wait for getting a connection
  302.      */
  303.     enumCallStatus = CALL_START;
  304.     do
  305.     {
  306.         if (MessageLoop(&msg))
  307.         {
  308.             // WM_QUIT was received
  309.             PostQuitMessage(0);
  310.             Cancel ( pncbNCB);
  311.             NcbFree((LPVOID) pncbNCB);
  312.             return (NRC_CMDTMO);         /* User got bored and timeed out! */
  313.         }
  314.         // Did we connect yet
  315.         if (enumCallStatus == CALL_CMPLT)
  316.         {
  317.            // Free the NCB
  318.            *pbLsn = pncbNCB->ncb_lsn;
  319.            NcbFree((LPVOID) pncbNCB);
  320.            return (NRC_GOODRET);
  321.         }
  322.         else if (enumCallStatus == CALL_ERROR)
  323.         {
  324.             bRc = pncbNCB->ncb_retcode;
  325.             // Free the NCB
  326.             *pbLsn = pncbNCB->ncb_lsn;
  327.             NcbFree((LPVOID) pncbNCB);
  328.             return (bRc);
  329.         }
  330.  
  331.     }while ( TimeOut(ctStart, CALL_TIME_OUT)== FALSE);
  332.  
  333.  
  334.  
  335.     // We time-ed out so cancel the Call command
  336.     Cancel ( pncbNCB);
  337.  
  338.     // Free the NCB
  339.     NcbFree((LPVOID) pncbNCB);
  340.     return (NRC_CMDTMO);
  341.  
  342. }
  343.  
  344.  
  345. /****************************************************************************
  346.  
  347.     FUNCTION: Listen
  348.  
  349.     PURPOSE:  Post a asynchronous listen and returns without waiting
  350.               for completion of Listen. Users must set blank padded
  351.               16-byte long names in 'lpLocalName' and 'lpRemoteName'.
  352.               They must also set correct timeout values in
  353.               'bRto' (receive time out) and 'bSto' (send time out).
  354.               The function returns a pointer to the submitted NCB
  355.               which is allocated in fixed memory.
  356.  
  357.     Effects/Requirements:
  358.                The function submits NCB.LISTEN | ASYNCH. The post
  359.                routine will thus send a completion message to
  360.                the window identified by 'hWnd'.
  361.  
  362.                In browser sample program, the message is intercepted
  363.                by main window (browser.c) and processed.
  364.  
  365. ****************************************************************************/
  366.  
  367. BYTE Listen (     HWND  hWnd,
  368.                   LPSTR lpLocalName,
  369.                   LPSTR lpRemoteName,
  370.                   BYTE  bRto,
  371.                   BYTE  bSto,
  372.                   PNCB  *pncbListenPosted
  373.             )
  374.  
  375. {
  376.  
  377.     PNCB pncbNCB;   /* Pointer to an NCB */
  378.     BYTE bRc;
  379.     int  iRc;
  380.  
  381.     // Assume error will happen
  382.     *pncbListenPosted = NULL;
  383.  
  384.     // Allocate a NCB
  385.     pncbNCB = NcbAlloc( 1 );
  386.     if (pncbNCB==NULL)
  387.         return (ERROR_OUT_OF_MEMORY);
  388.  
  389.  
  390.     /*
  391.      *    Make a asynchronous NCB.LISTEN
  392.      */
  393.  
  394.     pncbNCB->ncb_command  = NCBLISTEN | ASYNCH;   /* Asynchronous Listen */
  395.     pncbNCB->ncb_lana_num = 0;              /* assume single net       */
  396.     pncbNCB->ncb_rto      = bRto;          /* Receice Time out       */
  397.     pncbNCB->ncb_sto      = bSto;          /* Send    Time out       */
  398.  
  399.     // Copy the local name. Assumes blank padded NETBIOS_NAME_LENGTH sized
  400.     // buffer
  401.     _fmemcpy( (LPVOID) pncbNCB->ncb_name,
  402.               (LPVOID) lpLocalName,
  403.               NETBIOS_NAME_LENGTH
  404.             );
  405.  
  406.     // Copy the remote name. Assumes blank padded NETBIOS_NAME_LENGTH sized
  407.     // buffer
  408.     _fmemcpy( (LPVOID)pncbNCB->ncb_callname,
  409.               (LPVOID)lpRemoteName,
  410.               NETBIOS_NAME_LENGTH
  411.           );
  412.  
  413.  
  414.     iRc =  NetBiosPostMessage(hWnd,
  415.                               BW_LISTEN_BACK,
  416.                               NOTIFY_IF_ASYNC,
  417.                               pncbNCB
  418.                              );
  419.     // Only if internal error happens, wnetbios returns -1. Else
  420.     // it will always post the message.
  421.     if (iRc == -1)
  422.         bRc = WNETBIOS_ERROR;
  423.     else
  424.         bRc = pncbNCB->ncb_retcode;
  425.     if (( bRc != NRC_PENDING) && (bRc != NRC_GOODRET))
  426.     {
  427.         NcbFree ((LPVOID) pncbNCB);
  428.         return (bRc);
  429.     }
  430.  
  431.     // No, errors. So , return Posted Listen NCB address
  432.     *pncbListenPosted = pncbNCB;
  433.     return ( bRc);
  434.  
  435. }
  436.  
  437. /****************************************************************************
  438.  
  439.     FUNCTION: Send
  440.  
  441.     PURPOSE: This function is used to send data asynchronously.
  442.              The caller specifies a buffer in 'lpData' and buffer
  443.              length in 'wDataLen'. The caller must also specify
  444.              the local session number in 'bLsn' which should be
  445.              valid. The caller specifies the message (in 'iMessage')
  446.              that post routine should send to the originating
  447.              window recognized by 'hWnd'. Finally, a variable
  448.              'peSendStatus' pointer must be provided.
  449.              The pointer 'peSendStatus' allows for "sender" to be either
  450.              a Client or a Sender.
  451.  
  452.     Effect/Requirements: After submitting a NCB.SEND| ASYNCH,
  453.             the function sets 'peSendStatus' to SEND_START. It
  454.             is the caller's responsibility to set this
  455.             variable to either SEND_CMPLT or SEND_ERROR upon
  456.             receiving the post completion message ('iMessage').
  457.             In this sample, the work is done in browser.c.
  458.  
  459.  
  460. ****************************************************************************/
  461.  
  462. BYTE Send (HWND          hWnd,
  463.            LPSTR         lpData,
  464.            WORD          wDataLen,
  465.            BYTE          bLsn,
  466.            unsigned      iMessage,
  467.            SendStatus    *peSendStatus
  468.           )
  469.  
  470. {
  471.  
  472.     PNCB   pncbNCB;   /* Pointer to an NCB */
  473.     BYTE   bRc;       /* Error return code */
  474.     MSG    msg;       /* Window Message    */
  475.     LPSTR  lpBuffer;  /* NCB data buffer   */
  476.     clock_t ctStart;
  477.     int    iRc;
  478.  
  479.     // Allocate a NCB
  480.     pncbNCB = NcbAlloc( 1 );
  481.     if (pncbNCB==NULL)
  482.         return (ERROR_OUT_OF_MEMORY);
  483.  
  484.     // Allocate buffer the size of data buffer which will be
  485.     // locked in memory.
  486.     lpBuffer =    (LPSTR) NcbAllocBuf( (DWORD) wDataLen );
  487.     if (lpBuffer==NULL)
  488.     {
  489.         NcbFree((LPVOID) pncbNCB);
  490.         return (ERROR_OUT_OF_MEMORY);
  491.     }
  492.  
  493.     /*
  494.      *    Make a asynchronous NCB.SEND
  495.      */
  496.  
  497.     pncbNCB->ncb_command  = NCBSEND | ASYNCH;      /* Asynchronous send       */
  498.     pncbNCB->ncb_lana_num = 0;              /* assume single net       */
  499.     pncbNCB->ncb_lsn      = bLsn;          /* Local Session Number  */
  500.     pncbNCB->ncb_length   = wDataLen;          /* data length       */
  501.     pncbNCB->ncb_buffer   = lpBuffer;          /* data in 'safe' memory */
  502.  
  503.     // Copy the data into our buffer
  504.     _fmemcpy( (LPVOID) lpBuffer,
  505.               (LPVOID) lpData,
  506.               (size_t)    wDataLen
  507.         );
  508.  
  509.     iRc = NetBiosPostMessage(hWnd,
  510.                              iMessage,         // Notification Message
  511.                              NOTIFY_IF_ASYNC,
  512.                              pncbNCB
  513.                             );
  514.     // Only if internal error happens, wnetbios returns -1. Else
  515.     // it will always post the message. However, sometimes
  516.     // a command can successfully complete right away
  517.  
  518.     if (iRc == -1)
  519.         bRc = WNETBIOS_ERROR;
  520.     else
  521.         bRc = pncbNCB->ncb_retcode;
  522.     if (( bRc != NRC_PENDING) && (bRc != NRC_GOODRET))
  523.     {
  524.         NcbFree ((LPVOID) lpBuffer);
  525.         NcbFree ((LPVOID) pncbNCB );
  526.         return (bRc);
  527.     }
  528.  
  529.     /*
  530.      *    Set up timer and a timeout for this call
  531.      */
  532.     ctStart = clock();
  533.  
  534.     /*
  535.      *    Yield control and let other applications work
  536.      *    while we wait for getting a connection
  537.      */
  538.     *peSendStatus = SEND_START;
  539.     do
  540.     {
  541.         if (MessageLoop(&msg))
  542.         {
  543.             // WM_QUIT was received
  544.             PostQuitMessage(0);
  545.             Cancel ( pncbNCB);
  546.             // Free the NCB and the buffer
  547.             NcbFree((LPVOID) pncbNCB);
  548.             NcbFree((LPVOID) lpBuffer);
  549.             return (NRC_CMDTMO);         /* User got bored and timeed out! */
  550.         }
  551.         // Did we complete send successfully yet?
  552.         if (*peSendStatus == SEND_CMPLT)
  553.         {
  554.             // Free the NCB and the buffer
  555.             NcbFree((LPVOID) pncbNCB);
  556.             NcbFree((LPVOID) lpBuffer);
  557.             return (NRC_GOODRET);
  558.         }
  559.         else if (*peSendStatus == SEND_ERROR)
  560.         {
  561.  
  562.             bRc = pncbNCB->ncb_retcode;
  563.  
  564.             // Free the NCB and the buffer
  565.             NcbFree((LPVOID) pncbNCB);
  566.             NcbFree((LPVOID) lpBuffer);
  567.             return (bRc);
  568.         }
  569.  
  570.      }
  571.      while ( TimeOut(ctStart, SEND_TIME_OUT)== FALSE);
  572.  
  573.  
  574.     // We time-ed out so cancel the Send command
  575.     Cancel ( pncbNCB);
  576.  
  577.     // Free the NCB and the buffer
  578.     NcbFree((LPVOID) pncbNCB);
  579.     NcbFree((LPVOID) lpBuffer);
  580.     return (NRC_CMDTMO);
  581.  
  582. }
  583.  
  584. /****************************************************************************
  585.  
  586.     FUNCTION: Receive
  587.  
  588.     PURPOSE: Post a asynchronous receive. If 'fServer' is TRUE,
  589.              the routine returns immediately after submitting
  590.              the NCB. Otherwise (for Clients), it will loop
  591.              waiting for async. receive to complete. The caller
  592.              specifies the handle of window to receive completion
  593.              message in 'hWnd' and local session number in 'bLsn'.
  594.              The caler must specify the size of packet it
  595.              is expecting in 'wDataLen'. Accordingly, the routine
  596.              will allocate fixed memory which caller must release.
  597.  
  598.     Effect/Requirements: For Clients, it posts a NCB.RECEIVE.ANY|ASYNCH
  599.             and loops after setting enumCRecvStatus = RECEIVE_START.
  600.             The Client (in this sample, browser.c) must
  601.             set it's value to RECEIVE_CMPLT or RECEIVE_ERROR after
  602.             receiving post routine message.
  603.  
  604. ****************************************************************************/
  605.  
  606.  
  607. BYTE Receive (      HWND        hWnd,
  608.                   LPSTR     *ppLpData,
  609.                   WORD      wDataLen,
  610.                   BYTE      bLsn,
  611.                   BOOL      fServer
  612.              )
  613.  
  614. {
  615.  
  616.     PNCB   pncbNCB;   /* Pointer to an NCB */
  617.     BYTE   bRc;       /* Error return code */
  618.     MSG    msg;       /* Window Message    */
  619.     unsigned iMessage;/* Notification Message */
  620.     clock_t ctStart;
  621.     int    iRc;
  622.  
  623.     // Allocate a NCB
  624.     pncbNCB = NcbAlloc( 1 );
  625.     if (pncbNCB==NULL)
  626.         return (ERROR_OUT_OF_MEMORY);
  627.  
  628.     // Allocate buffer the size of data buffer which will be
  629.     // locked in memory. The caller of Receive must free
  630.     // the buffer if pointer returned in non-NULL.
  631.  
  632.     *ppLpData =  (LPSTR) NcbAllocBuf( (DWORD) wDataLen );
  633.     if (*ppLpData==NULL)
  634.     {
  635.         NcbFree((LPVOID) pncbNCB);
  636.         return (ERROR_OUT_OF_MEMORY);
  637.     }
  638.  
  639.  
  640.     /*
  641.      *    Make a asynchronous NCB.RECEIVE
  642.      */
  643.  
  644.     pncbNCB->ncb_command  = NCBRECV | ASYNCH;  /* Asynchronous Receive  */
  645.     pncbNCB->ncb_lana_num = 0;                 /* assume single net     */
  646.     pncbNCB->ncb_lsn      = bLsn;              /* Local Session Number  */
  647.     pncbNCB->ncb_length   = wDataLen;          /* data length       */
  648.     pncbNCB->ncb_buffer   = *ppLpData;         /* data in 'safe' memory */
  649.  
  650.     /*
  651.      * If server is calling, we simply submit the
  652.      * RECEIVE and return. If client is calling
  653.      * we loop just like in Send()
  654.      */
  655.  
  656.     if (fServer)
  657.         iMessage = BW_S_RECEIVE_BACK;
  658.     else
  659.         iMessage = BW_C_RECEIVE_BACK;
  660.  
  661.     iRc =  NetBiosPostMessage(hWnd,
  662.                               iMessage,         // Notification Message
  663.                               NOTIFY_IF_ASYNC,
  664.                               pncbNCB
  665.                              );
  666.     // Only if internal error happens, wnetbios returns -1. Else
  667.     // it will always post the message. However, sometimes
  668.     // an NCB completes successfully right away.
  669.     if (iRc == -1)
  670.         bRc = WNETBIOS_ERROR;
  671.     else
  672.         bRc = pncbNCB->ncb_retcode;
  673.     if (( bRc != NRC_PENDING) && (bRc != NRC_GOODRET))
  674.     {
  675.         NcbFree ((LPVOID) pncbNCB );
  676.         return (bRc);
  677.     }
  678.  
  679.  
  680.     // In case of Server, we are done.
  681.     if (fServer)
  682.     {
  683.         return (NRC_PENDING);
  684.     }
  685.     /*
  686.      *    Set up timer and a timeout for this call
  687.      */
  688.     ctStart = clock();
  689.  
  690.     /*
  691.      *    Yield control and let other applications work
  692.      *    while we wait for getting a connection
  693.      */
  694.      enumCRecvStatus = RECEIVE_START;
  695.      do
  696.      {
  697.     if (MessageLoop(&msg))
  698.     {
  699.         // WM_QUIT was received
  700.        PostQuitMessage(0);
  701.        Cancel ( pncbNCB);
  702.        // Free the NCB and the buffer
  703.        NcbFree((LPVOID) pncbNCB);
  704.        NcbFree((LPVOID) *ppLpData);
  705.        *ppLpData = NULL;
  706.        return (NRC_CMDTMO);         /* User got bored and timeed out! */
  707.     }
  708.     // Did we complete send successfully yet?
  709.     if (enumCRecvStatus == RECEIVE_CMPLT)
  710.     {
  711.        // Free the NCB. The buffer must
  712.        // be freed by the caller.
  713.  
  714.        NcbFree((LPVOID) pncbNCB);
  715.        return (NRC_GOODRET);
  716.     }
  717.     else if (enumCRecvStatus == RECEIVE_ERROR)
  718.     {
  719.  
  720.        bRc = pncbNCB->ncb_retcode;
  721.  
  722.        // Free the NCB . Buffer must be freed by
  723.        // Caller.
  724.        NcbFree((LPVOID) pncbNCB);
  725.        return (bRc);
  726.     }
  727.  
  728.      }
  729.      while ( TimeOut(ctStart, RECEIVE_TIME_OUT)== FALSE);
  730.  
  731.  
  732.     // We time-ed out so cancel the Send command
  733.     Cancel ( pncbNCB);
  734.  
  735.     // Free the NCB and the buffer
  736.     NcbFree((LPVOID) pncbNCB);
  737.     NcbFree((LPVOID) *ppLpData);
  738.     *ppLpData = NULL;
  739.  
  740.     return (NRC_CMDTMO);
  741.  
  742. }
  743.  
  744. /****************************************************************************
  745.  
  746.     FUNCTION: Hangup
  747.  
  748.     PURPOSE: Posts a synchrnous NCB.HANGUP message given a local
  749.              session number in 'bLsn'.
  750.  
  751. ****************************************************************************/
  752.  
  753.  
  754. BYTE Hangup( BYTE bLsn)
  755. {
  756.     BYTE bRc;
  757.     PNCB pncbNCB;
  758.     int iRc;
  759.  
  760.     // Allocate a NCB
  761.     pncbNCB = NcbAlloc( 1 );
  762.     if (pncbNCB==NULL)
  763.         return ERROR_OUT_OF_MEMORY;
  764.  
  765.  
  766.     /*
  767.      * Submit a Synchronous NCB.HANGUP
  768.      */
  769.     pncbNCB->ncb_command  = NCBHANGUP;        /* Synchronous hanup    */
  770.     pncbNCB->ncb_lana_num = 0;              /* assume single net    */
  771.     pncbNCB->ncb_lsn      = bLsn;        /* Local Session Number */
  772.  
  773.     iRc =  NetBiosPostMessage(0,          /* No Handle   */
  774.                               NO_MESSAGE,     /* No Message  */
  775.                               NOTIFY_OFF,     /* No Notify   */
  776.                               pncbNCB     /* Ptr. to NCB */
  777.                              );
  778.     if (iRc == -1)
  779.         bRc  = WNETBIOS_ERROR;
  780.     else
  781.         bRc  = pncbNCB->ncb_retcode;
  782.     if ( bRc != NRC_GOODRET)
  783.     {
  784.         NcbFree((LPVOID) pncbNCB);
  785.         return bRc;
  786.     }
  787.  
  788.     // Free the NCB
  789.     NcbFree((LPVOID) pncbNCB);
  790.     return NRC_GOODRET;
  791.  
  792. }
  793.  
  794. /****************************************************************************
  795.  
  796.     FUNCTION: Cancel
  797.  
  798.     PURPOSE:  Posts a synchronous NCB.CANCEL command against the NCB
  799.               mentioned in 'pncbNCBToCancel'.
  800.  
  801. ****************************************************************************/
  802.  
  803.  
  804. BYTE Cancel( PNCB pncbNCBToCancel)
  805. {
  806.     BYTE bRc;
  807.     PNCB pncbNCB;
  808.     int iRc;
  809.  
  810.     // Allocate a NCB
  811.     pncbNCB = NcbAlloc( 1 );
  812.     if (pncbNCB==NULL)
  813.         return ERROR_OUT_OF_MEMORY;
  814.  
  815.  
  816.     /*
  817.      * Submit a Synchronous NCB.CANCEL
  818.      */
  819.     pncbNCB->ncb_command  = NCBCANCEL;        /* Synchronous cancel    */
  820.     pncbNCB->ncb_lana_num = 0;              /* assume single net    */
  821.  
  822.     // Set in buffer the address of NCB to be cancelled
  823.     pncbNCB->ncb_buffer = (char far *) pncbNCBToCancel;
  824.  
  825.  
  826.     iRc =  NetBiosPostMessage(0,          /* No Handle   */
  827.                               NO_MESSAGE,     /* No Message  */
  828.                               NOTIFY_OFF,     /* No Notify   */
  829.                               pncbNCB     /* Ptr. to NCB */
  830.                              );
  831.     if (iRc == -1)
  832.         bRc = WNETBIOS_ERROR;
  833.     else
  834.         bRc  = pncbNCB->ncb_retcode;
  835.     if (bRc != NRC_GOODRET)
  836.     {
  837.         NcbFree((LPVOID) pncbNCB);
  838.         return bRc;
  839.     }
  840.  
  841.     // Free the NCB
  842.     NcbFree ((LPVOID) pncbNCB);
  843.     return (NRC_GOODRET);
  844.  
  845. }
  846.  
  847. /****************************************************************************
  848.  
  849.     FUNCTION:  R_getcwd()
  850.  
  851.     PURPOSE:   Remote getcwd() function. Gets remote current directory.
  852.                It operates like a Client for networking purposes.
  853.  
  854. ****************************************************************************/
  855.  
  856.  
  857. char * R_getcwd( HWND hWnd, BYTE bLsn, char * pszBuffer, int maxlen)
  858. {
  859.  
  860.     BYTE        bRc;
  861.     LPSTR       lpData;
  862.     PACKET  FAR *pacPtr;
  863.  
  864.     // Sanity Check
  865.     if ((pszBuffer==NULL)|| (maxlen > MAXPATH))
  866.         return NULL;
  867.  
  868.     // Allocate a PACKET
  869.     lpData = (LPSTR) NcbAllocBuf ( (DWORD) PACKET_SIZE );
  870.     if (lpData==NULL)
  871.         return NULL;
  872.     pacPtr = (PACKET FAR *) lpData;
  873.     pacPtr->bCommand = R_GETCWD;
  874.  
  875.     /*
  876.      * Set the Client in Send mode first
  877.      */
  878.     ClientState = C_SENDING;
  879.  
  880.     bRc = Send (   hWnd,                // handle to send message to
  881.                    lpData,              // Data to Send
  882.                    PACKET_SIZE,         // Data buffer size
  883.                    bLsn,                // Local Session Number
  884.                    BW_C_SEND_BACK,      // Message sent upon completion
  885.                    &enumCSendStatus     // A signal.
  886.                );
  887.     NcbFree( (LPVOID) lpData);          // Release the packet
  888.  
  889.     if (bRc)
  890.     {
  891.         ClientState = C_CONNECTED;
  892.         return NULL;
  893.     }
  894.  
  895.     /*
  896.      * Wait to Receive
  897.      */
  898.     ClientState = C_RECEIVING;
  899.  
  900.     bRc =   Receive (   hWnd,       // Handle to send message to
  901.                         &lpData,    // Pointer to Received buffer
  902.                         maxlen,     // Size of Receive buffer
  903.                         bLsn,       // Local Session Number
  904.                         FALSE       // It is a client
  905.                     );
  906.     if (bRc)
  907.     {
  908.         ClientState = C_CONNECTED;
  909.         return NULL;
  910.     }
  911.  
  912.     /*
  913.      * Copy returned data into local memory and free DLL allocated memory
  914.      */
  915.     _fmemcpy ( pszBuffer, lpData, _fstrlen (lpData) );
  916.     NcbFree((LPVOID) lpData);
  917.  
  918.     /*
  919.      *  Restore Client State
  920.      */
  921.  
  922.     ClientState = C_CONNECTED;
  923.     return (pszBuffer);
  924. }
  925.  
  926. /****************************************************************************
  927.  
  928.     FUNCTION:  R_dos_findfirst()
  929.  
  930.     PURPOSE:   Remote dos_findfirst. It behaves like a Client for networking
  931.                purposes.
  932.  
  933. ****************************************************************************/
  934.  
  935.  
  936. BYTE  R_dos_findfirst( HWND hWnd,
  937.                         BYTE bLsn,
  938.                         char * pchFileName,
  939.                         unsigned uAttrib,
  940.                         FINDT *findFileInfo)
  941. {
  942.  
  943.     BYTE          bRc;
  944.     LPSTR         lpData;
  945.     PACKET    FAR *pacPtr;
  946.     FINDFIRST FAR *pfindFirst;
  947.  
  948.     // Sanity Check
  949.     if ((pchFileName==NULL)|| (findFileInfo == NULL))
  950.         return !(NRC_GOODRET) ;
  951.  
  952.     // Allocate a packety to send to remote server
  953.     lpData = (LPSTR) NcbAllocBuf ( (DWORD) (PACKET_SIZE  + sizeof (FINDFIRST)));
  954.     if (lpData==NULL)
  955.         return !( NRC_GOODRET) ;
  956.  
  957.     pacPtr = (PACKET FAR *) lpData;
  958.     pacPtr->bCommand = R_FINDFIRST;
  959.     pfindFirst = (FINDFIRST FAR *) ( (LPSTR) pacPtr + sizeof (BYTE));
  960.  
  961.     // Copy user values in the Find First packet
  962.     _fstrcpy(pfindFirst->chFileName, (LPSTR) pchFileName);
  963.     pfindFirst->uAttrib = uAttrib;
  964.  
  965.     /*
  966.      * Set the Client in Send mode first
  967.      */
  968.     ClientState = C_SENDING;
  969.  
  970.     bRc = Send (   hWnd,                // handle to send message to
  971.                    lpData,              // Data to Send
  972.                    PACKET_SIZE  + sizeof (FINDFIRST),   // Data buffer size
  973.                    bLsn,                // Local Session Number
  974.                    BW_C_SEND_BACK,      // Message sent upon completion
  975.                    &enumCSendStatus     // A signal.
  976.                );
  977.     NcbFree( (LPVOID) lpData);          // Release the packet
  978.  
  979.     if (bRc)
  980.     {
  981.         ClientState = C_CONNECTED;
  982.         return !(NRC_GOODRET);
  983.     }
  984.  
  985.     /*
  986.      * Wait to Receive
  987.      */
  988.     ClientState = C_RECEIVING;
  989.  
  990.     bRc =   Receive (   hWnd,       // Handle to send message to
  991.                         &lpData,    // Pointer to Received buffer
  992.                         sizeof (FINDT),     // Size of Receive buffer
  993.                         bLsn,       // Local Session Number
  994.                         FALSE       // It is a client
  995.                     );
  996.     if (bRc)
  997.     {
  998.         ClientState = C_CONNECTED;
  999.         return !(NRC_GOODRET);
  1000.     }
  1001.  
  1002.     /*
  1003.      * Returned data is merely  a find_t structure. We copy it
  1004.      * in local memory and free the locally allocated (fixed) memory
  1005.      */
  1006.     _fmemcpy ( (LPVOID ) findFileInfo,
  1007.                (LPVOID ) lpData,
  1008.                sizeof (FINDT)
  1009.              );
  1010.     NcbFree((LPVOID) lpData);
  1011.  
  1012.     /*
  1013.      *  Restore Client State
  1014.      */
  1015.  
  1016.     ClientState = C_CONNECTED;
  1017.     // We send -1 in find_t size if remote server encountered an error
  1018.     if ( findFileInfo->size == -1)
  1019.         return !(NRC_GOODRET);
  1020.     else
  1021.         return (NRC_GOODRET);
  1022.  
  1023. }
  1024.  
  1025. /****************************************************************************
  1026.  
  1027.     FUNCTION:  R_dos_findnext()
  1028.  
  1029.     PURPOSE:   Remote dos_findnext. It behaves like a Client for
  1030.                networking purposes.
  1031.  
  1032. ****************************************************************************/
  1033.  
  1034.  
  1035. BYTE  R_dos_findnext( HWND hWnd,
  1036.                       BYTE bLsn,
  1037.                       FINDT *findFileInfo)
  1038. {
  1039.  
  1040.     BYTE          bRc;
  1041.     LPSTR         lpData;
  1042.     PACKET    FAR *pacPtr;
  1043.     FINDNEXT  FAR *pfindNext;
  1044.  
  1045.     // Sanity Check
  1046.     if ((findFileInfo == NULL))
  1047.         return !(NRC_GOODRET) ;
  1048.  
  1049.     // Allocate a packet to send to remote server
  1050.     lpData = (LPSTR) NcbAllocBuf ( (DWORD) (PACKET_SIZE  + sizeof (FINDNEXT)));
  1051.     if (lpData==NULL)
  1052.         return  !(NRC_GOODRET) ;
  1053.  
  1054.     pacPtr = (PACKET FAR *) lpData;
  1055.     pacPtr->bCommand = R_FINDNEXT;
  1056.     pfindNext = (FINDNEXT FAR *) ( (LPSTR) pacPtr + sizeof (BYTE));
  1057.  
  1058.     // Copy remote find_t data back into the packet
  1059.     _fmemcpy( (LPVOID) &(pfindNext->FileInfo),
  1060.               (LPVOID) findFileInfo,
  1061.               sizeof (FINDT)
  1062.             );
  1063.  
  1064.     /*
  1065.      * Set the Client in Send mode first
  1066.      */
  1067.     ClientState = C_SENDING;
  1068.  
  1069.     bRc = Send (   hWnd,                // handle to send message to
  1070.                    lpData,              // Data to Send
  1071.                    PACKET_SIZE  + sizeof (FINDNEXT),   // Data buffer size
  1072.                    bLsn,                // Local Session Number
  1073.                    BW_C_SEND_BACK,      // Message sent upon completion
  1074.                    &enumCSendStatus     // A signal.
  1075.                );
  1076.     NcbFree( (LPVOID) lpData);          // Release the packet
  1077.  
  1078.     if (bRc)
  1079.     {
  1080.         ClientState = C_CONNECTED;
  1081.         return !(NRC_GOODRET);
  1082.     }
  1083.  
  1084.     /*
  1085.      * Wait to Receive
  1086.      */
  1087.     ClientState = C_RECEIVING;
  1088.  
  1089.     bRc =   Receive (   hWnd,       // Handle to send message to
  1090.                         &lpData,    // Pointer to Received buffer
  1091.                         sizeof (FINDT),     // Size of Receive buffer
  1092.                         bLsn,       // Local Session Number
  1093.                         FALSE       // It is a client
  1094.                     );
  1095.     if (bRc)
  1096.     {
  1097.         ClientState = C_CONNECTED;
  1098.         return !(NRC_GOODRET);
  1099.     }
  1100.  
  1101.     /*
  1102.      * Returned data is merely  a find_t structure. We copy it
  1103.      * in local memory and free the locally allocated (fixed) memory
  1104.      */
  1105.     _fmemcpy ( (LPVOID ) findFileInfo,
  1106.                (LPVOID ) lpData,
  1107.                sizeof (FINDT)
  1108.              );
  1109.     NcbFree((LPVOID) lpData);
  1110.  
  1111.     /*
  1112.      *  Restore Client State
  1113.      */
  1114.  
  1115.     ClientState = C_CONNECTED;
  1116.     // We send -1 in find_t size if remote server encountered an error
  1117.     if ( findFileInfo->size == -1)
  1118.         return !(NRC_GOODRET);
  1119.     else
  1120.         return (NRC_GOODRET);
  1121.  
  1122. }
  1123.  
  1124.  
  1125.  
  1126. /****************************************************************************
  1127.  
  1128.     FUNCTION:  TimeOut
  1129.  
  1130.     PURPOSE:   This function will return TRUE if duration of time
  1131.                time elapsed from ctStart till "now" is >=
  1132.                dbWaitTime, else FALSE.
  1133.  
  1134. ****************************************************************************/
  1135.  
  1136.  
  1137. BOOL TimeOut( clock_t ctStart, double dbWaitTime)
  1138. {
  1139.  
  1140.     clock_t ctCurrent;        /* Current time in clock ticks */
  1141.  
  1142.     ctCurrent = clock();
  1143.     if (((double)(ctCurrent - ctStart)/ CLOCKS_PER_SEC ) >= dbWaitTime)
  1144.         return TRUE;
  1145.     else
  1146.         return FALSE;
  1147.  
  1148. }
  1149.