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
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 );
|
|
}
|
|
}
|