windows-nt/Source/XPSP1/NT/sdktools/proccon/mediate/pcmediate.cpp
2020-09-26 16:20:57 +08:00

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;
}