Leaked source code of windows server 2003
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.
 
 
 
 
 
 

913 lines
23 KiB

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#include <string.h>
#include <tchar.h>
#include <assert.h>
#include <time.h>
#include <msi.h>
#include <msiquery.h>
#include "dbcaum.h"
#include "..\..\shared\apppool.h"
#include "..\..\shared\common.h"
#define DIM(x) (sizeof x)/(sizeof x[0])
#define ROOT_REGPATH "Software\\Microsoft\\UDDI"
#define INSTROOT_REGPATH "InstallRoot"
#define RESROOT_REGPATH "ResourceRoot"
#define BOOTSTRAP_DIR "bootstrap"
//
// Forward declarations.
//
static int AddSharedDllRef( LPCSTR szFullPath );
static int ReleaseSharedDll ( LPCSTR szFullPath );
static bool AddAccessRights( TCHAR *lpszFileName, TCHAR *szUserName, DWORD dwAccessMask );
static LONG GetServiceStartupAccount( const TCHAR *pwszServiceName, TCHAR *pwszServiceAccount, int iLen );
static void GetUDDIDBServiceName( const TCHAR *pwszInstanceName, TCHAR *pwszServiceName, int iLen );
static void AddAccessRightsVerbose( TCHAR *pwszFileName, TCHAR *pwszUserName, DWORD dwMask );
//--------------------------------------------------------------------------
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
//--------------------------------------------------------------------------
//
// Install custom action used by the DB component installer to recycle the app pool
// This function is exported
//
UINT _stdcall Install( MSIHANDLE hInstall )
{
ENTER();
//
// stop and start the app pool
//
CUDDIAppPool apppool;
apppool.Recycle();
return ERROR_SUCCESS;
}
UINT __stdcall InstallTaxonomy( LPCSTR szSrcResource, LPCSTR szDestResource )
{
//
// Now we parse the path out of the Source and copy the Destination right by it
//
CHAR szPath[ _MAX_PATH + 1 ] = {0};
PCHAR pSlash = strrchr( szSrcResource, '\\' );
if ( pSlash )
{
strncpy( szPath, szSrcResource, pSlash - szSrcResource + 1 );
int iLen = _MAX_PATH - strlen( szPath );
strncat( szPath, szDestResource, iLen );
}
else
{
strncpy( szPath, szDestResource, _MAX_PATH + 1 );
}
szPath[ _MAX_PATH ] = 0;
#if defined( DBG ) || defined( _DEBUG )
TCHAR wszPath[ _MAX_PATH + 1 ];
int iwszCount = _MAX_PATH;
int ipszCount = strlen( szPath );
memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
Log( _T( "Installing taxonomy file: %s." ), wszPath );
#endif
if ( !CopyFileA( szSrcResource, szPath, FALSE ) )
return ERROR_INSTALL_FAILURE;
DeleteFileA( szSrcResource );
return ERROR_SUCCESS;
}
UINT __stdcall InstallResource( LPCSTR szCultureID, LPCSTR szDefCulture,
LPCSTR szSrcResource, LPCSTR szDestResource )
{
//
// Get the properties and then do the file manipulation
//
if ( _stricmp( szCultureID, szDefCulture ) )
{
//
// Now we parse the path out of the Source and copy the Destination right by it
//
CHAR szPath[ _MAX_PATH + 1 ] = {0};
PCHAR pSlash = strrchr( szSrcResource, '\\' );
if ( pSlash )
{
strncpy( szPath, szSrcResource, pSlash - szSrcResource + 1 );
int iLen = _MAX_PATH - strlen( szPath );
strncat( szPath, szDestResource, iLen );
}
else
{
strncpy( szPath, szDestResource, _MAX_PATH + 1 );
}
szPath[ _MAX_PATH ] = 0;
#if defined( DBG ) || defined( _DEBUG )
TCHAR wszPath[ _MAX_PATH + 1 ];
int iwszCount = _MAX_PATH;
int ipszCount = strlen( szPath );
memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
Log( _T( "Installing resource file: %s." ), wszPath );
#endif
if ( !CopyFileA( szSrcResource, szPath, FALSE ) )
return ERROR_INSTALL_FAILURE;
AddSharedDllRef( szPath );
}
DeleteFileA( szSrcResource );
return ERROR_SUCCESS;
}
UINT __stdcall RemoveResource( LPCSTR szDestResource )
{
HKEY hUddiKey = NULL;
try
{
CHAR szPath[ _MAX_PATH + 1 ] = {0};
DWORD cbPath = DIM( szPath );
size_t iLen = 0;
LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, ROOT_REGPATH, &hUddiKey );
if ( iRes != ERROR_SUCCESS )
return ERROR_INSTALL_FAILURE;
iRes = RegQueryValueExA( hUddiKey, RESROOT_REGPATH, NULL, NULL, (LPBYTE)szPath, &cbPath );
if ( iRes != ERROR_SUCCESS )
return ERROR_INSTALL_FAILURE;
RegCloseKey( hUddiKey );
hUddiKey = NULL;
iLen = strlen( szPath );
if ( ( iLen < _MAX_PATH ) && ( szPath[ iLen - 1 ] != '\\' ) )
{
strncat( szPath, "\\", 2 );
}
iLen = _MAX_PATH - strlen( szPath );
strncat( szPath, szDestResource, iLen );
szPath[ _MAX_PATH ] = 0;
#if defined( DBG ) || defined( _DEBUG )
TCHAR wszPath[ _MAX_PATH + 1 ];
int iwszCount = _MAX_PATH;
int ipszCount = strlen( szPath );
memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
Log( _T( "Removing resource file: %s." ), wszPath );
#endif
if ( ReleaseSharedDll( szPath ) == 0 )
DeleteFileA( szPath );
}
catch (...)
{
if ( hUddiKey )
RegCloseKey( hUddiKey );
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
UINT __stdcall RemoveTaxonomy( LPCSTR szDestResource )
{
HKEY hUddiKey = NULL;
try
{
CHAR szPath[ _MAX_PATH + 1 ] = {0};
DWORD cbPath = DIM( szPath );
size_t iLen = 0;
LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, ROOT_REGPATH, &hUddiKey );
if ( iRes != ERROR_SUCCESS )
return ERROR_INSTALL_FAILURE;
iRes = RegQueryValueExA( hUddiKey, INSTROOT_REGPATH, NULL, NULL, (LPBYTE)szPath, &cbPath );
if ( iRes != ERROR_SUCCESS )
return ERROR_INSTALL_FAILURE;
RegCloseKey( hUddiKey );
hUddiKey = NULL;
iLen = strlen( szPath );
if ( ( iLen < _MAX_PATH ) && ( szPath[ iLen - 1 ] != '\\' ) )
{
strncat( szPath, "\\", 2 );
}
//
// Append \bootstrap\<resource filename> to InstallRoot
//
iLen = _MAX_PATH - strlen( szPath );
strncat( szPath, BOOTSTRAP_DIR, iLen );
strncat( szPath, "\\", 2 );
iLen = _MAX_PATH - strlen( szPath );
strncat( szPath, szDestResource, iLen );
szPath[ _MAX_PATH ] = 0;
#if defined( DBG ) || defined( _DEBUG )
TCHAR wszPath[ _MAX_PATH + 1 ];
int iwszCount = _MAX_PATH;
int ipszCount = strlen( szPath );
memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
Log( _T( "Removing taxonomy file: %s." ), wszPath );
#endif
DeleteFileA( szPath );
}
catch (...)
{
if ( hUddiKey )
RegCloseKey( hUddiKey );
return ERROR_INSTALL_FAILURE;
}
return ERROR_SUCCESS;
}
UINT __stdcall GrantExecutionRights( LPCSTR pszInstanceNameOnly )
{
ENTER();
TCHAR wszInstanceName[ 256 ];
int iwszCount = 256;
int ipszCount = strlen( pszInstanceNameOnly );
memset( wszInstanceName, 0, 256 * sizeof( TCHAR ) );
::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, pszInstanceNameOnly, ipszCount, wszInstanceName, iwszCount );
Log( _T( "Instance Name only = %s" ), wszInstanceName );
TCHAR wszServiceName[ 128 ];
GetUDDIDBServiceName( wszInstanceName, wszServiceName, 128 );
TCHAR wszServiceAccount[ 128 ];
GetServiceStartupAccount( wszServiceName, wszServiceAccount, 128 );
//
// Get the UDDI installation point. ie, C:\Inetpub\uddi\
//
HKEY hKey = NULL;
LONG lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Microsoft\\UDDI\\Setup\\DBServer" ), 0, KEY_QUERY_VALUE, &hKey );
if( ERROR_SUCCESS != lRet )
{
Log( _T( "Call to RegOpenKeyEx failed." ) );
return ERROR_SUCCESS;
}
DWORD dwType = 0;
TCHAR wszUDDIRoot[ _MAX_PATH ];
DWORD dwSize = _MAX_PATH * sizeof( TCHAR );
memset( wszUDDIRoot, 0, dwSize );
lRet = RegQueryValueEx( hKey, _T( "TargetDir" ), NULL, &dwType, (LPBYTE)wszUDDIRoot, &dwSize );
RegCloseKey( hKey );
if( ERROR_SUCCESS != lRet )
{
Log( _T( "Call to RegQueryValueEx failed." ) );
return ERROR_SUCCESS;
}
//
// Build the full path to the 3 files whose ACLs are being modified.
//
dwSize = _MAX_PATH + _MAX_FNAME;
TCHAR wszResetKeyExe[ _MAX_PATH + _MAX_FNAME ];
TCHAR wszRecalcStatsExe[ _MAX_PATH + _MAX_FNAME ];
TCHAR wszXPDLL[ _MAX_PATH + _MAX_FNAME ];
memset( wszResetKeyExe, 0, dwSize * sizeof( TCHAR ) );
memset( wszRecalcStatsExe, 0, dwSize * sizeof( TCHAR ) ) ;
memset( wszXPDLL, 0, dwSize * sizeof( TCHAR ) ) ;
_tcscat( wszResetKeyExe, wszUDDIRoot );
_tcscat( wszResetKeyExe, _T( "bin\\resetkey.exe" ) );
_tcscat( wszRecalcStatsExe, wszUDDIRoot );
_tcscat( wszRecalcStatsExe, _T( "bin\\recalcstats.exe" ) );
_tcscat( wszXPDLL, wszUDDIRoot );
_tcscat( wszXPDLL, _T( "bin\\uddi.xp.dll" ) );
//
// If the service startup account is a local account, it will be prefixed
// with ".\" For example: ".\Administrator".
//
// For some reason, LookupAccountName (which we rely on just below) wants
// local accounts not to be prefixed with ".\".
//
TCHAR wszAccount[ 256 ];
memset( wszAccount, 0, 256 * sizeof( TCHAR ) );
if( 0 == _tcsnicmp( _T( ".\\" ), wszServiceAccount, 2 ) )
{
_tcsncpy( wszAccount, &wszServiceAccount[ 2 ], _tcslen( wszServiceAccount ) - 2 );
}
else
{
_tcsncpy( wszAccount, wszServiceAccount, _tcslen( wszServiceAccount ) );
}
Log( _T( "Account we will attempt to grant execute privilege = %s." ), wszAccount );
//
// We add an "execute" ACE to the ACL only if:
//
// 1. There is some content in the wszAccount variable.
// 2. The content is not "LocalSystem". We don't need to add an ACE if this is the case.
//
if( ( 0 != _tcslen( wszAccount ) ) && ( 0 != _tcsicmp( wszAccount, _T( "LocalSystem" ) ) ) )
{
DWORD dwAccessMask = GENERIC_EXECUTE;
AddAccessRightsVerbose( wszResetKeyExe, wszAccount, dwAccessMask );
AddAccessRightsVerbose( wszRecalcStatsExe, wszAccount, dwAccessMask );
AddAccessRightsVerbose( wszXPDLL, wszAccount, dwAccessMask );
}
return ERROR_SUCCESS;
}
//*************************************************************************************
// Helper functions. Manage the Shared Dll counters
//
int AddSharedDllRef( LPCSTR szFullPath )
{
LPCSTR szRegPath = "Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs";
HKEY hReg = NULL;
DWORD dwCount = 0;
if ( IsBadStringPtrA( szFullPath, MAX_PATH ) )
return E_INVALIDARG;
try
{
DWORD cbData = sizeof dwCount;
LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, szRegPath, &hReg );
if ( iRes != ERROR_SUCCESS )
return iRes;
iRes = RegQueryValueExA( hReg, szFullPath, NULL, NULL, (LPBYTE)&dwCount, &cbData );
if ( iRes != ERROR_SUCCESS && iRes != ERROR_FILE_NOT_FOUND && iRes != ERROR_PATH_NOT_FOUND )
{
RegCloseKey( hReg );
return iRes;
}
dwCount++;
cbData = sizeof dwCount;
iRes = RegSetValueExA( hReg, szFullPath, 0, REG_DWORD, (LPBYTE)&dwCount, cbData );
RegCloseKey( hReg );
}
catch (...)
{
if ( hReg )
RegCloseKey( hReg );
return E_FAIL;
}
return dwCount;
}
int ReleaseSharedDll ( LPCSTR szFullPath )
{
LPCSTR szRegPath = "Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs";
HKEY hReg = NULL;
DWORD dwCount = 0;
if ( IsBadStringPtrA( szFullPath, MAX_PATH ) )
return E_INVALIDARG;
try
{
DWORD cbData = sizeof dwCount;
LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, szRegPath, &hReg );
if ( iRes != ERROR_SUCCESS )
return iRes;
iRes = RegQueryValueExA( hReg, szFullPath, NULL, NULL, (LPBYTE)&dwCount, &cbData );
if ( iRes != ERROR_SUCCESS )
{
RegCloseKey( hReg );
return iRes;
}
if ( dwCount > 1 )
{
dwCount--;
cbData = sizeof dwCount;
iRes = RegSetValueExA( hReg, szFullPath, 0, REG_DWORD, (LPBYTE)&dwCount, cbData );
}
else
{
dwCount = 0;
iRes = RegDeleteValueA( hReg, szFullPath );
}
RegCloseKey( hReg );
}
catch (...)
{
if ( hReg )
RegCloseKey( hReg );
return E_FAIL;
}
return dwCount;
}
bool AddAccessRights( TCHAR *lpszFileName, TCHAR *szUserName, DWORD dwAccessMask )
{
//
// SID variables.
//
SID_NAME_USE snuType;
TCHAR * szDomain = NULL;
DWORD cbDomain = 0;
//
// User name variables.
//
LPVOID pUserSID = NULL;
DWORD cbUserSID = 0;
DWORD cbUserName = 0;
//
// File SD variables.
//
PSECURITY_DESCRIPTOR pFileSD = NULL;
DWORD cbFileSD = 0;
//
// New SD variables.
//
PSECURITY_DESCRIPTOR pNewSD = NULL;
//
// ACL variables.
//
PACL pACL = NULL;
BOOL fDaclPresent;
BOOL fDaclDefaulted;
ACL_SIZE_INFORMATION AclInfo;
//
// New ACL variables.
//
PACL pNewACL = NULL;
DWORD cbNewACL = 0;
//
// Temporary ACE.
//
LPVOID pTempAce = NULL;
UINT CurrentAceIndex;
bool fResult = false;
BOOL fAPISuccess;
// error code
DWORD lastErr = 0;
try
{
//
// Call this API once to get the buffer sizes ( it will return ERROR_INSUFFICIENT_BUFFER )
//
fAPISuccess = LookupAccountName( NULL, szUserName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType );
if( fAPISuccess )
{
throw E_FAIL; // we throw some fake error to skip through to the exit door
}
else if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
{
lastErr = GetLastError();
LogError( TEXT( "LookupAccountName() failed" ), lastErr );
throw lastErr;
}
//
// allocate the buffers
//
pUserSID = calloc( cbUserSID, 1 );
if( !pUserSID )
{
lastErr = GetLastError();
LogError( TEXT( "Alloc() for UserSID failed" ), lastErr );
throw lastErr;
}
szDomain = ( TCHAR * ) calloc( cbDomain + sizeof TCHAR, sizeof TCHAR );
if( !szDomain )
{
lastErr = GetLastError();
LogError( TEXT( "Alloc() for szDomain failed" ), lastErr );
throw lastErr;
}
//
// The LookupAccountName function accepts the name of a system and an account as input.
// It retrieves a security identifier ( SID ) for the account and
// the name of the domain on which the account was found
//
fAPISuccess = LookupAccountName( NULL /* = local computer */, szUserName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType );
if( !fAPISuccess )
{
lastErr = GetLastError();
LogError( TEXT( "LookupAccountName() failed" ), lastErr );
throw lastErr;
}
//
// call this API once to get the buffer sizes
// API should have failed with insufficient buffer.
//
fAPISuccess = GetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pFileSD, 0, &cbFileSD );
if( fAPISuccess )
{
throw E_FAIL;
}
else if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
{
lastErr = GetLastError();
LogError( TEXT( "GetFileSecurity() failed" ), lastErr );
throw lastErr;
}
//
// allocate the buffers
//
pFileSD = calloc( cbFileSD, 1 );
if( !pFileSD )
{
lastErr = GetLastError();
LogError( TEXT( "Alloc() for pFileSD failed" ), lastErr );
throw lastErr;
}
//
// call the api to get the actual data
//
fAPISuccess = GetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pFileSD, cbFileSD, &cbFileSD );
if( !fAPISuccess )
{
lastErr = GetLastError();
LogError( TEXT( "GetFileSecurity() failed" ), lastErr );
throw lastErr;
}
//
// Initialize new SD.
//
pNewSD = calloc( cbFileSD, 1 ); // Should be same size as FileSD.
if( !pNewSD )
{
lastErr = GetLastError();
LogError( TEXT( "Alloc() for pNewDS failed" ), GetLastError() );
throw lastErr;
}
if( !InitializeSecurityDescriptor( pNewSD, SECURITY_DESCRIPTOR_REVISION ) )
{
lastErr = GetLastError();
LogError( TEXT( "InitializeSecurityDescriptor() failed" ), lastErr );
throw lastErr;
}
//
// Get DACL from SD.
//
if( !GetSecurityDescriptorDacl( pFileSD, &fDaclPresent, &pACL, &fDaclDefaulted ) )
{
lastErr = GetLastError();
LogError( TEXT( "GetSecurityDescriptorDacl() failed" ), lastErr );
throw lastErr;
}
//
// Get size information for DACL.
//
AclInfo.AceCount = 0; // Assume NULL DACL.
AclInfo.AclBytesFree = 0;
AclInfo.AclBytesInUse = sizeof( ACL ); // If not NULL DACL, gather size information from DACL.
if( fDaclPresent && pACL )
{
if( !GetAclInformation( pACL, &AclInfo, sizeof( ACL_SIZE_INFORMATION ), AclSizeInformation ) )
{
lastErr = GetLastError();
LogError( TEXT( "GetAclInformation() failed" ), lastErr );
throw lastErr;
}
}
//
// Compute size needed for the new ACL.
//
cbNewACL = AclInfo.AclBytesInUse + sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( pUserSID );
//
// Allocate memory for new ACL.
//
pNewACL = ( PACL ) calloc( cbNewACL, 1 );
if( !pNewACL )
{
lastErr = GetLastError();
LogError( TEXT( "HeapAlloc() failed" ), lastErr );
throw lastErr;
}
//
// Initialize the new ACL.
//
if( !InitializeAcl( pNewACL, cbNewACL, ACL_REVISION2 ) )
{
lastErr = GetLastError();
LogError( TEXT( "InitializeAcl() failed" ), lastErr );
throw lastErr;
}
//
// Add the access-allowed ACE to the new DACL.
//
ACE_HEADER aceheader = {0};
aceheader.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
aceheader.AceSize = sizeof( ACE_HEADER );
aceheader.AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
if( !AddAccessAllowedAceEx( pNewACL, ACL_REVISION2, aceheader.AceFlags, dwAccessMask, pUserSID ) )
{
lastErr = GetLastError();
LogError( TEXT( "AddAccessAllowedAce() failed" ), lastErr );
throw lastErr;
}
//
// If DACL is present, copy it to a new DACL.
//
if( fDaclPresent )
{
//
// Copy the file's ACEs to the new ACL
//
if( AclInfo.AceCount )
{
for( CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++ )
{
//
// Get an ACE.
//
if( !GetAce( pACL, CurrentAceIndex, &pTempAce ) )
{
lastErr = GetLastError();
LogError( TEXT( "GetAce() failed" ), lastErr );
throw lastErr;
}
//
// Add the ACE to the new ACL.
//
if( !AddAce( pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ( ( PACE_HEADER ) pTempAce )->AceSize ) )
{
lastErr = GetLastError();
LogError( TEXT( "AddAce() failed" ), lastErr );
throw lastErr;
}
}
}
}
//
// Set the new DACL to the file SD.
//
if( !SetSecurityDescriptorDacl( pNewSD, TRUE, pNewACL, FALSE ) )
{
lastErr = GetLastError();
LogError( TEXT( "SetSecurityDescriptorDacl() failed" ), lastErr );
lastErr;
}
//
// Set the SD to the File.
//
if( !SetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pNewSD ) )
{
lastErr = GetLastError();
LogError( TEXT( "SetFileSecurity() failed" ), lastErr );
throw lastErr;
}
fResult = TRUE;
}
catch (...)
{
fResult = FALSE;
}
//
// Free allocated memory
//
if( pUserSID )
free( pUserSID );
if( szDomain )
free( szDomain );
if( pFileSD )
free( pFileSD );
if( pNewSD )
free( pNewSD );
if( pNewACL )
free( pNewACL );
return fResult;
}
//
// This function takes in the name of a Service (ie, MSSQL$DAVESEBESTA), and
// fills a buffer with the name of the startup account for said Service.
//
// It does this by opening the Service Control Manager, getting a handle to
// said Service, and then querying the properties of the service.
//
// returns: ERROR_SUCCESS if everything goes well.
//
LONG
GetServiceStartupAccount( const TCHAR *pwszServiceName, TCHAR *pwszServiceAccount, int iLen )
{
memset( pwszServiceAccount, 0, iLen * sizeof( TCHAR ) );
//
// 1. Open the Service Control Manager.
//
SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
if( NULL == hSCM )
{
Log( _T( "Could not open the Service Control Manager." ) );
return ERROR_SUCCESS;
}
else
{
Log( _T( "Successfully opened a handle to the Service Control Manager." ) );
}
//
// 2. Get a handle to the Service.
//
DWORD dwAccess = SERVICE_QUERY_CONFIG;
SC_HANDLE hSvc = OpenService( hSCM, pwszServiceName, dwAccess );
if( NULL == hSvc )
{
Log( _T( "Could not open a handle to the service %s." ), pwszServiceName );
CloseServiceHandle( hSCM );
return ERROR_SUCCESS;
}
else
{
Log( _T( "Successfully opened a handle to the service %s." ), pwszServiceName );
}
//
// 3. Call QueryServiceConfig. This get us, among other things, the name of
// the account that is used to start the Service.
//
DWORD dwSizeNeeded = 0;
BOOL b = QueryServiceConfig( hSvc, NULL, 0, &dwSizeNeeded );
DWORD d = GetLastError();
if( !b && ( ERROR_INSUFFICIENT_BUFFER == d ) )
{
Log( _T( "About to allocate memory for service config info..." ) );
}
else
{
Log( _T( "Something went wrong during the call to QueryServiceConfig." ) );
CloseServiceHandle( hSvc );
CloseServiceHandle( hSCM );
return ERROR_SUCCESS;
}
LPQUERY_SERVICE_CONFIG pSvcQuery = (LPQUERY_SERVICE_CONFIG)malloc( dwSizeNeeded );
if( NULL == pSvcQuery )
{
Log( _T( "Ran out of memory." ) );
CloseServiceHandle( hSvc );
CloseServiceHandle( hSCM );
return ERROR_SUCCESS;
}
b = QueryServiceConfig( hSvc, pSvcQuery, dwSizeNeeded, &dwSizeNeeded );
if( !b )
{
Log( _T( "Call to QueryServiceConfig failed." ) );
free( (void *)pSvcQuery );
CloseServiceHandle( hSvc );
CloseServiceHandle( hSCM );
return ERROR_SUCCESS;
}
Log( _T( "Service startup account = %s" ), pSvcQuery->lpServiceStartName );
//
// 4. Copy the account into our output buffer, free up memory, and exit.
//
_tcsncpy( pwszServiceAccount, pSvcQuery->lpServiceStartName, iLen );
free( (void *)pSvcQuery );
CloseServiceHandle( hSvc );
CloseServiceHandle( hSCM );
return ERROR_SUCCESS;
}
//
// Use the instance name to determine the name of the SQL Service.
//
// From the database instance name, you can infer the name of the Service
// for that particular instance.
//
// Instance Name Service Name
// ===========================================
// (default) MSSQLSERVER
// NULL MSSQLSERVER
// <anything else> MSSQL$<anything else>
//
void
GetUDDIDBServiceName( const TCHAR *pwszInstanceName, TCHAR *pwszServiceName, int iLen )
{
memset( pwszServiceName, 0, iLen * sizeof( TCHAR ) );
_tcscpy( pwszServiceName, _T( "MSSQL" ) );
if( ( 0 == _tcslen( pwszInstanceName ) ) ||
( 0 == _tcsicmp( pwszInstanceName, _T( "----" ) ) ) ||
( 0 == _tcsicmp( pwszInstanceName, _T( "(default)" ) ) ) )
{
_tcsncat( pwszServiceName, _T( "SERVER" ), iLen );
}
else
{
_tcsncat( pwszServiceName, _T( "$" ), iLen );
_tcsncat( pwszServiceName, pwszInstanceName, iLen );
}
Log( _T( "Database service name = %s" ), pwszServiceName );
}
void
AddAccessRightsVerbose( TCHAR *pwszFileName, TCHAR *pwszUserName, DWORD dwMask )
{
BOOL b = AddAccessRights( pwszFileName, pwszUserName, dwMask );
if( !b )
{
Log( _T( "ACL for file %s was NOT modified." ), pwszFileName );
}
else
{
Log( _T( "User: %s now has execute permissions on file: %s." ), pwszUserName, pwszFileName );
}
}