//+--------------------------------------------------------------------------- // // 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 #pragma hdrstop #include //+--------------------------------------------------------------------------- // // 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 ) ); }