Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
6.8 KiB

  1. /*======================================================================================//
  2. | //
  3. |Copyright (c) 1998, 1999 Sequent Computer Systems, Incorporated. All rights reserved. //
  4. | //
  5. |Description: //
  6. | //
  7. | Windows 2000 Process Control 'mediator' process. Holds handles and completion port //
  8. | for created jobs so that their names are not lost if the ProcCon service is stopped //
  9. | or goes away. //
  10. | //
  11. |Created: //
  12. | //
  13. | Jarl McDonald 04-99 //
  14. | //
  15. |Revision History: //
  16. | //
  17. |=======================================================================================*/
  18. #include "..\SERVICE\ProcConSvc.h"
  19. //=======================================================================================
  20. // Main...
  21. //=======================================================================================
  22. int _cdecl main( void ) {
  23. // Load our strings so we have proper reporting, etc.
  24. PCLoadStrings();
  25. CVersion *versionInfo = new CVersion( GetModuleHandle( NULL ) );
  26. static const TCHAR * const msgs[] = { PROCCON_MEDIATOR_DISP_NAME, PROCCON_SVC_DISP_NAME };
  27. // Make sure we're not already running and set up mutual exclusion...
  28. if ( !PCSetIsRunning( PC_MEDIATOR_EXCLUSION, PROCCON_MEDIATOR_DISP_NAME ) )
  29. return 1;
  30. // Get our event -- it must already exist (created by the service) or we quit...
  31. HANDLE hSvcEvent = CreateEvent( NULL, FALSE, FALSE, PC_MEDIATOR_EVENT );
  32. if ( !hSvcEvent ) {
  33. PCLogUnExError( PC_MEDIATOR_EVENT, TEXT("MediatorCreateEvent") );
  34. return 1;
  35. }
  36. else if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
  37. PCLogMessage( PC_MEDIATE_SVC_NEVER_STARTED, EVENTLOG_ERROR_TYPE, ENTRY_COUNT(msgs), msgs );
  38. CloseHandle( hSvcEvent );
  39. return 1;
  40. }
  41. // Get our file mapping object -- it must already exist (created by the service) or we quit...
  42. HANDLE hSvcJobMap = CreateFileMapping( HANDLE_FF_64, NULL, PAGE_READWRITE,
  43. 0, sizeof(PCMediateHdr), PC_MEDIATOR_FILEMAP );
  44. if ( !hSvcJobMap ) {
  45. PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("MediatorCreateMapping") );
  46. CloseHandle( hSvcEvent );
  47. return 1;
  48. }
  49. else if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
  50. PCLogMessage( PC_MEDIATE_SVC_NEVER_STARTED, EVENTLOG_ERROR_TYPE, ENTRY_COUNT(msgs), msgs );
  51. CloseHandle( hSvcJobMap );
  52. CloseHandle( hSvcEvent );
  53. return 1;
  54. }
  55. // Get our data pointer -- quit if we can't since we'd have nothing to do.
  56. PCMediateHdr *jobData = (PCMediateHdr *) MapViewOfFile( hSvcJobMap, FILE_MAP_WRITE, 0, 0, 0 );
  57. if ( !jobData ) {
  58. PCLogUnExError( PC_MEDIATOR_FILEMAP, TEXT("MediatorMapJobData") );
  59. CloseHandle( hSvcJobMap );
  60. CloseHandle( hSvcEvent );
  61. return 1;
  62. }
  63. // Update data about us in case we restarted...
  64. jobData->medProcessInfo.dwProcessId = GetCurrentProcessId();
  65. jobData->medProcessInfo.dwThreadId = GetCurrentThreadId();
  66. _tcsncpy( jobData->medFileVersion, versionInfo->GetFileVersion(), VERSION_STRING_LEN );
  67. _tcsncpy( jobData->medProductVersion, versionInfo->GetProductVersion(), VERSION_STRING_LEN );
  68. _tcsncpy( jobData->medFileFlags, versionInfo->GetFileFlags(), VERSION_STRING_LEN );
  69. // Duplicate ProcCon's completion port handle here to preserve it...
  70. HANDLE hServiceProc = OpenProcess( PROCESS_DUP_HANDLE, FALSE, (DWORD) jobData->svcPID ); // truncation of PID to 32-bit
  71. if ( !hServiceProc ) {
  72. PCLogUnExError( jobData->svcPID, TEXT("MediatorOpenSvcPID") );
  73. CloseHandle( hSvcJobMap );
  74. CloseHandle( hSvcEvent );
  75. return 1;
  76. }
  77. if ( !DuplicateHandle( hServiceProc,
  78. jobData->svcPortHandle,
  79. GetCurrentProcess(),
  80. &jobData->medPortHandle,
  81. NULL,
  82. FALSE,
  83. DUPLICATE_SAME_ACCESS ) )
  84. PCLogUnExError( TEXT("ComplPort"), TEXT("MediatorDupHandle") );
  85. CloseHandle( hServiceProc );
  86. // We're ready to run. On the first pass we'll open all jobs. Otherwise just the new jobs.
  87. ResetEvent( hSvcEvent ); // don't need to be signalled for first pass
  88. for ( BOOL firstPass = TRUE; ; firstPass = FALSE ) {
  89. // duplicate all chained block handles as needed...
  90. jobData->MedChainBlocks( firstPass );
  91. // duplicate all job object handles in chain as needed...
  92. for ( PCMediateBlock *blk = &jobData->groupBlock; blk; blk = jobData->NextBlock( blk ) ) {
  93. for ( PCULONG32 grp = 0; grp < blk->groupCount; ++grp ) {
  94. if ( firstPass && !(blk->group[grp].groupFlags & PCMEDIATE_CLOSE_ME) ) {
  95. blk->group[grp].mediatorHandle =
  96. OpenJobObject( JOB_OBJECT_QUERY, FALSE, blk->group[grp].groupName );
  97. if ( !blk->group[grp].mediatorHandle )
  98. PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorOpenJob1") );
  99. }
  100. else if ( blk->group[grp].groupFlags & PCMEDIATE_CLOSE_ME ) {
  101. if ( blk->group[grp].mediatorHandle && !CloseHandle( blk->group[grp].mediatorHandle ) )
  102. PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorCloseJob") );
  103. blk->group[grp].mediatorHandle = NULL;
  104. }
  105. else if ( !blk->group[grp].mediatorHandle ) {
  106. blk->group[grp].mediatorHandle =
  107. OpenJobObject( JOB_OBJECT_QUERY, FALSE, blk->group[grp].groupName );
  108. if ( !blk->group[grp].mediatorHandle )
  109. PCLogUnExError( blk->group[grp].groupName, TEXT("MediatorOpenJob2") );
  110. }
  111. }
  112. }
  113. // Wait for signal that a new job exists.
  114. // If the wait fails, just exit, else we reprocess job list...
  115. if ( WAIT_OBJECT_0 != WaitForSingleObject( hSvcEvent, INFINITE ) )
  116. break;
  117. }
  118. CloseHandle( hSvcJobMap );
  119. CloseHandle( hSvcEvent );
  120. return 0;
  121. }