404 lines
16 KiB
C++
404 lines
16 KiB
C++
|
/*======================================================================================//
|
||
|
| //
|
||
|
|Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated //
|
||
|
| //
|
||
|
|Description: //
|
||
|
| //
|
||
|
|---------------------------------------------------------------------------------------//
|
||
|
| This file contains the ProcCon NT service install and remove functions //
|
||
|
|---------------------------------------------------------------------------------------//
|
||
|
| //
|
||
|
|Created: //
|
||
|
| //
|
||
|
| Jarl McDonald 07-98 //
|
||
|
| //
|
||
|
|Revision History: //
|
||
|
| Jarl McDonald 19-08-99 change service start type to auto //
|
||
|
| //
|
||
|
|=======================================================================================*/
|
||
|
#include "ProcConSvc.h"
|
||
|
|
||
|
//========================================================================================
|
||
|
// function to install the ProcCon service... no input or output
|
||
|
// Note: installation also includes the EventLog entries necessary to
|
||
|
// resolve our event log messages.
|
||
|
//
|
||
|
void PCInstallService(int argc, TCHAR **argv) {
|
||
|
|
||
|
TCHAR path[MAX_PATH], err[512];
|
||
|
|
||
|
// Use security descriptor that allows admin access for our registry data.
|
||
|
// Post-installation the access list may need to be tailored.
|
||
|
SECURITY_ATTRIBUTES adminAttr;
|
||
|
if ( !PCBuildAdminSecAttr( adminAttr ) ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_UNABLE_TO_INSTALL, GetLastError(), args );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Get our module name -- needed to install service and error log message file...
|
||
|
if ( !GetModuleFileName( NULL, path, MAX_PATH ) ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_UNABLE_TO_INSTALL, GetLastError(), args );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Open SCM and install ourselves...
|
||
|
SC_HANDLE hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE );
|
||
|
PCULONG32 rc = GetLastError();
|
||
|
|
||
|
TCHAR *acct = NULL, *pswd = NULL;
|
||
|
if ( argc > 0 ) acct = argv[0];
|
||
|
if ( argc > 1 ) pswd = argv[1];
|
||
|
|
||
|
if ( hSCManager ) {
|
||
|
SC_HANDLE hService = CreateService( hSCManager, // SCManager database
|
||
|
PROCCON_SVC_NAME, // name of service
|
||
|
PROCCON_SVC_DISP_NAME, // name to display
|
||
|
GENERIC_READ, // desired access
|
||
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
||
|
SERVICE_AUTO_START, // start type -- auto by MS req.
|
||
|
SERVICE_ERROR_NORMAL, // error control type
|
||
|
path, // service's binary
|
||
|
NULL, // no load ordering group
|
||
|
NULL, // no tag identifier
|
||
|
TEXT(""), // dependencies
|
||
|
acct, // account or NULL
|
||
|
pswd); // password or NULL
|
||
|
|
||
|
// If installed, add related registry keys...
|
||
|
rc = GetLastError();
|
||
|
if ( hService ) {
|
||
|
PCLogStdout( PC_SERVICE_SERVICE_INSTALLED, PROCCON_SVC_DISP_NAME );
|
||
|
CloseServiceHandle(hService);
|
||
|
|
||
|
HKEY hKey;
|
||
|
PCULONG32 regDisp, types = 0x07;
|
||
|
TCHAR key[512];
|
||
|
|
||
|
// Add registry key describing service...
|
||
|
PCBuildBaseKey( key );
|
||
|
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, key, 0, KEY_READ + KEY_WRITE, &hKey );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
|
||
|
PCLogErrStdout( PC_SERVICE_REGISTRY_OPEN_FAILED,
|
||
|
rc,
|
||
|
args );
|
||
|
} else {
|
||
|
rc = RegSetValueEx( hKey, PROCCON_SERVICE_DESCRIPTION_NAME, NULL, REG_SZ,
|
||
|
(UCHAR *) PROCCON_SERVICE_DESCRIPTION,
|
||
|
(_tcslen( PROCCON_SERVICE_DESCRIPTION ) + 1) * sizeof(TCHAR) );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVICE_DESCRIPTION_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_ADD_VALUE_SERVICE_DESC_FAILED, rc, args );
|
||
|
}
|
||
|
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
|
||
|
// Add registry key describing server application...
|
||
|
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, PROCCON_SERVER_APP_KEY, 0, KEY_SET_VALUE, &hKey );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_KEY };
|
||
|
PCLogErrStdout( PC_SERVICE_APP_KEY_OPEN_FAILED, rc, args );
|
||
|
} else {
|
||
|
rc = RegSetValueEx( hKey, PROCCON_SERVER_APP_VALUE_NAME, NULL, REG_SZ,
|
||
|
(UCHAR *) PROCCON_SVC_DISP_NAME,
|
||
|
(_tcslen( PROCCON_SVC_DISP_NAME ) + 1) * sizeof(TCHAR) );
|
||
|
if ( rc == ERROR_SUCCESS )
|
||
|
PCLogStdout( PC_SERVICE_APP_KEY_CREATED, PROCCON_SVC_DISP_NAME );
|
||
|
else {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_VALUE_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_APP_KEY_ADD_FAILED,
|
||
|
rc,
|
||
|
args );
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
|
||
|
// Add registry key to support ProcCon event log messages...
|
||
|
// NULL security attribute is used to cause inheritance of attributes.
|
||
|
PCBuildMsgKey( key );
|
||
|
rc = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key,
|
||
|
0, TEXT(""), 0, KEY_READ + KEY_WRITE, NULL, &hKey, ®Disp );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
|
||
|
PCLogErrStdout( PC_SERVICE_REG_KEY_CREATE_FAILED,
|
||
|
rc,
|
||
|
args );
|
||
|
} else {
|
||
|
BOOL fname = TRUE;
|
||
|
rc = RegSetValueEx( hKey, EVENT_MSG_FILE_NAME, NULL, REG_SZ,
|
||
|
(UCHAR *) path, (_tcslen( path ) + 1) * sizeof(path[0]) );
|
||
|
if ( rc == ERROR_SUCCESS ) {
|
||
|
fname = FALSE;
|
||
|
rc = RegSetValueEx( hKey, EVENT_MSG_TYPES_SUPPORT, NULL, REG_DWORD,
|
||
|
(UCHAR *) &types, sizeof( types ) );
|
||
|
}
|
||
|
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL,
|
||
|
PROCCON_SVC_DISP_NAME,
|
||
|
fname
|
||
|
? EVENT_MSG_FILE_NAME
|
||
|
: EVENT_MSG_TYPES_SUPPORT };
|
||
|
PCLogErrStdout( PC_SERVICE_EVENTLOG_REG_SETUP_FAILED,
|
||
|
rc,
|
||
|
args );
|
||
|
} else {
|
||
|
PCLogStdout( PC_SERVICE_EVENTLOG_REG_SETUP, PROCCON_SVC_DISP_NAME );
|
||
|
}
|
||
|
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
|
||
|
// Add registry keys to support ProcCon...
|
||
|
// Security attribute for the PARAMETERS key is local administrators only.
|
||
|
// Security attribute for the access keys is local administrators only also.
|
||
|
PCBuildParmKey( key );
|
||
|
rc = RegCreateKeyEx( HKEY_LOCAL_MACHINE, key,
|
||
|
0, TEXT(""), 0, KEY_READ + KEY_WRITE, &adminAttr, &hKey, ®Disp );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
|
||
|
PCLogErrStdout( PC_SERVICE_PARAM_KEY_CREATE_FAILED, rc, args );
|
||
|
} else {
|
||
|
rc = RegSetValueEx( hKey, PROCCON_DATA_NAMERULES, NULL, REG_MULTI_SZ,
|
||
|
(UCHAR *) TEXT("\0\0"), 2 * sizeof(TCHAR) );
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_DATA_NAMERULES };
|
||
|
PCLogErrStdout( PC_SERVICE_PARAM_DATA_UPDATE_FAILED, rc, args );
|
||
|
} else {
|
||
|
HKEY hTemp;
|
||
|
for ( int i = 0; i < ENTRY_COUNT( accessKeyList ); ++i ) {
|
||
|
rc = RegCreateKeyEx( hKey, accessKeyList[i], 0, TEXT(""), 0,
|
||
|
KEY_WRITE, &adminAttr, &hTemp, ®Disp );
|
||
|
if ( rc == ERROR_SUCCESS ) RegCloseKey( hTemp );
|
||
|
else {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, accessKeyList[i] };
|
||
|
PCLogErrStdout( PC_SERVICE_PARAM_DATA_UPDATE_FAILED, rc, args );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if ( rc == ERROR_SUCCESS ) {
|
||
|
PCLogStdout( PC_SERVICE_PARAM_DATA_CREATED, PROCCON_SVC_DISP_NAME );
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_CREATESERVICE_FAILED, rc, args );
|
||
|
}
|
||
|
CloseServiceHandle(hSCManager);
|
||
|
}
|
||
|
else {
|
||
|
PCLogErrStdout( PC_SERVICE_OPENSCMGR_FAILED, rc, NULL );
|
||
|
}
|
||
|
PCFreeSecAttr( adminAttr );
|
||
|
}
|
||
|
|
||
|
//=============================================================================================
|
||
|
// function to remove (deinstall) the service... no input or output
|
||
|
//
|
||
|
void PCRemoveService(int argc, TCHAR **argv) {
|
||
|
|
||
|
TCHAR err[512];
|
||
|
|
||
|
// Open SCM and service then proceed with stop and delete...
|
||
|
SC_HANDLE hSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
|
||
|
if ( hSCManager ) {
|
||
|
SC_HANDLE hService = OpenService( hSCManager, PROCCON_SVC_NAME, SERVICE_ALL_ACCESS );
|
||
|
|
||
|
if ( hService ) {
|
||
|
|
||
|
// try to stop the service...
|
||
|
if ( ControlService( hService, SERVICE_CONTROL_STOP, &ssStatus ) ) {
|
||
|
PCLogStdout( PC_SERVICE_STOPPING, PROCCON_SVC_DISP_NAME );
|
||
|
Sleep( 1000 );
|
||
|
|
||
|
while( QueryServiceStatus( hService, &ssStatus ) ) {
|
||
|
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
|
||
|
PCLogStdout( PC_SERVICE_DOT );
|
||
|
Sleep( 1000 );
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( ssStatus.dwCurrentState == SERVICE_STOPPED ) {
|
||
|
PCLogStdout( PC_SERVICE_STOPPING_STOPPED, PROCCON_SVC_DISP_NAME );
|
||
|
} else {
|
||
|
PCLogStdout( PC_SERVICE_FAILED_TO_STOP, PROCCON_SVC_DISP_NAME );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// now remove the service...
|
||
|
if( DeleteService( hService ) ) {
|
||
|
PCLogStdout( PC_SERVICE_REG_ENTRIES_REMOVED, PROCCON_SVC_DISP_NAME );
|
||
|
}
|
||
|
else {
|
||
|
PCLogErrStdout( PC_SERVICE_DELETE_SVC_FAILED, GetLastError(), NULL );
|
||
|
}
|
||
|
CloseServiceHandle( hService );
|
||
|
}
|
||
|
else {
|
||
|
PCLogErrStdout( PC_SERVICE_OPEN_SVC_FAILED, GetLastError(), NULL );
|
||
|
}
|
||
|
CloseServiceHandle( hSCManager );
|
||
|
}
|
||
|
else {
|
||
|
PCLogErrStdout( PC_SERVICE_OPENSCMGR_FAILED, GetLastError(), NULL );
|
||
|
}
|
||
|
HKEY hKey;
|
||
|
TCHAR key[512];
|
||
|
// now remove server application registry keys...
|
||
|
PCULONG32 rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, PROCCON_SERVER_APP_KEY, 0, KEY_SET_VALUE, &hKey );
|
||
|
if ( rc == ERROR_SUCCESS ) {
|
||
|
rc = RegDeleteValue( hKey, PROCCON_SERVER_APP_VALUE_NAME );
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
if ( rc == ERROR_SUCCESS ) {
|
||
|
PCLogStdout( PC_SERVICE_APP_REG_ENTRY_DELETED, PROCCON_SVC_DISP_NAME );
|
||
|
} else if ( rc != ERROR_FILE_NOT_FOUND ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, PROCCON_SERVER_APP_VALUE_NAME };
|
||
|
PCLogErrStdout( PC_SERVICE_APP_REG_ENTRY_DEL_FAILED, rc, args );
|
||
|
}
|
||
|
|
||
|
// now remove message registry keys...
|
||
|
PCBuildMsgKey( key );
|
||
|
rc = RegDeleteKey( HKEY_LOCAL_MACHINE, key );
|
||
|
if ( rc == ERROR_SUCCESS || rc == ERROR_KEY_DELETED ) {
|
||
|
PCLogStdout( PC_SERVICE_EVTLOG_REG_DELETED, PROCCON_SVC_DISP_NAME );
|
||
|
} else if ( rc != ERROR_FILE_NOT_FOUND ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
|
||
|
PCLogErrStdout( PC_SERVICE_EVTLOG_REG_DEL_FAILED, rc, args );
|
||
|
}
|
||
|
|
||
|
// now attempt removal of parameter registry keys...
|
||
|
// (Delete of the service should have already deleted the Parameters sub-key)
|
||
|
PCBuildParmKey( key );
|
||
|
rc = PCDeleteKeyTree( HKEY_LOCAL_MACHINE, key );
|
||
|
// PCDeleteKeyTree does not return ERROR_KEY_DELETED or ERROR_FILE_NOT_FOUND
|
||
|
if ( rc != ERROR_SUCCESS ) {
|
||
|
const VOID *args[] = { NULL, PROCCON_SVC_DISP_NAME, key };
|
||
|
PCLogErrStdout( PC_SERVICE_REG_TREE_DEL_FAILED, rc, args );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
PCWriteStdout(
|
||
|
PTCHAR Buffer,
|
||
|
DWORD BufferLen
|
||
|
)
|
||
|
{
|
||
|
DWORD Written;
|
||
|
|
||
|
static BOOL ConsoleWorks = TRUE;
|
||
|
static HANDLE StdOutHandle = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
if (StdOutHandle == INVALID_HANDLE_VALUE) {
|
||
|
StdOutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||
|
}
|
||
|
|
||
|
if (ConsoleWorks) {
|
||
|
ConsoleWorks = WriteConsole(StdOutHandle,
|
||
|
Buffer,
|
||
|
BufferLen,
|
||
|
&Written,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
if (! ConsoleWorks) {
|
||
|
WriteFile(StdOutHandle,
|
||
|
Buffer,
|
||
|
BufferLen * sizeof(TCHAR),
|
||
|
&Written,
|
||
|
NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CDECL
|
||
|
PCLogStdout(
|
||
|
const PCULONG32 msgCode,
|
||
|
...
|
||
|
)
|
||
|
{
|
||
|
va_list args;
|
||
|
PTCHAR Buffer;
|
||
|
DWORD BufferLen;
|
||
|
|
||
|
va_start(args, msgCode);
|
||
|
|
||
|
BufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||
|
| FORMAT_MESSAGE_FROM_HMODULE,
|
||
|
NULL,
|
||
|
msgCode,
|
||
|
0,
|
||
|
(LPWSTR) &Buffer,
|
||
|
1,
|
||
|
&args);
|
||
|
|
||
|
va_end(args);
|
||
|
|
||
|
if (BufferLen) {
|
||
|
PCWriteStdout(Buffer, BufferLen);
|
||
|
LocalFree(Buffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
PCLogErrStdout(
|
||
|
const PCULONG32 msgCode,
|
||
|
const PCULONG32 errCode,
|
||
|
const VOID **args
|
||
|
)
|
||
|
{
|
||
|
PTCHAR Buffer;
|
||
|
PTCHAR ErrBuffer;
|
||
|
DWORD BufferLen;
|
||
|
DWORD ErrBufferLen;
|
||
|
|
||
|
ErrBufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||
|
| FORMAT_MESSAGE_IGNORE_INSERTS
|
||
|
| FORMAT_MESSAGE_FROM_SYSTEM,
|
||
|
0,
|
||
|
errCode,
|
||
|
0,
|
||
|
(LPWSTR) &ErrBuffer,
|
||
|
1,
|
||
|
NULL);
|
||
|
|
||
|
if (ErrBufferLen) {
|
||
|
|
||
|
if (args) {
|
||
|
args[0] = ErrBuffer;
|
||
|
}
|
||
|
|
||
|
BufferLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||
|
| FORMAT_MESSAGE_FROM_HMODULE
|
||
|
| (args
|
||
|
? FORMAT_MESSAGE_ARGUMENT_ARRAY
|
||
|
: 0),
|
||
|
NULL,
|
||
|
msgCode,
|
||
|
0,
|
||
|
(LPWSTR) &Buffer,
|
||
|
1,
|
||
|
(va_list *) (args
|
||
|
? (PVOID) args
|
||
|
: (PVOID) ErrBuffer));
|
||
|
|
||
|
if (BufferLen) {
|
||
|
PCWriteStdout(Buffer, BufferLen);
|
||
|
LocalFree(Buffer);
|
||
|
}
|
||
|
|
||
|
LocalFree(ErrBuffer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// End of PCService.cpp
|
||
|
//============================================================================J McDonald fecit====//
|