home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / windows / c / xlisp21w / sources / xserver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-02  |  9.1 KB  |  415 lines

  1. /****** xserver.c
  2.         Source code of XServer.DLL
  3.     Client programs can access the XLisp server
  4.     by importing and calling functions from this
  5.     DLL. See XLisp hypertext topic 'XLisp server'
  6.     for details
  7.  
  8.          Written by Gabor Paller
  9.                     *********/
  10.  
  11. #include    <windows.h>
  12. #include        "xserver.h"
  13.  
  14. #define    TRUE    1
  15. #define    FALSE    0
  16.  
  17. /* Queue packet structure */
  18. #define QPACKET    struct qpacket
  19. QPACKET
  20. {
  21.   HWND        Window;        /* Identifies the window */
  22.   HANDLE    Packet;        /* Points to the packet block */
  23.   HANDLE    Link;        /* Link field */
  24. };
  25.  
  26. /* Head and tail of the request list */
  27. static HANDLE        RQHead,RQTail;
  28. /* Head and tail of the reply list */
  29. static HANDLE        RPHead,RPTail;
  30. static HANDLE        ActivePacket;
  31. static QPACKET        *APP;
  32. static HWND        ServerWindow;
  33. static int        ServerBusy;
  34. static int        Clients;
  35.  
  36. #define    EXE_NAME_MAX_SIZE    128
  37. char    serverfilename[ EXE_NAME_MAX_SIZE + 1 ];
  38.  
  39. /* Creates the full server file path */
  40. void MakeServerName( HANDLE hInst , char *szFileName)
  41. {
  42.    char *  pcFileName;
  43.    int     nFileNameLen;
  44.  
  45.    nFileNameLen = GetModuleFileName(hInst,szFileName,EXE_NAME_MAX_SIZE);
  46.    pcFileName = szFileName + nFileNameLen;
  47.  
  48.    while (pcFileName > szFileName) {
  49.        if (*pcFileName == '\\' || *pcFileName == ':') {
  50.        *(++pcFileName) = '\0';
  51.        break;
  52.        }
  53.    nFileNameLen--;
  54.    pcFileName--;
  55.    }
  56.  
  57.    if ((nFileNameLen+15) < EXE_NAME_MAX_SIZE) {
  58.        lstrcat(szFileName, "xlisp.exe -s");
  59.    }
  60.  
  61.    else {
  62.        lstrcat(szFileName, "?");
  63.    }
  64.  
  65.    return;
  66. }
  67.  
  68. int FAR PASCAL LibMain( HANDLE hInstance , WORD wDataSeg ,
  69.             WORD wHeapSize , LPSTR lpCmdLine )
  70. {
  71.   if( wHeapSize > 0 )
  72.     UnlockData( 0 );
  73.   RQHead = RQTail = RPHead = RPTail = NULL;
  74.   ServerWindow = NULL;
  75.   ServerBusy = FALSE;
  76.   Clients = 0;
  77.   MakeServerName( hInstance , serverfilename );
  78.   return 1;
  79. }
  80.  
  81. /* Inserts an element into a queue. Gets the packet , pointers
  82.    to the head and tail pointer of the queue. Returns 1 if
  83.    not succesful. */
  84. int InsertElem( QPACKET NewElem , HANDLE *HeadPtr ,
  85.         HANDLE *TailPtr )
  86. {
  87.   HANDLE    h,h1;
  88.   QPACKET    *ptr,*HPtr;
  89.  
  90.   if( ( h = LocalAlloc( LMEM_MOVEABLE , sizeof( QPACKET ) ) ) == NULL )
  91.         return 1;
  92.  
  93.   ptr = (QPACKET *)LocalLock( h );
  94.   *ptr = NewElem;
  95.   ptr->Link = NULL;
  96.   if( *HeadPtr == NULL )
  97.   {
  98.     *HeadPtr = h;
  99.     *TailPtr = h;
  100.   }
  101.   else
  102.   {
  103.     HPtr = (QPACKET *)LocalLock( *HeadPtr );
  104.     HPtr->Link = h;
  105.     LocalUnlock( *HeadPtr );
  106.     *HeadPtr = h;
  107.   }
  108.   LocalUnlock( h );
  109.   return 0;
  110. }
  111.  
  112. /* Removes an element from a queue. Gets pointers to the head
  113.    and tail pointers of the queue , returns the handle of the
  114.    packet */
  115. HANDLE RemoveElem( HANDLE *HeadPtr , HANDLE *TailPtr )
  116. {
  117.   QPACKET    *ptr;
  118.   HANDLE    h,h1;
  119.  
  120.   h1 = *TailPtr;
  121.   if( h1 == NULL )
  122.         return NULL;
  123.  
  124.   ptr = (QPACKET *)LocalLock( h1 );
  125.   if( ( *TailPtr = ptr->Link ) == NULL )
  126.          *HeadPtr = NULL;
  127.   LocalUnlock( h1 );
  128.   return h1;
  129. }
  130.  
  131. /* Searches for the oldest reply which was sent to the given
  132.    window. Gets the HWND , returns the handle of the reply
  133.    packet or NULL */
  134. HANDLE LookReply( HWND Window )
  135. {
  136.   QPACKET    *Ptr;
  137.   HANDLE    h,h1;
  138.  
  139.   h = RPTail;
  140.   while( h != NULL)
  141.   {
  142.     Ptr = (QPACKET *)LocalLock( h );
  143.     if( Ptr->Window == Window )
  144.     {
  145.       LocalUnlock( h );
  146.       return h;
  147.     }
  148.     else
  149.     {
  150.       h1 = Ptr->Link;
  151.       LocalUnlock( h );
  152.       h = h1;
  153.     }
  154.   }
  155.   return NULL;
  156. }
  157.  
  158. /* Replacement for _fstrncpy which has several problems */
  159. void FAR PASCAL xstrncpy( LPSTR dest , LPSTR src , int maxlen )
  160. {
  161.   char c;
  162.  
  163.   do
  164.     c = *( dest++ ) = *( src++ );
  165.   while( c && --maxlen );
  166.   if( c )
  167.     *dest = 0;
  168. }
  169.  
  170. /* Starts the server. Does nothing if the server has already
  171.    been launched. Gets the HWND of the caller , returns 1 ,
  172.    if not succesful */
  173. int FAR PASCAL XDStartServer( HWND Window )
  174. {
  175.  
  176.   ++Clients;
  177.   if( ServerWindow != NULL )
  178.     return 0;
  179.   if( ( ServerWindow = FindWindow( "XLisp" , "XLisp server" ) )
  180.       != NULL )
  181.     return 0;
  182.   if( WinExec( serverfilename , SW_SHOW ) < 32 )
  183.     return 1;
  184.   BringWindowToTop( Window );
  185.   return ( ServerWindow = FindWindow( "XLisp","XLisp server" ) )
  186.       == NULL;
  187. }
  188.  
  189. /* Terminates the server. Does nothing , if the server is
  190.    not running or there are packets in the request queue */
  191. int FAR PASCAL XDTerminateServer()
  192. {
  193.   if( ServerWindow == NULL )
  194.     return 1;
  195.   if( RQTail != NULL )
  196.     return 1;
  197.   if( --Clients > 0 )
  198.     return 1;
  199.   PostMessage( ServerWindow , WM_CLOSE , 0 , 0L );
  200.   return 0;
  201. }
  202.  
  203. /* Places a request into the request queue. Gets the HWND of
  204.    the sending window and the data block. Returns 0 , if
  205.    succesful */
  206. int FAR PASCAL XDSendRequest( HWND Window , LPSTR Data )
  207. {
  208.   QPACKET    np;
  209.   HANDLE    h,h1;
  210.   char        *db;
  211.  
  212.   if( ServerWindow == NULL )
  213.     if( XDStartServer( Window ) )
  214.     return 1;
  215.  
  216.  
  217.   if( ( h = LocalAlloc( LMEM_MOVEABLE , strlen( Data ) + 1 ) ) == NULL )
  218.         return 1;
  219.   db = (char *)LocalLock( h );
  220.   xstrncpy( (LPSTR)db , Data , 95 );
  221.   LocalUnlock( h );
  222.   np.Window = Window;
  223.   np.Packet = h;
  224.  
  225.   if( InsertElem( np , &RQHead , &RQTail ) )
  226.         return 1;
  227.   if( !ServerBusy )
  228.   {
  229.     ServerBusy = TRUE;
  230.     PostMessage( ServerWindow , XL_REQ , 0 , 0L );
  231.     PostMessage( ServerWindow , XL_TRIG , 0 , 0L );
  232.   }
  233.   return 0;
  234. }
  235.  
  236. /* Passes one request to the server. The server calls this
  237.    function when it is ready to process a client request.
  238.    Returns a pointer to the data block , NULL in case of
  239.    error. The request packet and its data field remains
  240.    locked */
  241. LPSTR FAR PASCAL XDGetRequest()
  242. {
  243.   LPSTR        db;
  244.  
  245.   ActivePacket = RemoveElem( &RQHead , &RQTail );
  246.   if( ActivePacket == NULL )
  247.         return NULL;
  248.   else
  249.   {
  250.     APP = (QPACKET *)LocalLock( ActivePacket );
  251.     db = (LPSTR)LocalLock( APP->Packet );
  252.     return db;
  253.   }
  254. }
  255.  
  256. /* The server sends back its reply by calling this function.
  257.    Gets a pointer to the reply block , returns 1 , if
  258.    not succesful */
  259. int FAR PASCAL XDSendReply( LPSTR Data )
  260. {
  261.   QPACKET    rp;
  262.   HANDLE    h;
  263.   char        *db;
  264.   WORD        n;
  265.  
  266. /* Stores the reply */
  267.   n = strlen( Data ) + 1;
  268.   if( ( h = LocalAlloc( LMEM_MOVEABLE , n ) ) == NULL )
  269.         return 1;
  270.   db = LocalLock( h );
  271.   xstrncpy( (LPSTR)db , Data , 4095 );
  272.   LocalUnlock( h );
  273.   rp.Window = APP->Window;
  274.   rp.Packet = h;
  275.  
  276.   db = LocalLock( h );
  277.   LocalUnlock( h );
  278.  
  279. /* Releases the request packet */
  280.   LocalUnlock( APP->Packet );
  281.   LocalFree( APP->Packet );
  282.   LocalUnlock( ActivePacket );
  283.   LocalFree( ActivePacket );
  284.  
  285. /* Inserts the reply into the reply queue */
  286.   if( InsertElem( rp , &RPHead , &RPTail ) )
  287.         return 1;
  288.   PostMessage( rp.Window , XL_REQ , 0 , 0L );
  289.   PostMessage( rp.Window , XL_TRIG, 0 , 0L );
  290.  
  291. /* If the request queue is not empty , sends another request
  292.    to the server */
  293.   if( RQTail != NULL )
  294.   {
  295.     PostMessage( ServerWindow , XL_REQ , 0 , 0L );
  296.     PostMessage( ServerWindow , XL_TRIG , 0 , 0L );
  297.   }
  298.   else
  299.     ServerBusy = FALSE;
  300.   return 0;
  301. }
  302.  
  303. /* The client calls this function to obtain the server's
  304.    reply. Gets the HWND of the client , returns the address
  305.    of the data block or NULL in case of error. The reply
  306.    block and its data block remain locked */
  307. LPSTR FAR PASCAL XDGetReply( HWND Window )
  308. {
  309.   QPACKET    *rp;
  310.   LPSTR        db;
  311.   HANDLE    h;
  312.  
  313.   if( ( h = LookReply( Window ) ) == NULL )
  314.         return NULL;
  315.   rp = (QPACKET *)LocalLock( h );
  316.   db = (LPSTR)LocalLock( rp->Packet );
  317.   return db;
  318. }
  319.  
  320. /* Deletes the oldest reply posted to the given window.
  321.    Gets the HWND of the window , returns 0 if succesful */
  322. int FAR PASCAL XDDeleteReply( HWND Window )
  323. {
  324.   QPACKET    *Ptr1,*Ptr2;
  325.   HANDLE    h1,h2;
  326.  
  327.   h1 = RPTail;
  328.   h2 = NULL;
  329.  
  330.   while( h1 != NULL )
  331.   {
  332.     Ptr1 = (QPACKET *)LocalLock( h1 );
  333.     if( Ptr1->Window == Window )
  334.     break;
  335.     h2 = h1;
  336.     h1 = Ptr1->Link;
  337.     LocalUnlock( h2 );
  338.   }
  339.  
  340.   if( h1 == NULL )
  341.     return 1;
  342.  
  343.   if( h2 == NULL )
  344.   {
  345.     RPTail = Ptr1->Link;
  346.     if( h1 == RPHead )
  347.     RPHead = NULL;
  348.   }
  349.   else
  350.   if( h1 == RPHead )
  351.   {
  352.     RPHead = Ptr1->Link;
  353.     Ptr2 = (QPACKET *)LocalLock( RPHead );
  354.     Ptr2->Link = NULL;
  355.     LocalUnlock( RPHead );
  356.   }
  357.   else
  358.   {
  359.     Ptr2 = (QPACKET *)LocalLock( h2 );
  360.     Ptr2->Link = Ptr1->Link;
  361.     LocalUnlock( h2 );
  362.   }
  363.  
  364. /* Must be unlocked twice because XDGetReply locks these
  365.    blocks ! */
  366.     LocalUnlock( Ptr1->Packet );
  367.     LocalFree( Ptr1->Packet );
  368.     LocalUnlock( h1 );
  369.     LocalUnlock( h1 );
  370.     LocalFree( h1 );
  371.   return 0;
  372. }
  373.  
  374. /* Debug procedure - prints the state of the shared resource
  375.    manager */
  376. void FAR PASCAL XDDebug()
  377. {
  378.   char        string[200],s1[20];
  379.   int        req,rep;
  380.   HANDLE    h,h1;
  381.   QPACKET    *ptr;
  382.  
  383.   h = RQTail;
  384.   req = 0;
  385.   while( h != NULL )
  386.   {
  387.     ptr = (QPACKET *)LocalLock( h );
  388.     h1 = h;
  389.     h = ptr->Link;
  390.     LocalUnlock( h1 );
  391.     ++req;
  392.   }
  393.  
  394.   h = RPTail;
  395.   rep = 0;
  396.   while( h != NULL )
  397.   {
  398.     ptr = (QPACKET *)LocalLock( h );
  399.     h1 = h;
  400.     h = ptr->Link;
  401.     LocalUnlock( h1 );
  402.     ++rep;
  403.   }
  404.  
  405.   if( ServerBusy )
  406.     strcpy( s1 , "server busy" );
  407.   else
  408.     strcpy( s1 , "server free" );
  409.  
  410.   sprintf( string , "RQ:%u ; RP:%u %s",req,rep,s1 );
  411.   MessageBox( NULL , string , "XServer" , MB_OK );
  412. }
  413.  
  414.  
  415.