windows-nt/Source/XPSP1/NT/inetsrv/query/fdriver/proc32.cxx
2020-09-26 16:20:57 +08:00

325 lines
10 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000.
//
// File: process.cxx
//
// Contents: CProcess class
// CServiceProcess class
//
// History: 07-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <proc32.hxx>
#include <cievtmsg.h>
#include <fwevent.hxx>
//+-------------------------------------------------------------------------
//
// Member: CProcess::CProcess
//
// Purpose: Creates a process on the local machine.
//
// Arguments: [wcsImageName] -- name of EXE to run
// [wcsCommandLine] -- command line passed to EXE
// [fCreateSuspended] -- should the EXE be created suspended?
// [SAProcess] -- Security context to run under
// [fServiceChild] -- Flag set to TRUE if the process is a
// child of a "service" process (ala CiFilter
// service or W3Svc).
// [pAdviseStatus] -- ICiCAdviseStatus interface, optional.
//
// History: 06-Jun-94 DwightKr Created
//
// Notes: If a system process (such as a service) spawning a process
// it will always be created on the SYSTEM desktop, and never
// the user's or DEFAULT desktop. System processes do not have
// sufficient acccess to create windows on the user's desktop.
//
//--------------------------------------------------------------------------
CProcess::CProcess( const WCHAR *wcsImageName,
const WCHAR *wcsCommandLine,
BOOL fCreateSuspended,
const SECURITY_ATTRIBUTES & SAProcess,
BOOL fOFSDaemon,
ICiCAdviseStatus * pAdviseStatus )
{
_pAdviseStatus = pAdviseStatus;
WCHAR wcsEXEName[_MAX_PATH + 1];
if ( ExpandEnvironmentStrings( wcsImageName, wcsEXEName, _MAX_PATH ) == 0 )
{
THROW( CException() );
}
STARTUPINFO siDefault;
RtlZeroMemory( &siDefault, sizeof(siDefault) );
DWORD dwCreateFlags = 0;
siDefault.cb = sizeof(STARTUPINFO); // Size of this struct
if ( fOFSDaemon )
{
siDefault.lpReserved = NULL; // Not used (for now)
siDefault.lpDesktop = L"Default"; // Use default desktop
siDefault.lpTitle = (WCHAR *) wcsImageName; // Default title
siDefault.dwX = 0; // Don't specify where to
siDefault.dwY = 0; // place the window
siDefault.dwXSize = 0; // " " " " "
siDefault.dwYSize = 0; // " " " " "
siDefault.dwFlags = STARTF_USESHOWWINDOW; // Allow for minimizing
siDefault.wShowWindow = SW_MINIMIZE; // Normal display
siDefault.cbReserved2 = 0; // Not used (for now)
siDefault.lpReserved2 = NULL; // " " " " "
dwCreateFlags = CREATE_NEW_CONSOLE;
}
else
{
siDefault.lpTitle = (WCHAR *) wcsImageName; // Default title
dwCreateFlags = DETACHED_PROCESS;
}
if ( fCreateSuspended )
dwCreateFlags |= CREATE_SUSPENDED;
if ( !CreateProcess( fOFSDaemon ? (WCHAR *) wcsEXEName : 0, // EXE name
(WCHAR *) wcsCommandLine, // Command line
(SECURITY_ATTRIBUTES *) &SAProcess, // Proc sec attrib
NULL, // Thread sec attrib
fOFSDaemon, // Inherit handles
dwCreateFlags, // Creation flags
NULL, // Environment
NULL, // Startup directory
&siDefault, // Startup Info
&_piProcessInfo ) ) // Process handles
{
DWORD dwLastError = GetLastError();
if ( ERROR_FILE_NOT_FOUND == dwLastError && _pAdviseStatus )
{
CFwEventItem item( EVENTLOG_AUDIT_FAILURE,
MSG_CI_FILE_NOT_FOUND,
1 );
item.AddArg( wcsEXEName );
item.ReportEvent(*_pAdviseStatus);
}
THROW( CException( HRESULT_FROM_WIN32( dwLastError) ) );
}
//
// Only AddRef() once we get to a point where the constructor can
// no longer fail (and the destructor is guaranteed to be called)
//
if (_pAdviseStatus)
_pAdviseStatus->AddRef();
} //CProcess
//+-------------------------------------------------------------------------
//
// Member: CProcess::~CProcess
//
// Purpose: destructor
//
// History: 06-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
CProcess::~CProcess()
{
if ( 0 != _pAdviseStatus )
_pAdviseStatus->Release();
Terminate();
WaitForDeath();
}
//+-------------------------------------------------------------------------
//
// Member: CProcess::Resume, public
//
// Purpose: Continue a suspended thread
//
// History: 06-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
void CProcess::Resume()
{
ResumeThread( _piProcessInfo.hThread );
}
//+-------------------------------------------------------------------------
//
// Member: CProcess::WaitForDeath
//
// Purpose: Blocks until the process has been terminated.
//
// History: 06-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
void CProcess::WaitForDeath( DWORD dwTimeout )
{
DWORD res = WaitForSingleObject ( _piProcessInfo.hProcess, dwTimeout );
#if 0
if ( WAIT_FAILED == res )
{
Win4Assert( !"Are we leaking a handle" );
}
#endif // 0
CloseHandle(_piProcessInfo.hThread);
CloseHandle(_piProcessInfo.hProcess);
// if ( WAIT_FAILED == res )
// {
// THROW( CException() );
// }
}
//+-------------------------------------------------------------------------
//
// Member: CProcess::GetProcessToken, private
//
// Purpose: Returns the process token for the process
//
// History: 06-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
HANDLE CProcess::GetProcessToken()
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION,
FALSE,
_piProcessInfo.dwProcessId );
if ( NULL == hProcess )
{
THROW( CException() );
}
SWin32Handle process(hProcess); // Save in smart pointer
HANDLE hProcessToken = 0;
if ( !OpenProcessToken( hProcess, TOKEN_ADJUST_DEFAULT | TOKEN_QUERY, &hProcessToken ) )
{
THROW( CException() );
}
return hProcessToken;
}
//+-------------------------------------------------------------------------
//
// Member: CProcess::AddDacl, public
//
// Purpose: Adds the access specified onto the Dacl on the process.
//
// Arguments: [dwAccessMask] -- Any combination of the Win32 ACCESS_MASK bits
//
// History: 06-Jun-94 DwightKr Created
//
//--------------------------------------------------------------------------
void CProcess::AddDacl( DWORD dwAccessMask )
{
HANDLE hProcessToken = GetProcessToken();
SWin32Handle processToken( hProcessToken );
//
// Create a SID that gives everyone access. We want to allow anyone
// to synchronize on the objects created in this process (if they
// can get a handle to the object to synchronize on).
//
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_WORLD_SID_AUTHORITY;
CSid WorldSid( NtAuthority, SECURITY_WORLD_RID );
//
// Read the current Dacl. This requires two steps. The current
// Dacl size is not known, the 1st call determines its current size.
//
DWORD cbRequired;
if ( !GetTokenInformation( hProcessToken,
TokenDefaultDacl,
0,
0,
&cbRequired ) )
{
if ( ERROR_INSUFFICIENT_BUFFER != GetLastError() )
THROW( CException() );
}
else
{
ciDebugOut(( DEB_WARN,
"No default dacl(1), invalid CI configuration\n" ));
THROW( CException( STATUS_INVALID_PARAMETER ) );
}
//
// Create a buffer of the size requested to store the Dacl on the next
// call to GetTokenInformation(). Add additional space for the new
// synchronize-all Ace to be appended later.
//
cbRequired += sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( WorldSid );
TOKEN_DEFAULT_DACL *pDacl = (TOKEN_DEFAULT_DACL *) new BYTE[cbRequired];
SDacl SDacl(pDacl); // Save in smart pointer
if ( !GetTokenInformation( hProcessToken,
TokenDefaultDacl,
pDacl,
cbRequired,
&cbRequired ) )
{
THROW( CException() );
}
//
// pDacl->DefaultDacl will be 0 if cisvc is started in windbg
// with pipes preconfigured. Don't do that -- we don't support it.
//
if ( 0 == pDacl->DefaultDacl )
{
ciDebugOut(( DEB_WARN,
"No default dacl(2), invalid CI configuration\n" ));
THROW( CException( STATUS_INVALID_PARAMETER ) );
}
pDacl->DefaultDacl->AclSize += (USHORT)(sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( WorldSid ) - sizeof(ULONG));
//
// Append synchronize access onto the Dacl.
//
if ( !AddAccessAllowedAce( pDacl->DefaultDacl, // On to this acl,
ACL_REVISION, // built for version X,
dwAccessMask, // allow synchronize,
WorldSid ) ) // for these objects.
{
THROW( CException() );
}
#if CIDBG == 1
if ( !IsValidAcl( pDacl->DefaultDacl ) )
{
Win4Assert(!"Invalid Acl");
}
#endif
//
// Update the process's Dacl.
//
if ( !SetTokenInformation( hProcessToken,
TokenDefaultDacl,
&pDacl->DefaultDacl,
pDacl->DefaultDacl->AclSize ) )
{
THROW( CException() );
}
}