home *** CD-ROM | disk | FTP | other *** search
- /****** xserver.c
- Source code of XServer.DLL
- Client programs can access the XLisp server
- by importing and calling functions from this
- DLL. See XLisp hypertext topic 'XLisp server'
- for details
-
- Written by Gabor Paller
- *********/
-
- #include <windows.h>
- #include "xserver.h"
-
- #define TRUE 1
- #define FALSE 0
-
- /* Queue packet structure */
- #define QPACKET struct qpacket
- QPACKET
- {
- HWND Window; /* Identifies the window */
- HANDLE Packet; /* Points to the packet block */
- HANDLE Link; /* Link field */
- };
-
- /* Head and tail of the request list */
- static HANDLE RQHead,RQTail;
- /* Head and tail of the reply list */
- static HANDLE RPHead,RPTail;
- static HANDLE ActivePacket;
- static QPACKET *APP;
- static HWND ServerWindow;
- static int ServerBusy;
- static int Clients;
-
- #define EXE_NAME_MAX_SIZE 128
- char serverfilename[ EXE_NAME_MAX_SIZE + 1 ];
-
- /* Creates the full server file path */
- void MakeServerName( HANDLE hInst , char *szFileName)
- {
- char * pcFileName;
- int nFileNameLen;
-
- nFileNameLen = GetModuleFileName(hInst,szFileName,EXE_NAME_MAX_SIZE);
- pcFileName = szFileName + nFileNameLen;
-
- while (pcFileName > szFileName) {
- if (*pcFileName == '\\' || *pcFileName == ':') {
- *(++pcFileName) = '\0';
- break;
- }
- nFileNameLen--;
- pcFileName--;
- }
-
- if ((nFileNameLen+15) < EXE_NAME_MAX_SIZE) {
- lstrcat(szFileName, "xlisp.exe -s");
- }
-
- else {
- lstrcat(szFileName, "?");
- }
-
- return;
- }
-
- int FAR PASCAL LibMain( HANDLE hInstance , WORD wDataSeg ,
- WORD wHeapSize , LPSTR lpCmdLine )
- {
- if( wHeapSize > 0 )
- UnlockData( 0 );
- RQHead = RQTail = RPHead = RPTail = NULL;
- ServerWindow = NULL;
- ServerBusy = FALSE;
- Clients = 0;
- MakeServerName( hInstance , serverfilename );
- return 1;
- }
-
- /* Inserts an element into a queue. Gets the packet , pointers
- to the head and tail pointer of the queue. Returns 1 if
- not succesful. */
- int InsertElem( QPACKET NewElem , HANDLE *HeadPtr ,
- HANDLE *TailPtr )
- {
- HANDLE h,h1;
- QPACKET *ptr,*HPtr;
-
- if( ( h = LocalAlloc( LMEM_MOVEABLE , sizeof( QPACKET ) ) ) == NULL )
- return 1;
-
- ptr = (QPACKET *)LocalLock( h );
- *ptr = NewElem;
- ptr->Link = NULL;
- if( *HeadPtr == NULL )
- {
- *HeadPtr = h;
- *TailPtr = h;
- }
- else
- {
- HPtr = (QPACKET *)LocalLock( *HeadPtr );
- HPtr->Link = h;
- LocalUnlock( *HeadPtr );
- *HeadPtr = h;
- }
- LocalUnlock( h );
- return 0;
- }
-
- /* Removes an element from a queue. Gets pointers to the head
- and tail pointers of the queue , returns the handle of the
- packet */
- HANDLE RemoveElem( HANDLE *HeadPtr , HANDLE *TailPtr )
- {
- QPACKET *ptr;
- HANDLE h,h1;
-
- h1 = *TailPtr;
- if( h1 == NULL )
- return NULL;
-
- ptr = (QPACKET *)LocalLock( h1 );
- if( ( *TailPtr = ptr->Link ) == NULL )
- *HeadPtr = NULL;
- LocalUnlock( h1 );
- return h1;
- }
-
- /* Searches for the oldest reply which was sent to the given
- window. Gets the HWND , returns the handle of the reply
- packet or NULL */
- HANDLE LookReply( HWND Window )
- {
- QPACKET *Ptr;
- HANDLE h,h1;
-
- h = RPTail;
- while( h != NULL)
- {
- Ptr = (QPACKET *)LocalLock( h );
- if( Ptr->Window == Window )
- {
- LocalUnlock( h );
- return h;
- }
- else
- {
- h1 = Ptr->Link;
- LocalUnlock( h );
- h = h1;
- }
- }
- return NULL;
- }
-
- /* Replacement for _fstrncpy which has several problems */
- void FAR PASCAL xstrncpy( LPSTR dest , LPSTR src , int maxlen )
- {
- char c;
-
- do
- c = *( dest++ ) = *( src++ );
- while( c && --maxlen );
- if( c )
- *dest = 0;
- }
-
- /* Starts the server. Does nothing if the server has already
- been launched. Gets the HWND of the caller , returns 1 ,
- if not succesful */
- int FAR PASCAL XDStartServer( HWND Window )
- {
-
- ++Clients;
- if( ServerWindow != NULL )
- return 0;
- if( ( ServerWindow = FindWindow( "XLisp" , "XLisp server" ) )
- != NULL )
- return 0;
- if( WinExec( serverfilename , SW_SHOW ) < 32 )
- return 1;
- BringWindowToTop( Window );
- return ( ServerWindow = FindWindow( "XLisp","XLisp server" ) )
- == NULL;
- }
-
- /* Terminates the server. Does nothing , if the server is
- not running or there are packets in the request queue */
- int FAR PASCAL XDTerminateServer()
- {
- if( ServerWindow == NULL )
- return 1;
- if( RQTail != NULL )
- return 1;
- if( --Clients > 0 )
- return 1;
- PostMessage( ServerWindow , WM_CLOSE , 0 , 0L );
- return 0;
- }
-
- /* Places a request into the request queue. Gets the HWND of
- the sending window and the data block. Returns 0 , if
- succesful */
- int FAR PASCAL XDSendRequest( HWND Window , LPSTR Data )
- {
- QPACKET np;
- HANDLE h,h1;
- char *db;
-
- if( ServerWindow == NULL )
- if( XDStartServer( Window ) )
- return 1;
-
-
- if( ( h = LocalAlloc( LMEM_MOVEABLE , strlen( Data ) + 1 ) ) == NULL )
- return 1;
- db = (char *)LocalLock( h );
- xstrncpy( (LPSTR)db , Data , 95 );
- LocalUnlock( h );
- np.Window = Window;
- np.Packet = h;
-
- if( InsertElem( np , &RQHead , &RQTail ) )
- return 1;
- if( !ServerBusy )
- {
- ServerBusy = TRUE;
- PostMessage( ServerWindow , XL_REQ , 0 , 0L );
- PostMessage( ServerWindow , XL_TRIG , 0 , 0L );
- }
- return 0;
- }
-
- /* Passes one request to the server. The server calls this
- function when it is ready to process a client request.
- Returns a pointer to the data block , NULL in case of
- error. The request packet and its data field remains
- locked */
- LPSTR FAR PASCAL XDGetRequest()
- {
- LPSTR db;
-
- ActivePacket = RemoveElem( &RQHead , &RQTail );
- if( ActivePacket == NULL )
- return NULL;
- else
- {
- APP = (QPACKET *)LocalLock( ActivePacket );
- db = (LPSTR)LocalLock( APP->Packet );
- return db;
- }
- }
-
- /* The server sends back its reply by calling this function.
- Gets a pointer to the reply block , returns 1 , if
- not succesful */
- int FAR PASCAL XDSendReply( LPSTR Data )
- {
- QPACKET rp;
- HANDLE h;
- char *db;
- WORD n;
-
- /* Stores the reply */
- n = strlen( Data ) + 1;
- if( ( h = LocalAlloc( LMEM_MOVEABLE , n ) ) == NULL )
- return 1;
- db = LocalLock( h );
- xstrncpy( (LPSTR)db , Data , 4095 );
- LocalUnlock( h );
- rp.Window = APP->Window;
- rp.Packet = h;
-
- db = LocalLock( h );
- LocalUnlock( h );
-
- /* Releases the request packet */
- LocalUnlock( APP->Packet );
- LocalFree( APP->Packet );
- LocalUnlock( ActivePacket );
- LocalFree( ActivePacket );
-
- /* Inserts the reply into the reply queue */
- if( InsertElem( rp , &RPHead , &RPTail ) )
- return 1;
- PostMessage( rp.Window , XL_REQ , 0 , 0L );
- PostMessage( rp.Window , XL_TRIG, 0 , 0L );
-
- /* If the request queue is not empty , sends another request
- to the server */
- if( RQTail != NULL )
- {
- PostMessage( ServerWindow , XL_REQ , 0 , 0L );
- PostMessage( ServerWindow , XL_TRIG , 0 , 0L );
- }
- else
- ServerBusy = FALSE;
- return 0;
- }
-
- /* The client calls this function to obtain the server's
- reply. Gets the HWND of the client , returns the address
- of the data block or NULL in case of error. The reply
- block and its data block remain locked */
- LPSTR FAR PASCAL XDGetReply( HWND Window )
- {
- QPACKET *rp;
- LPSTR db;
- HANDLE h;
-
- if( ( h = LookReply( Window ) ) == NULL )
- return NULL;
- rp = (QPACKET *)LocalLock( h );
- db = (LPSTR)LocalLock( rp->Packet );
- return db;
- }
-
- /* Deletes the oldest reply posted to the given window.
- Gets the HWND of the window , returns 0 if succesful */
- int FAR PASCAL XDDeleteReply( HWND Window )
- {
- QPACKET *Ptr1,*Ptr2;
- HANDLE h1,h2;
-
- h1 = RPTail;
- h2 = NULL;
-
- while( h1 != NULL )
- {
- Ptr1 = (QPACKET *)LocalLock( h1 );
- if( Ptr1->Window == Window )
- break;
- h2 = h1;
- h1 = Ptr1->Link;
- LocalUnlock( h2 );
- }
-
- if( h1 == NULL )
- return 1;
-
- if( h2 == NULL )
- {
- RPTail = Ptr1->Link;
- if( h1 == RPHead )
- RPHead = NULL;
- }
- else
- if( h1 == RPHead )
- {
- RPHead = Ptr1->Link;
- Ptr2 = (QPACKET *)LocalLock( RPHead );
- Ptr2->Link = NULL;
- LocalUnlock( RPHead );
- }
- else
- {
- Ptr2 = (QPACKET *)LocalLock( h2 );
- Ptr2->Link = Ptr1->Link;
- LocalUnlock( h2 );
- }
-
- /* Must be unlocked twice because XDGetReply locks these
- blocks ! */
- LocalUnlock( Ptr1->Packet );
- LocalFree( Ptr1->Packet );
- LocalUnlock( h1 );
- LocalUnlock( h1 );
- LocalFree( h1 );
- return 0;
- }
-
- /* Debug procedure - prints the state of the shared resource
- manager */
- void FAR PASCAL XDDebug()
- {
- char string[200],s1[20];
- int req,rep;
- HANDLE h,h1;
- QPACKET *ptr;
-
- h = RQTail;
- req = 0;
- while( h != NULL )
- {
- ptr = (QPACKET *)LocalLock( h );
- h1 = h;
- h = ptr->Link;
- LocalUnlock( h1 );
- ++req;
- }
-
- h = RPTail;
- rep = 0;
- while( h != NULL )
- {
- ptr = (QPACKET *)LocalLock( h );
- h1 = h;
- h = ptr->Link;
- LocalUnlock( h1 );
- ++rep;
- }
-
- if( ServerBusy )
- strcpy( s1 , "server busy" );
- else
- strcpy( s1 , "server free" );
-
- sprintf( string , "RQ:%u ; RP:%u %s",req,rep,s1 );
- MessageBox( NULL , string , "XServer" , MB_OK );
- }
-
-
-