windows-nt/Source/XPSP1/NT/ds/security/ntmarta/newsrc/svcctx.cpp
2020-09-26 16:20:57 +08:00

531 lines
13 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows NT Security
// Copyright (C) Microsoft Corporation, 1997 - 1998
//
// File: svcctx.cpp
//
// Contents: Implementation of CServiceContext and NT Marta Service Functions
//
// History: 3-31-1999 kirtd Created
//
//----------------------------------------------------------------------------
#include <aclpch.hxx>
#pragma hdrstop
#include <svcctx.h>
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::CServiceContext, public
//
// Synopsis: Constructor
//
//----------------------------------------------------------------------------
CServiceContext::CServiceContext ()
{
m_cRefs = 1;
m_hService = NULL;
m_fNameInitialized = FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::~CServiceContext, public
//
// Synopsis: Destructor
//
//----------------------------------------------------------------------------
CServiceContext::~CServiceContext ()
{
if ( ( m_hService != NULL ) && ( m_fNameInitialized == TRUE ) )
{
CloseServiceHandle( m_hService );
}
assert( m_cRefs == 0 );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::InitializeByName, public
//
// Synopsis: initialize the context given the name of the service
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::InitializeByName (LPCWSTR pObjectName, ACCESS_MASK AccessMask)
{
DWORD Result;
LPWSTR pwszMachine = NULL;
LPWSTR pwszService = NULL;
SC_HANDLE hSCM = NULL;
SC_HANDLE hService = NULL;
Result = ServiceContextParseServiceName(
pObjectName,
&pwszMachine,
&pwszService
);
if ( Result == ERROR_SUCCESS )
{
hSCM = OpenSCManagerW( pwszMachine, NULL, AccessMask );
if ( hSCM == NULL )
{
delete pwszMachine;
delete pwszService;
return( GetLastError() );
}
if ( AccessMask & GENERIC_WRITE )
{
AccessMask |= ( WRITE_DAC | WRITE_OWNER );
}
m_hService = OpenServiceW( hSCM, pwszService, AccessMask );
if ( m_hService != NULL )
{
m_fNameInitialized = TRUE;
}
else
{
Result = GetLastError();
}
CloseServiceHandle( hSCM );
delete pwszMachine;
delete pwszService;
}
return( Result );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::InitializeByHandle, public
//
// Synopsis: initialize the context given a service handle
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::InitializeByHandle (HANDLE Handle)
{
m_hService = (SC_HANDLE)Handle;
assert( m_fNameInitialized == FALSE );
return( ERROR_SUCCESS );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::AddRef, public
//
// Synopsis: add a reference to the context
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::AddRef ()
{
m_cRefs += 1;
return( m_cRefs );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::Release, public
//
// Synopsis: release a reference to the context
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::Release ()
{
m_cRefs -= 1;
if ( m_cRefs == 0 )
{
delete this;
return( 0 );
}
return( m_cRefs );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::GetServiceProperties, public
//
// Synopsis: get properties about the context
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::GetServiceProperties (
PMARTA_OBJECT_PROPERTIES pObjectProperties
)
{
if ( pObjectProperties->cbSize < sizeof( MARTA_OBJECT_PROPERTIES ) )
{
return( ERROR_INVALID_PARAMETER );
}
assert( pObjectProperties->dwFlags == 0 );
return( ERROR_SUCCESS );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::GetServiceRights, public
//
// Synopsis: get the service security descriptor
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::GetServiceRights (
SECURITY_INFORMATION SecurityInfo,
PSECURITY_DESCRIPTOR* ppSecurityDescriptor
)
{
BOOL fResult;
UCHAR SDBuff[1];
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
DWORD cb = 0;
assert( m_hService != NULL );
fResult = QueryServiceObjectSecurity(
m_hService,
SecurityInfo,
(PSECURITY_DESCRIPTOR) SDBuff,
0,
&cb
);
if ( ( fResult == FALSE ) && ( cb > 0 ) )
{
assert( ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) ||
( GetLastError() == STATUS_BUFFER_TOO_SMALL ) );
pSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, cb );
if ( pSecurityDescriptor == NULL )
{
return( ERROR_OUTOFMEMORY );
}
fResult = QueryServiceObjectSecurity(
m_hService,
SecurityInfo,
pSecurityDescriptor,
cb,
&cb
);
}
else
{
assert( fResult == FALSE );
return( GetLastError() );
}
if ( fResult == TRUE )
{
*ppSecurityDescriptor = pSecurityDescriptor;
}
else
{
return( GetLastError() );
}
return( ERROR_SUCCESS );
}
//+---------------------------------------------------------------------------
//
// Member: CServiceContext::SetServiceRights, public
//
// Synopsis: set the window security descriptor
//
//----------------------------------------------------------------------------
DWORD
CServiceContext::SetServiceRights (
SECURITY_INFORMATION SecurityInfo,
PSECURITY_DESCRIPTOR pSecurityDescriptor
)
{
assert( m_hService != NULL );
if ( SetServiceObjectSecurity(
m_hService,
SecurityInfo,
pSecurityDescriptor
) == FALSE )
{
return( GetLastError() );
}
return( ERROR_SUCCESS );
}
//+---------------------------------------------------------------------------
//
// Function: ServiceContextParseServiceName
//
// Synopsis: parse the service name and machine
//
//----------------------------------------------------------------------------
DWORD
ServiceContextParseServiceName (
LPCWSTR pwszName,
LPWSTR* ppMachine,
LPWSTR* ppService
)
{
return( StandardContextParseName( pwszName, ppMachine, ppService ) );
}
//+---------------------------------------------------------------------------
//
// Function: StandardContextParseName
//
// Synopsis: parse the name and machine
//
//----------------------------------------------------------------------------
DWORD
StandardContextParseName (
LPCWSTR pwszName,
LPWSTR* ppMachine,
LPWSTR* ppRest
)
{
LPWSTR pwszMachine = NULL;
LPWSTR pwszNameLocal = NULL;
LPWSTR pwszRest = NULL;
DWORD cwName = 0;
DWORD cw = 0;
DWORD rc = ERROR_SUCCESS;
//
// VishnuP: 392334 AV because IN parameter pwszName could be constant and is written
// to inside here. Irrespective of whether it is a constant, this IN parameter is coming
// from GetNamedSecurityInfo and should not be mangled.
// So, create a local copy of the IN parameter and mangle it if needeed.
//
cwName = wcslen( pwszName );
pwszNameLocal = new WCHAR [ cwName + 1 ];
if ( pwszNameLocal == NULL )
{
rc = ERROR_OUTOFMEMORY ;
goto CleanUp;
}
wcscpy( pwszNameLocal, pwszName);
if ( cwName > 2 )
{
if ( ( pwszNameLocal[0] == L'\\' ) && ( pwszNameLocal[1] == L'\\' ) )
{
LPWSTR pwsz, tmp;
pwsz = (LPWSTR)&pwszNameLocal[2];
while ( ( *pwsz != L'\0' ) && ( *pwsz != L'\\' ) )
{
pwsz++;
cw++;
}
if ( *pwsz == L'\0' )
{
rc = ERROR_INVALID_PARAMETER ;
goto CleanUp;
}
*pwsz = L'\0';
tmp = pwsz;
pwsz++;
pwszMachine = new WCHAR [ cw + 1 ];
if ( pwszMachine == NULL )
{
rc = ERROR_OUTOFMEMORY ;
goto CleanUp;
}
cw = wcslen( pwsz );
if ( cw == 0 )
{
delete pwszMachine;
rc = ERROR_INVALID_PARAMETER ;
goto CleanUp;
}
pwszRest = new WCHAR [ cw + 1 ];
if ( pwszRest == NULL )
{
delete pwszMachine;
rc = ERROR_OUTOFMEMORY ;
goto CleanUp;
}
wcscpy( pwszMachine, &pwszNameLocal[2] );
wcscpy( pwszRest, pwsz );
*tmp = L'\\';
}
}
else if ( ( pwszNameLocal[0] == L'\\' ) || ( pwszNameLocal[1] == L'\\' ) )
{
rc = ERROR_INVALID_PARAMETER ;
goto CleanUp;
}
if ( pwszRest == NULL )
{
assert( pwszMachine == NULL );
pwszRest = new WCHAR [ cwName + 1 ];
if ( pwszRest == NULL )
{
rc = ERROR_OUTOFMEMORY ;
goto CleanUp;
}
wcscpy( pwszRest, pwszNameLocal );
}
*ppMachine = pwszMachine;
*ppRest = pwszRest;
CleanUp:
if (pwszNameLocal)
delete pwszNameLocal;
return( rc );
}
//
// Functions from service.h which dispatch unto the CServiceContext class
//
DWORD
MartaAddRefServiceContext(
IN MARTA_CONTEXT Context
)
{
return( ( (CServiceContext *)Context )->AddRef() );
}
DWORD
MartaCloseServiceContext(
IN MARTA_CONTEXT Context
)
{
return( ( (CServiceContext *)Context )->Release() );
}
DWORD
MartaGetServiceProperties(
IN MARTA_CONTEXT Context,
IN OUT PMARTA_OBJECT_PROPERTIES pProperties
)
{
return( ( (CServiceContext *)Context )->GetServiceProperties( pProperties ) );
}
DWORD
MartaGetServiceTypeProperties(
IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
)
{
if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
{
return( ERROR_INVALID_PARAMETER );
}
assert( pProperties->dwFlags == 0 );
return( ERROR_SUCCESS );
}
DWORD
MartaGetServiceRights(
IN MARTA_CONTEXT Context,
IN SECURITY_INFORMATION SecurityInfo,
OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
)
{
return( ( (CServiceContext *)Context )->GetServiceRights(
SecurityInfo,
ppSecurityDescriptor
) );
}
DWORD
MartaOpenServiceNamedObject(
IN LPCWSTR pObjectName,
IN ACCESS_MASK AccessMask,
OUT PMARTA_CONTEXT pContext
)
{
DWORD Result;
CServiceContext* pServiceContext;
pServiceContext = new CServiceContext;
if ( pServiceContext == NULL )
{
return( ERROR_OUTOFMEMORY );
}
Result = pServiceContext->InitializeByName( pObjectName, AccessMask );
if ( Result != ERROR_SUCCESS )
{
pServiceContext->Release();
return( Result );
}
*pContext = pServiceContext;
return( ERROR_SUCCESS );
}
DWORD
MartaOpenServiceHandleObject(
IN HANDLE Handle,
IN ACCESS_MASK AccessMask,
OUT PMARTA_CONTEXT pContext
)
{
DWORD Result;
CServiceContext* pServiceContext;
pServiceContext = new CServiceContext;
if ( pServiceContext == NULL )
{
return( ERROR_OUTOFMEMORY );
}
Result = pServiceContext->InitializeByHandle( Handle );
if ( Result != ERROR_SUCCESS )
{
pServiceContext->Release();
return( Result );
}
*pContext = pServiceContext;
return( ERROR_SUCCESS );
}
DWORD
MartaSetServiceRights(
IN MARTA_CONTEXT Context,
IN SECURITY_INFORMATION SecurityInfo,
IN PSECURITY_DESCRIPTOR pSecurityDescriptor
)
{
return( ( (CServiceContext *)Context )->SetServiceRights(
SecurityInfo,
pSecurityDescriptor
) );
}