8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-26 07:23:08 +01:00
firebird-mirror/src/remote/srvr_w32.cpp
eku 0c1b55dd08 Code cleanup:
Since we already have the define ISC_STATUS_LENGTH for the the length of
the status vector, we should use it! Replaced 'status[20]' with
'status[ISC_STATUS_LENGTH]'.

Replaced the different symbolic names for the maximum length of a path
(MAX_PATH, MAX_PATH_LENGTH, MAXPATHLEN) with one uniq symbol MAXPATHLEN.
2002-10-24 09:01:44 +00:00

567 lines
14 KiB
C++

/************* history ************
*
* COMPONENT: REMOTE MODULE: SRVR_W32.C
* generated by Marion V2.5 2/6/90
* from dev db on 26-JAN-1996
*****************************************************************
*
* 20927 klaus 26-JAN-1996
* Call ICS_enter at start
*
* 20858 klaus 17-JAN-1996
* Get rid of extraneous header file
*
* 20841 klaus 12-JAN-1996
* Add interprocess comm under remote component
*
* 20804 RCURRY 9-JAN-1996
* Change priority for NP threads to normal
*
* 20768 klaus 20-DEC-1995
* More xnet driver work
*
* 20729 klaus 8-DEC-1995
* Begin adding xnet protocol
*
* 20716 jmayer 6-DEC-1995
* Update to not show NamedPipes as supported on Win95.
*
* 20690 jmayer 4-DEC-1995
* Change to start the IPC protocol when running as a service.
*
* 20682 jmayer 3-DEC-1995
* Update to write to logfile and display msg box as a non-service.
*
* 20373 RCURRY 24-OCT-1995
* Fix bug with license checking
*
* 20359 RMIDEKE 23-OCT-1995
* add a semicollin
*
* 20356 rcurry 23-OCT-1995
* Add more license file checking
*
* 20350 RCURRY 20-OCT-1995
* add license file checking for remote protocols
*
* 20281 RCURRY 13-OCT-1995
* fix multi thread scheduler problem
*
* 20198 RCURRY 27-SEP-1995
* Make Windows95 and Windows NT have the same defaults
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2001.11.20: Claudio Valderrama: Honor -b in SS for high priority.
*
*/
/*
* PROGRAM: JRD Remote Server
* MODULE: nt_server.c
* DESCRIPTION: Windows NT remote server.
*
* copyright (c) 1993, 1996 by Borland International
*/
#include "firebird.h"
#include "../jrd/ib_stdio.h"
#include <stdlib.h>
#include <windows.h>
#include "../remote/remote.h"
#include "gen/codes.h"
#include "../jrd/license.h"
#include "../jrd/thd.h"
#include "../jrd/license.h"
#include "../utilities/install_nt.h"
#include "../remote/cntl_proto.h"
#include "../remote/inet_proto.h"
#include "../remote/serve_proto.h"
#include "../remote/window_proto.h"
#include "../remote/wnet_proto.h"
#include "../remote/window.rh"
#ifdef XNET
#include "../remote/xnet_proto.h"
#endif /* XNET */
#include "../jrd/gds_proto.h"
#include "../jrd/license.h"
#include "../jrd/sch_proto.h"
#include "../jrd/svc_proto.h"
#include "../jrd/isc_proto.h"
#include "../jrd/thd_proto.h"
#include "../jrd/jrd_proto.h"
#include "../jrd/isc_i_proto.h"
#include "../jrd/isc.h"
#include "../jrd/file_params.h"
static void THREAD_ROUTINE process_connection_thread(PORT);
static void THREAD_ROUTINE inet_connect_wait_thread(void *);
static void THREAD_ROUTINE ipc_connect_wait_thread(void *);
static void service_connection(PORT);
static void THREAD_ROUTINE start_connections_thread(int);
static void THREAD_ROUTINE wnet_connect_wait_thread(void *);
static HANDLE parse_args(LPSTR, USHORT *);
static HINSTANCE hInst;
static TEXT protocol_inet[128];
static TEXT protocol_wnet[128];
static USHORT server_flag;
static SERVICE_TABLE_ENTRY service_table[] = {
REMOTE_SERVICE, (LPSERVICE_MAIN_FUNCTION) CNTL_main_thread,
NULL, NULL
};
/* CPU affinity setting - default is first CPU only */
static SLONG g_CPU_affinity_mask = ISCCFG_CPU_AFFINITY_DEF;
static struct ipccfg CPU_affinity_setting[] =
{
{ ISCCFG_CPU_AFFINITY_TAG, 0, &g_CPU_affinity_mask, 0, 0 },
{ NULL, 0, NULL, 0, 0 }
};
#ifdef XNET
/* put into ensure that we have a parent port for the XNET connections */
static int xnet_server_set = FALSE;
#endif /* XNET */
int WINAPI WinMain(HINSTANCE hThisInst,
HINSTANCE hPrevInst,
LPSTR lpszArgs,
int nWndMode)
{
/**************************************
*
* W i n M a i n
*
**************************************
*
* Functional description
* Run the server with NT named
* pipes and/or TCP/IP sockets.
*
**************************************/
HANDLE connection_handle;
int nReturnValue = 0;
hInst = hThisInst;
if (ISC_is_WinNT()) { /* True - NT, False - Win95 */
/* CVC: This operating system call doesn't exist for W9x. */
typedef BOOL (__stdcall *PSetProcessAffinityMask)(HANDLE, DWORD);
PSetProcessAffinityMask SetProcessAffinityMask;
server_flag = (SRVR_multi_client);
SetProcessAffinityMask = (PSetProcessAffinityMask)
GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "SetProcessAffinityMask");
if (SetProcessAffinityMask) {
/* Mike Nordell - 11 Jun 2001: CPU affinity. */
ISC_get_config (LOCK_HEADER, CPU_affinity_setting);
(*SetProcessAffinityMask)(GetCurrentProcess(),
static_cast<DWORD>(g_CPU_affinity_mask));
}
}
else
server_flag = (SRVR_multi_client | SRVR_non_service);
gds__thread_enable(-1);
protocol_inet[0] = 0;
protocol_wnet[0] = 0;
connection_handle = parse_args(lpszArgs, &server_flag);
if (ISC_is_WinNT()) /* True - NT, False - Win95 */
server_flag |= (SRVR_inet | SRVR_pipe);
else
server_flag |= SRVR_inet;
server_flag |= SRVR_ipc;
/* CVC: Honor -b for SS on Win32. */
#ifdef SUPERSERVER
if (server_flag & SRVR_high_priority)
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
#endif
/* Initialize the service and
Setup sig_mutex for the process
*/
ISC_signal_init();
ISC_enter();
if (!(server_flag & SRVR_non_service)) {
CNTL_init((FPTR_VOID) start_connections_thread, REMOTE_SERVICE);
if (!StartServiceCtrlDispatcher(service_table)) {
if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
CNTL_shutdown_service("StartServiceCtrlDispatcher failed");
}
server_flag |= SRVR_non_service;
}
}
else {
if ((server_flag & SRVR_inet) &&
((server_flag & SRVR_pipe) || (server_flag & SRVR_non_service))) {
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(inet_connect_wait_thread), 0, THREAD_medium, 0,
0);
}
if ((server_flag & SRVR_pipe) && (server_flag & SRVR_non_service)) {
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(wnet_connect_wait_thread), 0, THREAD_medium, 0,
0);
}
/* No need to waste a thread if we are running as a window. Just start
* the ipc communication
*/
if (server_flag & SRVR_non_service) {
nReturnValue = WINDOW_main(hThisInst, nWndMode, server_flag);
}
}
return nReturnValue;
}
#ifdef XNET
ULONG SRVR_xnet_start_thread(ULONG client_pid)
{
/**************************************
*
* S R V R _ x n e t _ s t a r t _ t h r e a d
*
**************************************
*
* Functional description
* Start an interprocess thread. This allocates
* the next available chunk of the mapped file and
* tells the client where it is.
*
**************************************/
PORT port;
ULONG response;
/* get a port */
port = XNET_start_thread(client_pid, &response);
/* Ensure that the main port is set with this new port if we are the first
* XNET connection
*/
if (!xnet_server_set) {
USHORT flags = ((USHORT) SRVR_xnet | (USHORT) SRVR_multi_client |
(USHORT) SRVR_thread_per_port);
PORT xnet_header_port = (PORT) ALLR_alloc(sizeof(struct port));
if (xnet_header_port)
*xnet_header_port = *port;
else
return FALSE;
xnet_server_set = TRUE;
(void) set_server(xnet_header_port, flags);
}
/* start the thread for this client */
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(process_connection_thread), port,
THREAD_medium, 0, 0);
/* return combined mapped area and number */
return response;
}
#endif /* XNET */
static void THREAD_ROUTINE process_connection_thread( PORT port)
{
/**************************************
*
* p r o c e s s _ c o n n e c t i o n _ t h r e a d
*
**************************************
*
* Functional description
*
**************************************/
void *thread;
if (!(server_flag & SRVR_non_service)) {
thread = CNTL_insert_thread();
}
service_connection(port);
if (!(server_flag & SRVR_non_service)) {
CNTL_remove_thread(thread);
}
}
static void THREAD_ROUTINE inet_connect_wait_thread( void *dummy)
{
/**************************************
*
* i n e t _ c o n n e c t _ w a i t _ t h r e a d
*
**************************************
*
* Functional description
*
**************************************/
void *thread;
STATUS status_vector[ISC_STATUS_LENGTH];
PORT port;
if (!(server_flag & SRVR_non_service))
thread = CNTL_insert_thread();
THREAD_ENTER;
port = INET_connect(protocol_inet, 0, status_vector, server_flag, 0, 0);
THREAD_EXIT;
if (port)
SRVR_multi_thread(port, server_flag);
else
gds__log_status(0, status_vector);
if (!(server_flag & SRVR_non_service))
CNTL_remove_thread(thread);
}
static void THREAD_ROUTINE wnet_connect_wait_thread( void *dummy)
{
/**************************************
*
* w n e t _ c o n n e c t _ w a i t _ t h r e a d
*
**************************************
*
* Functional description
*
**************************************/
void *thread;
STATUS status_vector[ISC_STATUS_LENGTH];
PORT port;
if (!(server_flag & SRVR_non_service))
thread = CNTL_insert_thread();
while (TRUE) {
THREAD_ENTER;
port = WNET_connect(protocol_wnet, 0, status_vector, server_flag);
THREAD_EXIT;
if (!port) {
if (status_vector[1] != gds_io_error ||
status_vector[6] != gds_arg_win32 ||
status_vector[7] != ERROR_CALL_NOT_IMPLEMENTED) {
gds__log_status(0, status_vector);
}
break;
}
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(process_connection_thread), port, THREAD_medium, 0,
0);
}
if (!(server_flag & SRVR_non_service)) {
CNTL_remove_thread(thread);
}
}
static void THREAD_ROUTINE ipc_connect_wait_thread( void *dummy)
{
/**************************************
*
* i p c _ c o n n e c t _ w a i t _ t h r e a d
*
**************************************
*
* Functional description
*
**************************************/
void *thread;
if (!(server_flag & SRVR_non_service))
thread = CNTL_insert_thread();
WINDOW_main(hInst, SW_NORMAL, server_flag);
if (!(server_flag & SRVR_non_service))
CNTL_remove_thread(thread);
}
static void service_connection( PORT port)
{
/**************************************
*
* s e r v i c e _ c o n n e c t i o n
*
**************************************
*
* Functional description
*
**************************************/
SRVR_main(port, (USHORT) (server_flag & ~SRVR_multi_client));
}
static void THREAD_ROUTINE start_connections_thread( int flag)
{
/**************************************
*
* s t a r t _ c o n n e c t i o n s _ t h r e a d
*
**************************************
*
* Functional description
*
**************************************/
HANDLE ipc_thread_handle = 0;
#ifndef XNET
if (server_flag & SRVR_ipc) {
const int bFailed =
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(ipc_connect_wait_thread),
0,
THREAD_medium,
0,
&ipc_thread_handle);
if (bFailed ||
WaitForSingleObject(ipc_thread_handle, 2000) != WAIT_TIMEOUT) {
/* If the IPC thread did not time out, then it must have finished. *
* the only way for it to have finished in 2 seconds is for it to *
* not have succeeded. IE. It already exists. */
if (!bFailed && ipc_thread_handle) {
CloseHandle(ipc_thread_handle);
}
CNTL_shutdown_service("Could not start service");
return;
}
}
#endif /* XNET */
if (server_flag & SRVR_inet) {
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(inet_connect_wait_thread), 0, THREAD_medium, 0, 0);
}
if (server_flag & SRVR_pipe) {
gds__thread_start(reinterpret_cast < FPTR_INT_VOID_PTR >
(wnet_connect_wait_thread), 0, THREAD_medium, 0, 0);
}
}
static HANDLE parse_args( LPSTR lpszArgs, USHORT * pserver_flag)
{
/**************************************
*
* p a r s e _ a r g s
*
**************************************
*
* Functional description
* WinMain gives us a stupid command string, not
* a cool argv. Parse through the string and
* set the options.
* Returns
* a connection handle if one was passed in,
* INVALID_HANDLE_VALUE otherwise.
*
**************************************/
TEXT *p, c;
HANDLE connection_handle;
connection_handle = INVALID_HANDLE_VALUE;
p = lpszArgs;
while (*p) {
if (*p++ == '-')
while ((*p) && (c = *p++) && (c != ' '))
switch (UPPER(c)) {
case 'A':
*pserver_flag |= SRVR_non_service;
break;
case 'B':
*pserver_flag |= SRVR_high_priority;
break;
case 'D':
*pserver_flag |= SRVR_debug | SRVR_non_service;
break;
case 'N':
*pserver_flag |= SRVR_no_icon;
break;
#ifdef XNET
case 'X':
*pserver_flag |= SRVR_xnet;
break;
#endif /* XNET */
case 'P': /* Specify a port or named pipe other than the default */
while (*p && *p == ' ')
p++;
if (*p) {
char *pi = protocol_inet, *pw = protocol_wnet;
*pi++ = '/';
*pw++ = '\\';
*pw++ = '\\';
*pw++ = '.';
*pw++ = '@';
while (*p && *p != ' ') {
*pi++ = *p;
*pw++ = *p++;
}
*pi++ = '\0';
*pw++ = '\0';
}
break;
case 'R':
*pserver_flag &= ~SRVR_high_priority;
break;
case 'Z':
ib_printf("Interbase remote server version %s\n",
GDS_VERSION);
exit(FINI_OK);
default:
/* In case of something unrecognized, just
* continue, since we have already taken it off
* of p. */
break;
}
}
return connection_handle;
}