#include "server.h" #include "..\DynamicLink\serverblock.h" #include "..\ClientChannel\channel.h" #include "utilities.h" #include "global.h" static char *b = NULL; static DWORD ClientProcessId = 0; static HANDLE ClientProcessHandle = NULL; #define INIT_SERVER 0 #define INIT_CHANNEL 1 #define PROCESS_REQUESTS 2 #define SET_GLOBAL_SERVER_READY 3 static state = INIT_SERVER; // static HANDLE hClient = NULL; /* ** */ #define TEXT 0 #define DATA 1 static int *CodeBuffer = NULL; static int *DataBuffer = NULL; static int CodeStart = 0; static int DataStart = 0; static int CodeSize = 0; static int DataSize = 0; CLEAN_BOOL StoreLong(int pvMem, int l) { char *dest; dest = (((int) CodeBuffer) + (pvMem - CodeStart)); *((int *) dest) = l; return( CLEAN_TRUE ); } int mwrites(int kind, int offset, CLEAN_STRING s, int address) { char *dest; int i; // __asm int 3; if (kind == TEXT) { dest = ((int) CodeBuffer) + offset; } else { dest = ((int) DataBuffer) + offset; } for( i = 0; i < (s->length); i++) { dest[i] = (s->characters)[i]; } return (address + (s->length)); } // ServerInfoBlock static PSERVER_INFO_BLOCK pSIB = NULL; #define CONNECTION_INFO_IN_ENV #ifdef CONNECTION_INFO_IN_ENV void StartProcess (CLEAN_BOOL is_console_client, CLEAN_STRING cg, CLEAN_STRING Title, CLEAN_STRING CmdLine, CLEAN_STRING Environment, CLEAN_BOOL *ok, int *client_id, CLEAN_STRING *result_path) { // ServerInfoBlock DWORD dwServerId; HANDLE hServerReady; HANDLE hClientReady; HANDLE hFileMapping; DWORD offset; PROCESS_INFORMATION pi; STARTUPINFO si; BOOL fSuccess; // Process information BOOL try_again; BOOL is_cg_path_statically_allocated; // char *dir; char *cmdline; char *cg_path; // char *env; char env[1000]; char *envP; char *s; int i; static CLEAN_STRING console_or_gui_path = NULL; if( console_or_gui_path != NULL ) { rfree( console_or_gui_path ); console_or_gui_path = NULL; } // __asm int 3 cg_path = (char *) rmalloc ((cg->length) + 1); rsncopy (cg_path,cg->characters, cg->length); cg_path[cg->length] = 0; is_cg_path_statically_allocated = FALSE; // env = (char *) rmalloc ((Environment->length) + 1); // rsncopy (env, Environment->characters, Environment->length ); // env[Environment->length] = 0; // ServerInfoBlock AddClient_to_ServerInfoBlock( pSIB, &dwServerId, &hServerReady, &hClientReady, &hFileMapping, &offset); // Commandline: // dummy cmdline = (char *) rmalloc ( 200 ); // sprintf // __asm int 3 // ith position contains '\0' envP = env; i = sprintf( envP, "dwServerId=%d", dwServerId); envP = envP + i + 1; i = sprintf( envP, "hServerReady=%d", hServerReady); envP = envP + i + 1; i = sprintf( envP, "hClientReady=%d", hClientReady); envP = envP + i + 1; i = sprintf( envP, "hFileMapping=%d", hFileMapping); envP = envP + i + 1; i = sprintf( envP, "offset=%d", offset); envP = envP + i + 1; i = sprintf( envP, "MESSAGE_SIZE=%d", MESSAGE_SIZE); envP = envP + i + 1; *envP = '\0'; /* __asm int 3 // s = cmdline; while ( *s != ' ' ) s++; cmdline[0] = '\0'; */ /*1 rsprintf( cmdline, "%d %d %d %d %d %d", dwServerId, hServerReady, hClientReady, hFileMapping, offset, MESSAGE_SIZE); */ // msg( cmdline ); // Convert workdir dir = (char *) rmalloc ((Title->length) + 1); rsncopy (dir,Title->characters, Title->length); dir[Title->length] = 0; // StartUpInfo for (i=0; i < sizeof(si); i++) ((char *) &si)[i] = (char) 0; //ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.lpTitle = dir; si.wShowWindow = SW_SHOWNORMAL; si.dwFlags = STARTF_USESHOWWINDOW; // Create new process do { try_again = FALSE; fSuccess = CreateProcess( cg_path, // Executable cmdline, // Commandline NULL, // Standard security (Proces) NULL, // Standard security (Thread) TRUE, // No handle inherited by child CREATE_NEW_CONSOLE, // Plain process env, // Environment of parent NULL, /*dir,*/ // Current directory &si, // Startup information &pi); // Process information if( fSuccess == NULL ) { switch( GetLastError() ) { case ERROR_FILE_NOT_FOUND: rfree(cg_path); msg( "server.c: GUI OR CONSOLE CLIENT NOT FOUND" ); /* cg_path = (is_console_client == CLEAN_TRUE) ? SetConsoleOrGuiClient(CONSOLECLIENT) : SetConsoleOrGuiClient(GUICLIENT); */ is_cg_path_statically_allocated = TRUE; if( cg_path == NULL ) { /* ** Free strings */ rfree(dir); rfree(cmdline); /* ** The user canceled the dialogue, then the ** process cannot be started */ *ok = CLEAN_FALSE; *client_id = 0; *result_path = EmptyCleanString; return; } /* ** cgpath contains a path, try again */ try_again = TRUE; break; default: msg( "StartProcess: cannot handle error" ); ExitProcess(-1); break; } } } while (try_again); /* ** The process has been started, free resources */ rfree( dir ); rfree( cmdline ); CloseHandle(pi.hThread); UpdateClient_in_ServerInfoBlock( pSIB, pi.hProcess, pi.dwProcessId); hClient = pi.hProcess; *ok = CLEAN_TRUE; *client_id = pi.dwProcessId; if( !is_cg_path_statically_allocated ) { /* ** cg_path is dynamically allocated which implies that the user has ** not selected a (new) console or gui client. */ rfree( cg_path ); *result_path = EmptyCleanString; } else { /* ** The console or gui client executable could not be found. The user ** has supplied a new path. Pass this on to clean */ console_or_gui_path = (CLEAN_STRING) rmalloc (sizeof (int) + rstrlen(cg_path) + 1); console_or_gui_path->length = rstrlen( cg_path ); rsncopy( console_or_gui_path->characters, cg_path, rstrlen(cg_path) + 1); *result_path = console_or_gui_path; } } // --------------------------------------------------------------------------------- void StartProcess2(CLEAN_STRING current_directory, CLEAN_STRING file_name, CLEAN_STRING commandline, CLEAN_BOOL *ok, int *client_id) { // ServerInfoBlock DWORD dwServerId; HANDLE hServerReady; HANDLE hClientReady; HANDLE hFileMapping; DWORD offset; PROCESS_INFORMATION pi; STARTUPINFO si; BOOL fSuccess; // Process information BOOL try_again; BOOL is_cg_path_statically_allocated; // char *dir; char *cmdline; char *cg_path; // char *env; char env[1000]; char *envP; char *s; int i; // __asm int 3 // ServerInfoBlock AddClient_to_ServerInfoBlock( pSIB, &dwServerId, &hServerReady, &hClientReady, &hFileMapping, &offset); // __asm int 3 // create environment envP = env; // i = sprintf( envP, "a=b"); envP = envP + i + 1; // i = sprintf( envP, "dwServerId=-%d", 1); envP = envP + i + 1; // i = sprintf( envP, "dwServerId=%u", dwServerId); envP = envP + i + 1; i = sprintf( envP, "dwServerId=%d", dwServerId); envP = envP + i + 1; i = sprintf( envP, "hServerReady=%d", hServerReady); envP = envP + i + 1; i = sprintf( envP, "hClientReady=%d", hClientReady); envP = envP + i + 1; i = sprintf( envP, "hFileMapping=%d", hFileMapping); envP = envP + i + 1; i = sprintf( envP, "offset=%d", offset); envP = envP + i + 1; i = sprintf( envP, "MESSAGE_SIZE=%d", MESSAGE_SIZE); envP = envP + i + 1; // i = sprintf( envP, "a=%u", dwServerId); envP = envP + i + 1; *envP = '\0'; // sprintf( env, "a=b\0\0"); // StartUpInfo // for (i=0; i < sizeof(si); i++) // ((char *) &si)[i] = (char) 0; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.lpTitle = file_name->characters; si.wShowWindow = SW_SHOWNORMAL; si.dwFlags = STARTF_USESHOWWINDOW; fSuccess = CreateProcess( NULL, // Executable commandline->characters, // Commandline NULL, // Standard security (Proces) NULL, // Standard security (Thread) TRUE, // No handle inherited by child CREATE_NEW_CONSOLE, // Plain process env, // Environment of parent current_directory->characters, /*dir,*/ // Current directory &si, // Startup information &pi); // Process information if( !fSuccess ) { *ok = 0; *client_id = 0; } else { CloseHandle(pi.hThread); UpdateClient_in_ServerInfoBlock( pSIB, pi.hProcess, pi.dwProcessId); hClient = pi.hProcess; *ok = CLEAN_TRUE; *client_id = pi.dwProcessId; } return; #ifdef OMIT // Create new process do { try_again = FALSE; if( fSuccess == NULL ) { switch( GetLastError() ) { case ERROR_FILE_NOT_FOUND: rfree(cg_path); msg( "server.c: GUI OR CONSOLE CLIENT NOT FOUND" ); /* cg_path = (is_console_client == CLEAN_TRUE) ? SetConsoleOrGuiClient(CONSOLECLIENT) : SetConsoleOrGuiClient(GUICLIENT); */ is_cg_path_statically_allocated = TRUE; if( cg_path == NULL ) { /* ** Free strings */ rfree(dir); rfree(cmdline); /* ** The user canceled the dialogue, then the ** process cannot be started */ *ok = CLEAN_FALSE; *client_id = 0; *result_path = EmptyCleanString; return; } /* ** cgpath contains a path, try again */ try_again = TRUE; break; default: msg( "StartProcess: cannot handle error" ); ExitProcess(-1); break; } } } while (try_again); /* ** The process has been started, free resources */ rfree( dir ); rfree( cmdline ); CloseHandle(pi.hThread); UpdateClient_in_ServerInfoBlock( pSIB, pi.hProcess, pi.dwProcessId); hClient = pi.hProcess; *ok = CLEAN_TRUE; *client_id = pi.dwProcessId; if( !is_cg_path_statically_allocated ) { /* ** cg_path is dynamically allocated which implies that the user has ** not selected a (new) console or gui client. */ rfree( cg_path ); *result_path = EmptyCleanString; } else { /* ** The console or gui client executable could not be found. The user ** has supplied a new path. Pass this on to clean */ console_or_gui_path = (CLEAN_STRING) rmalloc (sizeof (int) + rstrlen(cg_path) + 1); console_or_gui_path->length = rstrlen( cg_path ); rsncopy( console_or_gui_path->characters, cg_path, rstrlen(cg_path) + 1); *result_path = console_or_gui_path; } #endif } #else void StartProcess (CLEAN_BOOL is_console_client, CLEAN_STRING cg, CLEAN_STRING Title, CLEAN_STRING CmdLine, CLEAN_BOOL *ok, int *client_id, CLEAN_STRING *result_path) { // ServerInfoBlock DWORD dwServerId; HANDLE hServerReady; HANDLE hClientReady; HANDLE hFileMapping; DWORD offset; PROCESS_INFORMATION pi; STARTUPINFO si; BOOL fSuccess; // Process information BOOL try_again; BOOL is_cg_path_statically_allocated; // char *dir; char *cmdline; char *cg_path; int i; static CLEAN_STRING console_or_gui_path = NULL; if( console_or_gui_path != NULL ) { rfree( console_or_gui_path ); console_or_gui_path = NULL; } __asm int 3 cg_path = (char *) rmalloc ((cg->length) + 1); rsncopy (cg_path,cg->characters, cg->length); cg_path[cg->length] = 0; is_cg_path_statically_allocated = FALSE; // ServerInfoBlock AddClient_to_ServerInfoBlock( pSIB, &dwServerId, &hServerReady, &hClientReady, &hFileMapping, &offset); // Commandline: // dummy cmdline = (char *) rmalloc ( 200 ); rsprintf( cmdline, "%d %d %d %d %d %d", dwServerId, hServerReady, hClientReady, hFileMapping, offset, MESSAGE_SIZE); // msg( cmdline ); // Convert workdir dir = (char *) rmalloc ((Title->length) + 1); rsncopy (dir,Title->characters, Title->length); dir[Title->length] = 0; // StartUpInfo for (i=0; i < sizeof(si); i++) ((char *) &si)[i] = (char) 0; //ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.lpTitle = dir; si.wShowWindow = SW_SHOWNORMAL; si.dwFlags = STARTF_USESHOWWINDOW; // Create new process do { try_again = FALSE; fSuccess = CreateProcess( cg_path, // Executable cmdline, // Commandline NULL, // Standard security (Proces) NULL, // Standard security (Thread) TRUE, // No handle inherited by child CREATE_NEW_CONSOLE, // Plain process NULL, // Environment of parent NULL, /*dir,*/ // Current directory &si, // Startup information &pi); // Process information if( fSuccess == NULL ) { switch( GetLastError() ) { case ERROR_FILE_NOT_FOUND: rfree(cg_path); msg( "server.c: GUI OR CONSOLE CLIENT NOT FOUND" ); /* cg_path = (is_console_client == CLEAN_TRUE) ? SetConsoleOrGuiClient(CONSOLECLIENT) : SetConsoleOrGuiClient(GUICLIENT); */ is_cg_path_statically_allocated = TRUE; if( cg_path == NULL ) { /* ** Free strings */ rfree(dir); rfree(cmdline); /* ** The user canceled the dialogue, then the ** process cannot be started */ *ok = CLEAN_FALSE; *client_id = 0; *result_path = EmptyCleanString; return; } /* ** cgpath contains a path, try again */ try_again = TRUE; break; default: msg( "StartProcess: cannot handle error" ); ExitProcess(-1); break; } } } while (try_again); /* ** The process has been started, free resources */ rfree( dir ); rfree( cmdline ); CloseHandle(pi.hThread); UpdateClient_in_ServerInfoBlock( pSIB, pi.hProcess, pi.dwProcessId); hClient = pi.hProcess; *ok = CLEAN_TRUE; *client_id = pi.dwProcessId; if( !is_cg_path_statically_allocated ) { /* ** cg_path is dynamically allocated which implies that the user has ** not selected a (new) console or gui client. */ rfree( cg_path ); *result_path = EmptyCleanString; } else { /* ** The console or gui client executable could not be found. The user ** has supplied a new path. Pass this on to clean */ console_or_gui_path = (CLEAN_STRING) rmalloc (sizeof (int) + rstrlen(cg_path) + 1); console_or_gui_path->length = rstrlen( cg_path ); rsncopy( console_or_gui_path->characters, cg_path, rstrlen(cg_path) + 1); *result_path = console_or_gui_path; } } #endif void ReceiveReqWithTimeOut(CLEAN_BOOL static_application_as_client, CLEAN_BOOL *timeout,int *client_id, CLEAN_STRING *result) { char *s; static CLEAN_STRING cs = NULL; int ClientId; // ServerInfoBlock DWORD dwResult; int Client_i; DWORD dwMilliSeconds; // ServerInfoBlock DWORD dwServerId; HANDLE hServerReady; HANDLE hClientReady; HANDLE hFileMapping; DWORD offset; HANDLE hClient; HANDLE hServer; BOOL ok; int length; *timeout = CLEAN_FALSE; // msg( "WAIT_FAILED" ); #ifdef RECEIVEREQ msg( "ReceiveReq 1" ); #endif if( cs != NULL ) { rfree( cs ); cs = NULL; } #ifdef RECEIVEREQ msg( "ReceiveReq 2" ); #endif if( state == INIT_SERVER ) { state = INIT_CHANNEL; // ServerInfoBlock pSIB = Empty_ServerInfoBlock(); AddInitialSyncs_to_ServerInfoBlock( pSIB ); if( static_application_as_client == CLEAN_FALSE ) { cs = (CLEAN_STRING) rmalloc (sizeof(int)+12+rstrlen(GetCommandLine()) + 1); // 0123456789 * 0 rsprintf( cs->characters, "AddClient\n%s\n\n", GetCommandLine() ); cs->length = rstrlen(cs->characters); *client_id = 0; *result = cs; return; } /* ** Static application as client */ } else if( state == INIT_CHANNEL ) { state = PROCESS_REQUESTS; } else if( state == SET_GLOBAL_SERVER_READY ) { /* ** Settings this flag later guarantees round-robin fashion ** of serving clients. Not doing this, guarantees that ** registering clients take priority. */ SetEvent( pSIB->hClientKilledOrReady[GLOBAL_SERVER_READY] ); state = PROCESS_REQUESTS; } // sprintf( q, "No. of clients: %d", pSIB->n_Clients ); // msg( q ); /* old: dwMilliSeconds = INFINITE; if( pSIB->n_Clients == (N_OF_RESERVED_ENTRIES_INITIAL_BLOCK / 2) && !(static_application_as_client == CLEAN_TRUE) //!! ) { cs = (CLEAN_STRING) rmalloc(sizeof(int) + 7 ); cs->length = 5; // 01234 rsncopy( cs->characters, "Quit\n", 5); *result = cs; *client_id = 0; return; } */ // while(1) // ; // ServerInfoBlock, only initial block dwResult = WaitForMultipleObjects( (pSIB->n_Clients * 2) - 1, &(pSIB->hClientKilledOrReady[LOCAL_CLIENT_READY]), FALSE, 10);//INFINITE ); if( dwResult == /*WAIT_FAILED*/ WAIT_TIMEOUT ) { *timeout = CLEAN_TRUE; // msg( "WAIT_TIMEOUT" ); cs = (CLEAN_STRING) rmalloc (sizeof(int)+ 12); cs->length = 0; *result = cs; *client_id = 0; return; /* if( static_application_as_client == CLEAN_FALSE ) { cs = (CLEAN_STRING) rmalloc (sizeof(int)+12+rstrlen(GetCommandLine()) + 1); // 0123456789 * 0 rsprintf( cs->characters, "AddClient\n%s\n\n", GetCommandLine() ); cs->length = rstrlen(cs->characters); *client_id = 0; *result = cs; return; */ error(); msg( "WAIT_FAILED: jaa!!server.c" ); ExitProcess(-1); } Client_i = dwResult - WAIT_OBJECT_0 + 1; #ifdef DEBUG rsprintf( q, "Client #%d with %d", Client_i / 2, Client_i % 2); msg( q ); #endif DEBUG /* ** Protocol message has been received, the following code handles ** the messages */ if( Client_i < 2 ) { if( Client_i != LOCAL_CLIENT_READY ) { msg( "local client should be ready" ); ExitProcess(-1); } b = pSIB->hView[INDEX(Client_i)]; ClientId = *((DWORD *) (b+GLOBAL_BUFFER_START)); // msg( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); cs = (CLEAN_STRING) rmalloc(sizeof(int) + rstrlen( b + sizeof(DWORD) + GLOBAL_BUFFER_START) + 1); cs->length = rstrlen( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); rscopy(cs->characters, b + sizeof(DWORD) + GLOBAL_BUFFER_START); // msg( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); #ifdef DEBUG msg( cs->characters ); #endif state = SET_GLOBAL_SERVER_READY; if( ClientId != UNKNOWN_CLIENT_ID ) { /* ** An AddAndInit--protocol. Reply by sending the handles ** to the required synchronization objects. */ // ServerInfoBlock AddClient_to_ServerInfoBlock( pSIB, &dwServerId, &hServerReady, &hClientReady, &hFileMapping, &offset); hClient = OpenProcess(STANDARD_RIGHTS_REQUIRED | PROCESS_ALL_ACCESS, FALSE, ClientId); if( hClient == NULL ) { error(); msg( "ReceiveReq: could not open handle to statically linked client" ); ExitProcess(-1); } UpdateClient_in_ServerInfoBlock( pSIB, hClient, ClientId); /* ** Open handle to itself */ hServer = OpenProcess(STANDARD_RIGHTS_REQUIRED | PROCESS_ALL_ACCESS, FALSE, dwServerId); if( hServer == NULL ) { error(); msg( "ReceiveReq: could not open handle to itself, the dynamic linker" ); ExitProcess(-1); } /* ** Fill buffer */ *((DWORD *) (b+GLOBAL_BUFFER_START)) = dwServerId; ok = DuplicateHandle(hServer, hServerReady, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } ok = DuplicateHandle(hServer, hClientReady, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + sizeof(HANDLE) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } ok = DuplicateHandle(hServer, hFileMapping, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + 2 * sizeof(HANDLE) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } *((DWORD *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + 3 * sizeof(HANDLE) )) = offset; *((DWORD *) (b+ GLOBAL_BUFFER_START + 2 * sizeof(DWORD) + 3 * sizeof(HANDLE) )) = MESSAGE_SIZE; // Send to client SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); // Wait for confirmation that Client processed buffer WaitForSingleObject( pSIB->hClientKilledOrReady[LOCAL_CLIENT_READY], INFINITE ); // Signal Client SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); // msg( "Server gaat verder" ); } else SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); *client_id = ClientId; *result = cs; return; } if( IS_CLIENT_KILLED(Client_i) ) { *client_id = pSIB->ProcessId[ INDEX( Client_i ) ]; RemoveClient_from_ServerInfoBlock( pSIB, (INDEX( Client_i )) ); cs = (CLEAN_STRING) rmalloc(sizeof(int) + 7 ); cs->length = 7; // 012345 6 rsncopy( cs->characters, "Close\n\n", 7); *result = cs; //msg( "killed" ); return; //ExitProcess(-1); } if( IS_CLIENT_READY(Client_i) ) ; #ifdef DEBUG msg( "client ready" ); #endif // Prepare communication channel b = (pSIB->hView[INDEX(Client_i)]) + (int) (pSIB->Offset[INDEX(Client_i)]); SetHandlesToClient( pSIB->hServerReady[INDEX(Client_i)], pSIB->hClientKilledOrReady[INDEX_CLIENT_KILLED(Client_i)], pSIB->hClientKilledOrReady[INDEX_CLIENT_READY(Client_i)] ); length = *((DWORD *) (b+SIZE_OF_MESSAGE)); ClientProcessId = *((DWORD *) (b+DATA_START)); ClientProcessHandle = pSIB->hClientKilledOrReady[INDEX_CLIENT_KILLED(Client_i)]; s = b+DATA_START+sizeof(DWORD); cs = (CLEAN_STRING) rmalloc (sizeof(int) + /*rstrlen(s) + 1*/ length ); rsncopy( cs->characters, s, length); cs->length = length; rstrlen(s); (*result) = cs; *client_id = pSIB->ProcessId[ INDEX(Client_i) ]; return; } // original: void ReceiveReq(CLEAN_BOOL static_application_as_client, int *client_id, CLEAN_STRING *result) { char *s; static CLEAN_STRING cs = NULL; int ClientId; // ServerInfoBlock DWORD dwResult; int Client_i; DWORD dwMilliSeconds; // ServerInfoBlock DWORD dwServerId; HANDLE hServerReady; HANDLE hClientReady; HANDLE hFileMapping; DWORD offset; HANDLE hClient; HANDLE hServer; BOOL ok; int length; #ifdef RECEIVEREQ msg( "ReceiveReq 1" ); #endif if( cs != NULL ) { rfree( cs ); cs = NULL; } #ifdef RECEIVEREQ msg( "ReceiveReq 2" ); #endif if( state == INIT_SERVER ) { state = INIT_CHANNEL; // ServerInfoBlock pSIB = Empty_ServerInfoBlock(); AddInitialSyncs_to_ServerInfoBlock( pSIB ); if( static_application_as_client == CLEAN_FALSE ) { cs = (CLEAN_STRING) rmalloc (sizeof(int)+12+rstrlen(GetCommandLine()) + 1); // 0123456789 * 0 rsprintf( cs->characters, "AddClient\n%s\n\n", GetCommandLine() ); cs->length = rstrlen(cs->characters); *client_id = 0; *result = cs; return; } /* ** Static application as client */ } else if( state == INIT_CHANNEL ) { state = PROCESS_REQUESTS; } else if( state == SET_GLOBAL_SERVER_READY ) { /* ** Settings this flag later guarantees round-robin fashion ** of serving clients. Not doing this, guarantees that ** registering clients take priority. */ SetEvent( pSIB->hClientKilledOrReady[GLOBAL_SERVER_READY] ); state = PROCESS_REQUESTS; } // sprintf( q, "No. of clients: %d", pSIB->n_Clients ); // msg( q ); dwMilliSeconds = INFINITE; if( pSIB->n_Clients == (N_OF_RESERVED_ENTRIES_INITIAL_BLOCK / 2) && !(static_application_as_client == CLEAN_TRUE) //!! ) { cs = (CLEAN_STRING) rmalloc(sizeof(int) + 7 ); cs->length = 5; // 01234 rsncopy( cs->characters, "Quit\n", 5); *result = cs; *client_id = 0; return; } // ServerInfoBlock, only initial block dwResult = WaitForMultipleObjects( (pSIB->n_Clients * 2) - 1, &(pSIB->hClientKilledOrReady[LOCAL_CLIENT_READY]), FALSE, /*dwMilliSeconds*/ INFINITE ); if( dwResult == WAIT_FAILED ) { error(); msg( "WAIT_FAILED: server.c" ); ExitProcess(-1); } Client_i = dwResult - WAIT_OBJECT_0 + 1; #ifdef DEBUG rsprintf( q, "Client #%d with %d", Client_i / 2, Client_i % 2); msg( q ); #endif DEBUG /* ** Protocol message has been received, the following code handles ** the messages */ if( Client_i < 2 ) { if( Client_i != LOCAL_CLIENT_READY ) { msg( "local client should be ready" ); ExitProcess(-1); } b = pSIB->hView[INDEX(Client_i)]; ClientId = *((DWORD *) (b+GLOBAL_BUFFER_START)); // msg( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); cs = (CLEAN_STRING) rmalloc(sizeof(int) + rstrlen( b + sizeof(DWORD) + GLOBAL_BUFFER_START) + 1); cs->length = rstrlen( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); rscopy(cs->characters, b + sizeof(DWORD) + GLOBAL_BUFFER_START); // msg( b + sizeof(DWORD) + GLOBAL_BUFFER_START ); #ifdef DEBUG msg( cs->characters ); #endif state = SET_GLOBAL_SERVER_READY; if( ClientId != UNKNOWN_CLIENT_ID ) { /* ** An AddAndInit--protocol. Reply by sending the handles ** to the required synchronization objects. */ // ServerInfoBlock AddClient_to_ServerInfoBlock( pSIB, &dwServerId, &hServerReady, &hClientReady, &hFileMapping, &offset); hClient = OpenProcess(STANDARD_RIGHTS_REQUIRED | PROCESS_ALL_ACCESS, FALSE, ClientId); if( hClient == NULL ) { error(); msg( "ReceiveReq: could not open handle to statically linked client" ); ExitProcess(-1); } UpdateClient_in_ServerInfoBlock( pSIB, hClient, ClientId); /* ** Open handle to itself */ hServer = OpenProcess(STANDARD_RIGHTS_REQUIRED | PROCESS_ALL_ACCESS, FALSE, dwServerId); if( hServer == NULL ) { error(); msg( "ReceiveReq: could not open handle to itself, the dynamic linker" ); ExitProcess(-1); } /* ** Fill buffer */ *((DWORD *) (b+GLOBAL_BUFFER_START)) = dwServerId; ok = DuplicateHandle(hServer, hServerReady, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } ok = DuplicateHandle(hServer, hClientReady, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + sizeof(HANDLE) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } ok = DuplicateHandle(hServer, hFileMapping, hClient, ((HANDLE *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + 2 * sizeof(HANDLE) )), NULL, FALSE, DUPLICATE_SAME_ACCESS); if( !ok ) { error(); msg( "Receivereq: could not dup handle" ); ExitProcess(-1); } *((DWORD *) (b+ GLOBAL_BUFFER_START + sizeof(DWORD) + 3 * sizeof(HANDLE) )) = offset; *((DWORD *) (b+ GLOBAL_BUFFER_START + 2 * sizeof(DWORD) + 3 * sizeof(HANDLE) )) = MESSAGE_SIZE; // Send to client SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); // Wait for confirmation that Client processed buffer WaitForSingleObject( pSIB->hClientKilledOrReady[LOCAL_CLIENT_READY], INFINITE ); // Signal Client SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); // msg( "Server gaat verder" ); } else SetEvent( pSIB->hServerReady[LOCAL_SERVER_READY] ); *client_id = ClientId; *result = cs; return; } if( IS_CLIENT_KILLED(Client_i) ) { *client_id = pSIB->ProcessId[ INDEX( Client_i ) ]; RemoveClient_from_ServerInfoBlock( pSIB, (INDEX( Client_i )) ); cs = (CLEAN_STRING) rmalloc(sizeof(int) + 7 ); cs->length = 7; // 012345 6 rsncopy( cs->characters, "Close\n\n", 7); *result = cs; //msg( "killed" ); return; //ExitProcess(-1); } if( IS_CLIENT_READY(Client_i) ) ; #ifdef DEBUG msg( "client ready" ); #endif // Prepare communication channel b = (pSIB->hView[INDEX(Client_i)]) + (int) (pSIB->Offset[INDEX(Client_i)]); SetHandlesToClient( pSIB->hServerReady[INDEX(Client_i)], pSIB->hClientKilledOrReady[INDEX_CLIENT_KILLED(Client_i)], pSIB->hClientKilledOrReady[INDEX_CLIENT_READY(Client_i)] ); length = *((DWORD *) (b+SIZE_OF_MESSAGE)); ClientProcessId = *((DWORD *) (b+DATA_START)); ClientProcessHandle = pSIB->hClientKilledOrReady[INDEX_CLIENT_KILLED(Client_i)]; s = b+DATA_START+sizeof(DWORD); cs = (CLEAN_STRING) rmalloc (sizeof(int) + /*rstrlen(s) + 1*/ length ); rsncopy( cs->characters, s, length); cs->length = length; rstrlen(s); (*result) = cs; *client_id = pSIB->ProcessId[ INDEX(Client_i) ]; return; } void ReceiveCodeDataAdr(int code_size, int data_size, CLEAN_BOOL *result, int *code_start, int *data_start) { // char *i; #ifdef DEBUG msg( "ReceiveCodeDataAdr" ); #endif if( state != PROCESS_REQUESTS ) { msg("ReceiveCodeDataAdr: no init"); ExitProcess(-1); } // Reserve memory for server // Code if( code_size != 0 ) { CodeBuffer = (int *) VirtualAlloc( NULL,code_size,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE ); if( !CodeBuffer ) { error(); msg( "**CodeBuffer"); ExitProcess(-1); } } // Data if( data_size != 0) { DataBuffer = (int *) VirtualAlloc( NULL,data_size,MEM_RESERVE | MEM_COMMIT,PAGE_READWRITE ); if( (DataBuffer == NULL) && (data_size != 0)) { error(); msg( "DataBuffer"); ExitProcess(-1); } } // Make client reserve memory for code and data b[MESSAGE_TYPE] = ADDRESS_UNKNOWN; *((int *) (b+DATA_START)) = code_size; *((int *) (b+DATA_START+sizeof(int))) = data_size; #ifdef DEBUG msg( "ReceiveCodeDataAdr 2" ); #endif Send(); #ifdef DEBUG msg( "ReceiveCodeDataAdr 3" ); #endif // Receive message containing startaddresses if( (Receive()) == CLIENT_READY ) { CodeSize = code_size; CodeStart = *((int *) (b+DATA_START)); *code_start = CodeStart; DataSize = data_size; DataStart = *((int *) (b+DATA_START+sizeof(int))); *data_start = DataStart; // Operation correctly performed *result = CLEAN_TRUE; } else { *result = CLEAN_FALSE; // Free used server buffers (code,data) if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) { error(); msg( "ReceiveCodeDataAdr: 1" ); ExitProcess(-1); } CodeBuffer = NULL; if( !VirtualFree(DataBuffer,0,MEM_RELEASE) ) { error(); msg( "ReceiveCodeDataAdr: 2" ); ExitProcess(-1); } DataBuffer = NULL; } #ifdef DEBUG msg( "ReceiveCodeDataAdr 4"); #endif } //#define DEBUG /* ** NeedBaseLibraries */ void NeedBaseLibraries(CLEAN_STRING clstring, int n_libraries,CLEAN_BOOL *result,CLEAN_STRING *s) { char *hLibraryBufferView = NULL; #ifdef CREATE_BUFFER2 BufferInfo server_info; BufferInfo client_info; #endif #ifdef DEBUG msg( "NeedBaseLibraries 1" ); #endif if (n_libraries == 0) { *result = CLEAN_TRUE; return; } // __asm int 3 /* ** Allocate and fill buffer with library names */ #ifdef DEBUG msg( "NeedBaseLibraries 2" ); #endif // Work #ifdef CREATE_BUFFER2 CreateBuffer2( "ServerLibraryBuffer", clstring->length, FALSE, &server_info); hLibraryBufferView = server_info.hView; #else hLibraryBufferView = (char *)CreateBuffer( "ServerLibraryBuffer", clstring->length, FALSE); #endif rsncopy(hLibraryBufferView, clstring->characters,clstring->length); #ifdef DEBUG msg( "NeedBaseLibraries 3" ); rscopy( hLibraryBufferView, "Hallo!" ); sprintf( bs, "SERVER: <%s> <%d>", hLibraryBufferView, clstring->length ); msg( bs ); #endif /* ** Send a message demanding the bases of libraries */ b[MESSAGE_TYPE] = NEED_BASE_OF_LIBRARIES; *((int *) (b+DATA_START)) = n_libraries; *((int *) (b+DATA_START+sizeof(int))) = clstring->length; #ifdef DEBUG rsprintf( bs, "SERVER: n_libraries: %d, string length: %d", n_libraries, clstring->length ); msg( bs ); #endif Send(); #ifdef DEBUG msg( "NeedBaseLibraries 3a" ); #endif if( (Receive()) == CLIENT_READY ) { #ifdef CREATE_BUFFER2 CloseBuffer2( &server_info ); #else CloseBuffer( hLibraryBufferView ); #endif /* ** Answer received. Convert it to a string */ #ifdef DEBUG msg( "NeedBaseLibraries 4" ); #endif #ifdef CREATE_BUFFER2 CreateBuffer2( "ClientLibraryBuffer",BUFFER_SIZE_UNKNOWN, TRUE, &client_info); hLibraryBufferView = client_info.hView; #else hLibraryBufferView = (char *) CreateBuffer( "ClientLibraryBuffer",BUFFER_SIZE_UNKNOWN, TRUE); #endif #ifdef DEBUG msg( "NeedBaseLibraries 5" ); #endif *result = CLEAN_TRUE; *s = cleanstringn(hLibraryBufferView,sizeof(int) * n_libraries); #ifdef CREATE_BUFFER2 CloseBuffer2( &client_info ); #else CloseBuffer( hLibraryBufferView ); #endif } else { *result = CLEAN_FALSE; *s = EmptyCleanString; msg( "NeedBaseLibraries: client killed" ); } } int FlushBuffers() { DWORD lpNumberOfBytesWritten; if( (CodeBuffer != NULL) && (CodeSize !=0 ) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) CodeStart, //code, CodeBuffer, // source, CodeSize, &lpNumberOfBytesWritten) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) {" ); ExitProcess(-1); } CodeBuffer = NULL; } if( (DataBuffer != NULL) && (DataSize != 0) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) DataStart, //code, DataBuffer, // source, DataSize, NULL) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(DataBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: 1" ); ExitProcess(-1); } DataBuffer = NULL; } return 1; } int ReplyReqS(CLEAN_STRING message) { DWORD lpNumberOfBytesWritten; #ifdef DEBUG msg( "ReplyReqS" ); #endif // __asm int 3 if( state != PROCESS_REQUESTS ) { msg("ReplyReqS: no init"); ExitProcess(-1); } #ifdef DEBUG_MV if( (CodeBuffer != NULL) && (CodeSize !=0 ) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) CodeStart, //code, CodeBuffer, // source, CodeSize, &lpNumberOfBytesWritten) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) {" ); ExitProcess(-1); } CodeBuffer = NULL; } if( (DataBuffer != NULL) && (DataSize != 0) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) DataStart, //code, DataBuffer, // source, DataSize, NULL) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(DataBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: 1" ); ExitProcess(-1); } DataBuffer = NULL; } #endif b[MESSAGE_TYPE] = ADDRESS_KNOWN; // b[SIZE_OF_MESSAGE] = message->length; *((DWORD *) (b+SIZE_OF_MESSAGE)) = message->length; rsncopy( /**((char *) (b+DATA_START))*/ b + DATA_START,message->characters, message->length); Send(); #ifdef DEBUG msg( "returning from ReplyReqS" ); #endif return 1; } // ------- int ReplyReq(int num) { DWORD lpNumberOfBytesWritten; // char s[100]; #ifdef DEBUG msg( "ReplyReq" ); #endif // sprintf( s, "code size: %d, data size: %d", CodeSize, DataSize ); // msg( s ); if( state != PROCESS_REQUESTS ) { msg("ReplyReq: no init"); ExitProcess(-1); } if( (CodeBuffer != NULL) && (CodeSize !=0 ) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) CodeStart, //code, CodeBuffer, // source, CodeSize, &lpNumberOfBytesWritten) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: if( !VirtualFree(CodeBuffer,0,MEM_RELEASE) ) {" ); ExitProcess(-1); } CodeBuffer = NULL; } if( (DataBuffer != NULL) && (DataSize != 0) ) { if( !WriteProcessMemory(ClientProcessHandle, (LPVOID) DataStart, //code, DataBuffer, // source, DataSize, NULL) ) { error(); msg( "mwrites"); ExitProcess(-1); } if( !VirtualFree(DataBuffer,0,MEM_RELEASE) ) { error(); msg( "ReplyReq: 1" ); ExitProcess(-1); } DataBuffer = NULL; } b[MESSAGE_TYPE] = ADDRESS_KNOWN; *((int *) (b+DATA_START)) = num; // msg( "voor return"); Send(); #ifdef DEBUG msg( "returning from ReplyReq" ); #endif return 1; } CLEAN_BOOL KillClient(int client_id) { int i; i = (N_OF_RESERVED_ENTRIES_INITIAL_BLOCK / 2); while( i < ((N_OF_RESERVED_ENTRIES_INITIAL_BLOCK / 2) + (pSIB->n_Clients)) ) { if( (pSIB->ProcessId)[i] == client_id ) { TerminateProcess( pSIB->hClientKilledOrReady[2 * i + CLIENT_KILLED], 0 ); return( CLEAN_TRUE ); } i++; } msg( "KillClient: internal error; could not kill client process" ); ExitProcess(-1); return( CLEAN_FALSE ); }