137 lines
6.8 KiB
C++
137 lines
6.8 KiB
C++
/*======================================================================================//
|
|
| //
|
|
|Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved. //
|
|
| //
|
|
|Description: //
|
|
| //
|
|
| Windows 2000 Process Control 'mediator' process. Holds handles and completion port //
|
|
| for created jobs so that their names are not lost if the ProcCon service is stopped //
|
|
| or goes away. //
|
|
| //
|
|
|Created: //
|
|
| //
|
|
| Jarl McDonald 04-99 //
|
|
| //
|
|
|Revision History: //
|
|
| //
|
|
|=======================================================================================*/
|
|
#include "..\SERVICE\ProcConSvc.h"
|
|
|
|
//=======================================================================================
|
|
// Main...
|
|
//=======================================================================================
|
|
int _cdecl main( void ) {
|
|
|
|
// Load our strings so we have proper reporting, etc.
|
|
PCLoadStrings();
|
|
CVersion *versionInfo = new CVersion( GetModuleHandle( NULL ) );
|
|
|
|
static const TCHAR * const msgs[] = { PROCCON_MEDIATOR_DISP_NAME, PROCCON_SVC_DISP_NAME };
|
|
|
|
// Make sure we're not already running and set up mutual exclusion...
|
|
if ( !PCSetIsRunning( PC_MEDIATOR_EXCLUSION, PROCCON_MEDIATOR_DISP_NAME ) )
|
|
return 1;
|
|
|
|
// Get our event -- it must already exist (created by the service) or we quit...
|
|
HANDLE hSvcEvent = CreateEvent( NULL, FALSE, FALSE, PC_MEDIATOR_EVENT );
|
|
if ( !hSvcEvent ) {
|
|
PCLogUnExError( PC_MEDIATOR_EVENT, TEXT("MediatorCreateEvent") );
|
|
return 1;
|
|
}
|
|
else if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
|
|
PCLogMessage( PC_MEDIATE_SVC_NEVER_STARTED, EVENTLOG_ERROR_TYPE, ENTRY_COUNT(msgs), msgs );
|
|
CloseHandle( hSvcEvent );
|
|
return 1;
|
|
}
|
|
|
|
// Get our file mapping object -- it must already exist (created by the service) or we quit...
|
|
HANDLE hSvcJobMap = CreateFileMapping( HANDLE_FF_64, NULL, PAGE_READWRITE,
|
|
0, sizeof(PCMediateHdr), PC_MEDIATOR_FILEMAP );
|
|
if ( !hSvcJobMap ) {
|
|
PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("MediatorCreateMapping") );
|
|
CloseHandle( hSvcEvent );
|
|
return 1;
|
|
}
|
|
else if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
|
|
PCLogMessage( PC_MEDIATE_SVC_NEVER_STARTED, EVENTLOG_ERROR_TYPE, ENTRY_COUNT(msgs), msgs );
|
|
CloseHandle( hSvcJobMap );
|
|
CloseHandle( hSvcEvent );
|
|
return 1;
|
|
}
|
|
|
|
// Get our data pointer -- quit if we can't since we'd have nothing to do.
|
|
PCMediateHdr *jobData = (PCMediateHdr *) MapViewOfFile( hSvcJobMap, FILE_MAP_WRITE, 0, 0, 0 );
|
|
if ( !jobData ) {
|
|
PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("MediatorMapJobData") );
|
|
CloseHandle( hSvcJobMap );
|
|
CloseHandle( hSvcEvent );
|
|
return 1;
|
|
}
|
|
|
|
// Update data about us in case we restarted...
|
|
jobData->medProcessInfo.dwProcessId = GetCurrentProcessId();
|
|
jobData->medProcessInfo.dwThreadId = GetCurrentThreadId();
|
|
|
|
_tcsncpy( jobData->medFileVersion, versionInfo->GetFileVersion(), VERSION_STRING_LEN );
|
|
_tcsncpy( jobData->medProductVersion, versionInfo->GetProductVersion(), VERSION_STRING_LEN );
|
|
_tcsncpy( jobData->medFileFlags, versionInfo->GetFileFlags(), VERSION_STRING_LEN );
|
|
|
|
// Duplicate ProcCon's completion port handle here to preserve it...
|
|
HANDLE hServiceProc = OpenProcess( PROCESS_DUP_HANDLE, FALSE, (DWORD) jobData->svcPID ); // truncation of PID to 32-bit
|
|
if ( !hServiceProc ) {
|
|
PCLogUnExError( jobData->svcPID, TEXT("MediatorOpenSvcPID") );
|
|
CloseHandle( hSvcJobMap );
|
|
CloseHandle( hSvcEvent );
|
|
return 1;
|
|
}
|
|
|
|
if ( !DuplicateHandle( hServiceProc,
|
|
jobData->svcPortHandle,
|
|
GetCurrentProcess(),
|
|
&jobData->medPortHandle,
|
|
NULL,
|
|
FALSE,
|
|
DUPLICATE_SAME_ACCESS ) )
|
|
PCLogUnExError( TEXT("ComplPort"), TEXT("MediatorDupHandle") );
|
|
|
|
CloseHandle( hServiceProc );
|
|
|
|
// We're ready to run. On the first pass we'll open all jobs. Otherwise just the new jobs.
|
|
ResetEvent( hSvcEvent ); // don't need to be signalled for first pass
|
|
for ( BOOL firstPass = TRUE; ; firstPass = FALSE ) {
|
|
// duplicate all chained block handles as needed...
|
|
jobData->MedChainBlocks( firstPass );
|
|
// duplicate all job object handles in chain as needed...
|
|
for ( PCMediateBlock *blk = &jobData->groupBlock; blk; blk = jobData->NextBlock( blk ) ) {
|
|
for ( PCULONG32 grp = 0; grp < blk->groupCount; ++grp ) {
|
|
if ( firstPass && !(blk->group[grp].groupFlags & PCMEDIATE_CLOSE_ME) ) {
|
|
blk->group[grp].mediatorHandle =
|
|
OpenJobObject( JOB_OBJECT_QUERY, FALSE, blk->group[grp].groupName );
|
|
if ( !blk->group[grp].mediatorHandle )
|
|
PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorOpenJob1") );
|
|
}
|
|
else if ( blk->group[grp].groupFlags & PCMEDIATE_CLOSE_ME ) {
|
|
if ( blk->group[grp].mediatorHandle && !CloseHandle( blk->group[grp].mediatorHandle ) )
|
|
PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorCloseJob") );
|
|
blk->group[grp].mediatorHandle = NULL;
|
|
}
|
|
else if ( !blk->group[grp].mediatorHandle ) {
|
|
blk->group[grp].mediatorHandle =
|
|
OpenJobObject( JOB_OBJECT_QUERY, FALSE, blk->group[grp].groupName );
|
|
if ( !blk->group[grp].mediatorHandle )
|
|
PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorOpenJob2") );
|
|
}
|
|
}
|
|
}
|
|
// Wait for signal that a new job exists.
|
|
// If the wait fails, just exit, else we reprocess job list...
|
|
if ( WAIT_OBJECT_0 != WaitForSingleObject( hSvcEvent, INFINITE ) )
|
|
break;
|
|
}
|
|
|
|
CloseHandle( hSvcJobMap );
|
|
CloseHandle( hSvcEvent );
|
|
return 0;
|
|
}
|
|
|