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.
813 lines
22 KiB
813 lines
22 KiB
//============================================================
|
|
|
|
//
|
|
|
|
// UserHive.cpp - Class to load/unload specified user's profile
|
|
|
|
// hive from registry
|
|
|
|
//
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// 01/03/97 a-jmoon created
|
|
//
|
|
//============================================================
|
|
|
|
#include "precomp.h"
|
|
#include <assertbreak.h>
|
|
#include <cregcls.h>
|
|
#include "sid.h"
|
|
#include "UserHive.h"
|
|
#include <cominit.h>
|
|
#include <strsafe.h>
|
|
|
|
#pragma warning(disable : 4995) // we introduced as including strsafe.h gives error for all unsafe string functions
|
|
|
|
CThreadBase CUserHive::m_criticalSection;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::CUserHive
|
|
*
|
|
* DESCRIPTION : Constructor
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CUserHive::CUserHive()
|
|
{
|
|
OSInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
|
|
GetVersionEx(&OSInfo) ;
|
|
m_pOriginalPriv = NULL;
|
|
m_dwSize = NULL;
|
|
m_hKey = NULL;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::~CUserHive
|
|
*
|
|
* DESCRIPTION : Destructor
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
CUserHive::~CUserHive()
|
|
{
|
|
#ifdef NTONLY
|
|
if (m_pOriginalPriv)
|
|
RestorePrivilege();
|
|
#endif
|
|
|
|
// NOTE: The destructor does not unload the key. Nor does doing a load unload
|
|
// a previously loaded key;
|
|
ASSERT_BREAK(m_hKey == NULL);
|
|
|
|
if (m_hKey != NULL)
|
|
{
|
|
RegCloseKey(m_hKey);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::AcquirePrivilege
|
|
*
|
|
* DESCRIPTION : Acquires SeRestorePrivilege for calling thread
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef NTONLY
|
|
DWORD CUserHive::AcquirePrivilege()
|
|
{
|
|
// are you calling in twice? Shouldn't.
|
|
// at worst, it would cause a leak, so I'm going with it anyway.
|
|
ASSERT_BREAK(m_pOriginalPriv == NULL);
|
|
|
|
BOOL bRetCode = FALSE;
|
|
SmartCloseHandle hToken;
|
|
TOKEN_PRIVILEGES TPriv ;
|
|
LUID LUID ;
|
|
|
|
// Validate the platform
|
|
//======================
|
|
|
|
// Try getting the thread token.
|
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES |
|
|
TOKEN_QUERY, FALSE, &hToken))
|
|
{
|
|
|
|
GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &m_dwSize);
|
|
if (m_dwSize > 0)
|
|
{
|
|
// This is cleaned in the destructor, so no try/catch required
|
|
m_pOriginalPriv = (TOKEN_PRIVILEGES*) new BYTE[m_dwSize];
|
|
if (m_pOriginalPriv == NULL)
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
|
|
}
|
|
|
|
if (m_pOriginalPriv && GetTokenInformation(hToken, TokenPrivileges, m_pOriginalPriv, m_dwSize, &m_dwSize))
|
|
{
|
|
bRetCode = LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &LUID) ;
|
|
if(bRetCode)
|
|
{
|
|
TPriv.PrivilegeCount = 1 ;
|
|
TPriv.Privileges[0].Luid = LUID ;
|
|
TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
|
|
|
|
bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL) ;
|
|
}
|
|
bRetCode = LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &LUID) ;
|
|
if(bRetCode)
|
|
{
|
|
TPriv.PrivilegeCount = 1 ;
|
|
TPriv.Privileges[0].Luid = LUID ;
|
|
TPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
|
|
|
|
bRetCode = AdjustTokenPrivileges(hToken, FALSE, &TPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bRetCode)
|
|
{
|
|
return GetLastError() ;
|
|
}
|
|
|
|
return ERROR_SUCCESS ;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::RestorePrivilege
|
|
*
|
|
* DESCRIPTION : Restores original status of SeRestorePrivilege
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef NTONLY
|
|
void CUserHive::RestorePrivilege()
|
|
{
|
|
ASSERT_BREAK(m_pOriginalPriv != NULL);
|
|
|
|
if (m_pOriginalPriv != NULL)
|
|
{
|
|
SmartCloseHandle hToken;
|
|
|
|
try
|
|
{
|
|
if (OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &hToken))
|
|
{
|
|
AdjustTokenPrivileges(hToken, FALSE, m_pOriginalPriv, m_dwSize, NULL, NULL);
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete m_pOriginalPriv;
|
|
m_pOriginalPriv = NULL;
|
|
m_dwSize = 0;
|
|
|
|
throw;
|
|
}
|
|
|
|
delete m_pOriginalPriv;
|
|
m_pOriginalPriv = NULL;
|
|
m_dwSize = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
DWORD CUserHive::Load(LPCWSTR pszUserName, LPWSTR pszKeyName, size_t PATHSIZE)
|
|
{
|
|
// NOTE: The destructor does not unload the key. Nor does doing a load unload
|
|
// a previously loaded key;
|
|
ASSERT_BREAK(m_hKey == NULL);
|
|
|
|
#ifdef NTONLY
|
|
return LoadNT(pszUserName, pszKeyName, PATHSIZE);
|
|
#endif
|
|
#ifdef WIN9XONLY
|
|
return Load95(pszUserName, pszKeyName);
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::LoadNT
|
|
*
|
|
* DESCRIPTION : Locates user's hive & loads into registry if not already
|
|
* present
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : pszKeyName receives the expanded SID of the user's
|
|
* registry key under HKEY_USERS
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS : Hive will remain in registry unless unloaded
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef NTONLY
|
|
DWORD CUserHive::LoadNT(LPCTSTR pszUserName, LPTSTR pszKeyName, size_t PATHSIZE)
|
|
{
|
|
DWORD i, dwSIDSize, dwRetCode, dwDomainNameSize, dwSubAuthorities ;
|
|
TCHAR szDomainName[_MAX_PATH], szSID[_MAX_PATH], szTemp[_MAX_PATH] ;
|
|
PSID pSID = NULL ;
|
|
PSID_IDENTIFIER_AUTHORITY pSIA ;
|
|
SID_NAME_USE AccountType ;
|
|
CHString sTemp ;
|
|
CRegistry Reg ;
|
|
|
|
// Set the necessary privs
|
|
//========================
|
|
dwRetCode = AcquirePrivilege() ;
|
|
if(dwRetCode != ERROR_SUCCESS)
|
|
{
|
|
return dwRetCode ;
|
|
}
|
|
|
|
// Look up the user's account info
|
|
//================================
|
|
dwSIDSize = 0L ;
|
|
dwDomainNameSize = sizeof(szDomainName) ;
|
|
|
|
BOOL bLookup = FALSE;
|
|
{
|
|
bLookup = LookupAccountName(NULL, pszUserName, pSID, &dwSIDSize, szDomainName, &dwDomainNameSize, &AccountType);
|
|
ASSERT_BREAK ( bLookup == FALSE );
|
|
|
|
if ( ERROR_INSUFFICIENT_BUFFER == ::GetLastError () )
|
|
{
|
|
pSID = (PSID) malloc( dwSIDSize );
|
|
if ( NULL != pSID )
|
|
{
|
|
bLookup = LookupAccountName(NULL, pszUserName, pSID, &dwSIDSize, szDomainName, &dwDomainNameSize, &AccountType);
|
|
}
|
|
else
|
|
{
|
|
RestorePrivilege() ;
|
|
return ERROR_NOT_ENOUGH_MEMORY ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bLookup)
|
|
{
|
|
if ( pSID )
|
|
{
|
|
free ( pSID ) ;
|
|
pSID = NULL ;
|
|
}
|
|
|
|
RestorePrivilege() ;
|
|
return ERROR_BAD_USERNAME ;
|
|
}
|
|
|
|
// Translate the SID into text (a la PSS article Q131320)
|
|
//=======================================================
|
|
|
|
pSIA = GetSidIdentifierAuthority(pSID) ;
|
|
dwSubAuthorities = *GetSidSubAuthorityCount(pSID) ;
|
|
dwSIDSize = _stprintf(szSID, _T("S-%lu-"), (DWORD) SID_REVISION) ;
|
|
|
|
if((pSIA->Value[0] != 0) || (pSIA->Value[1] != 0) )
|
|
{
|
|
dwSIDSize += _stprintf(szSID + _tcslen(szSID), _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
|
|
(USHORT) pSIA->Value[0],
|
|
(USHORT) pSIA->Value[1],
|
|
(USHORT) pSIA->Value[2],
|
|
(USHORT) pSIA->Value[3],
|
|
(USHORT) pSIA->Value[4],
|
|
(USHORT) pSIA->Value[5]) ;
|
|
}
|
|
else
|
|
{
|
|
dwSIDSize += _stprintf(szSID + _tcslen(szSID), _T("%lu"),
|
|
(ULONG)(pSIA->Value[5] ) +
|
|
(ULONG)(pSIA->Value[4] << 8) +
|
|
(ULONG)(pSIA->Value[3] << 16) +
|
|
(ULONG)(pSIA->Value[2] << 24));
|
|
}
|
|
|
|
for(i = 0 ; i < dwSubAuthorities ; i++)
|
|
{
|
|
dwSIDSize += _stprintf(szSID + dwSIDSize, _T("-%lu"),
|
|
*GetSidSubAuthority(pSID, i)) ;
|
|
}
|
|
|
|
free ( pSID ) ;
|
|
pSID = NULL ;
|
|
|
|
// See if the key already exists
|
|
//==============================
|
|
dwRetCode = Reg.Open(HKEY_USERS, szSID, KEY_READ) ;
|
|
|
|
// We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
|
|
// Reg.Close();
|
|
|
|
if(dwRetCode != ERROR_SUCCESS)
|
|
{
|
|
// Try to locate user's registry hive
|
|
//===================================
|
|
|
|
_stprintf(szTemp, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s"), szSID) ;
|
|
dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
dwRetCode = Reg.GetCurrentKeyValue(_T("ProfileImagePath"), sTemp) ;
|
|
Reg.Close() ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
// NT 4 doesn't include the file name in the registry
|
|
//===================================================
|
|
|
|
if(OSInfo.dwMajorVersion >= 4)
|
|
{
|
|
|
|
sTemp += _T("\\NTUSER.DAT") ;
|
|
}
|
|
|
|
ExpandEnvironmentStrings(LPCTSTR(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
|
|
|
|
// Try it three times, another process may have the file open
|
|
bool bTryTryAgain = false;
|
|
int nTries = 0;
|
|
do
|
|
{
|
|
// need to serialize access, using "write" because RegLoadKey wants exclusive access
|
|
// even though it is a read operation
|
|
m_criticalSection.BeginWrite();
|
|
|
|
try
|
|
{
|
|
dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, szSID, szTemp) ;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
m_criticalSection.EndWrite();
|
|
throw;
|
|
}
|
|
|
|
m_criticalSection.EndWrite();
|
|
|
|
if ((dwRetCode == ERROR_SHARING_VIOLATION)
|
|
&& (++nTries < 11))
|
|
{
|
|
Sleep(20 * nTries);
|
|
bTryTryAgain = true;
|
|
}
|
|
else
|
|
{
|
|
bTryTryAgain = false;
|
|
}
|
|
|
|
} while (bTryTryAgain);
|
|
// if we still can't get in, tell somebody.
|
|
if (dwRetCode == ERROR_SHARING_VIOLATION)
|
|
LogErrorMessage(_T("Sharing violation on NTUSER.DAT (Load)"));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
HRESULT hr = StringCchCopy(pszKeyName, PATHSIZE, szSID) ;
|
|
|
|
ASSERT_BREAK(SUCCEEDED(hr));
|
|
|
|
LONG lRetVal;
|
|
CHString sKey(szSID);
|
|
|
|
sKey += _T("\\Software");
|
|
lRetVal = RegOpenKeyEx(HKEY_USERS, sKey, 0, KEY_QUERY_VALUE, &m_hKey);
|
|
|
|
ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Restore original privilege level & end self-impersonation
|
|
//==========================================================
|
|
|
|
RestorePrivilege() ;
|
|
|
|
return dwRetCode ;
|
|
}
|
|
#endif
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::Load95
|
|
*
|
|
* DESCRIPTION : Locates user's hive & loads into registry if not already
|
|
* present
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : pszKeyName receives the expanded SID of the user's
|
|
* registry key under HKEY_USERS
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS : Hive will remain in registry unless unloaded
|
|
*
|
|
*****************************************************************************/
|
|
#ifdef WIN9XONLY
|
|
DWORD CUserHive::Load95(LPCWSTR pszUserName, LPWSTR pszKeyName)
|
|
{
|
|
DWORD dwRetCode;
|
|
WCHAR wszTemp[_MAX_PATH];
|
|
TCHAR szTemp[_MAX_PATH];
|
|
CHString sTemp ;
|
|
CRegistry Reg ;
|
|
|
|
wcscpy(pszKeyName, pszUserName);
|
|
|
|
// See if the key already exists
|
|
//==============================
|
|
dwRetCode = Reg.Open(HKEY_USERS, pszKeyName, KEY_READ) ;
|
|
// We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
|
|
// Reg.Close() ;
|
|
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
// We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
|
|
// Reg.Close() ;
|
|
}
|
|
else
|
|
{
|
|
// Try to locate user's registry hive
|
|
//===================================
|
|
swprintf(wszTemp, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ProfileList\\%s", pszUserName) ;
|
|
dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, wszTemp, KEY_READ);
|
|
if(dwRetCode == ERROR_SUCCESS) {
|
|
|
|
dwRetCode = Reg.GetCurrentKeyValue(L"ProfileImagePath", sTemp) ;
|
|
Reg.Close() ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
sTemp += _T("\\USER.DAT") ;
|
|
|
|
ExpandEnvironmentStrings(TOBSTRT(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
|
|
|
|
// Try it three times, another process may have the file open
|
|
bool bTryTryAgain = false;
|
|
int nTries = 0;
|
|
do
|
|
{
|
|
// need to serialize access, using "write" because RegLoadKey wants exclusive access
|
|
// even though it is a read operation
|
|
m_criticalSection.BeginWrite();
|
|
|
|
try
|
|
{
|
|
dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, TOBSTRT(pszUserName), szTemp) ;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
m_criticalSection.EndWrite();
|
|
throw;
|
|
}
|
|
|
|
m_criticalSection.EndWrite();
|
|
|
|
if ((dwRetCode == ERROR_SHARING_VIOLATION)
|
|
&& (++nTries < 11))
|
|
{
|
|
LogErrorMessage(L"Sharing violation on USER.DAT (Load)");
|
|
Sleep(15 * nTries);
|
|
bTryTryAgain = true;
|
|
}
|
|
else
|
|
bTryTryAgain = false;
|
|
|
|
} while (bTryTryAgain);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
LONG lRetVal;
|
|
CHString sKey(pszUserName);
|
|
|
|
sKey += L"\\Software";
|
|
lRetVal = RegOpenKeyEx(HKEY_USERS, TOBSTRT(sKey), 0, KEY_QUERY_VALUE, &m_hKey);
|
|
ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
|
|
}
|
|
|
|
|
|
return dwRetCode ;
|
|
}
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::LoadProfile
|
|
*
|
|
* DESCRIPTION : Locates user's hive & loads into registry if not already
|
|
* present
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none.
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS : Hive will remain in registry unless unloaded
|
|
* NT Only.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
DWORD CUserHive::LoadProfile( LPCWSTR pszSID, CHString& strUserName )
|
|
{
|
|
// NOTE: The destructor does not unload the key. Nor does doing a load unload
|
|
// a previously loaded key;
|
|
ASSERT_BREAK(m_hKey == NULL);
|
|
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
WCHAR szTemp[_MAX_PATH] ;
|
|
CHString sTemp ;
|
|
CRegistry Reg ;
|
|
|
|
strUserName = L"";
|
|
|
|
// Set the necessary privs
|
|
//========================
|
|
|
|
#ifdef NTONLY
|
|
dwRetCode = AcquirePrivilege() ;
|
|
#endif
|
|
if(dwRetCode != ERROR_SUCCESS)
|
|
{
|
|
return dwRetCode ;
|
|
}
|
|
|
|
// See if the key already exists
|
|
//==============================
|
|
|
|
dwRetCode = Reg.Open(HKEY_USERS, pszSID, KEY_READ) ;
|
|
// We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
|
|
// Reg.Close() ;
|
|
|
|
// If we got the profile, make sure we can get account information regarding
|
|
// the SID.
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
CRegistry Reg2 ;
|
|
StringCbPrintf(szTemp, _MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s", pszSID) ;
|
|
dwRetCode = Reg2.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
// Load the user account information
|
|
dwRetCode = UserAccountFromProfile( Reg2, strUserName );
|
|
// We need to keep a handle open. See m_hKey below, so we'll let the destructor close this.
|
|
Reg2.Close() ;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// Try to locate user's registry hive
|
|
//===================================
|
|
|
|
StringCbPrintf(szTemp,_MAX_PATH, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\%s", pszSID) ;
|
|
dwRetCode = Reg.Open(HKEY_LOCAL_MACHINE, szTemp, KEY_READ) ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
UserAccountFromProfile( Reg, strUserName );
|
|
|
|
dwRetCode = Reg.GetCurrentKeyValue(L"ProfileImagePath", sTemp) ;
|
|
Reg.Close() ;
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
// NT 4 doesn't include the file name in the registry
|
|
//===================================================
|
|
|
|
if(OSInfo.dwMajorVersion >= 4)
|
|
{
|
|
sTemp += _T("\\NTUSER.DAT") ;
|
|
}
|
|
|
|
TCHAR szTemp[MAX_PATH];
|
|
|
|
ExpandEnvironmentStrings(TOBSTRT(sTemp), szTemp, sizeof(szTemp) / sizeof(TCHAR)) ;
|
|
|
|
// Try it three times, another process may have the file open
|
|
bool bTryTryAgain = false;
|
|
int nTries = 0;
|
|
do
|
|
{
|
|
// need to serialize access, using "write" because RegLoadKey wants exclusive access
|
|
// even though it is a read operation
|
|
m_criticalSection.BeginWrite();
|
|
|
|
try
|
|
{
|
|
dwRetCode = (DWORD) RegLoadKey(HKEY_USERS, TOBSTRT(pszSID), szTemp);
|
|
}
|
|
catch ( ... )
|
|
{
|
|
m_criticalSection.EndWrite();
|
|
throw;
|
|
}
|
|
m_criticalSection.EndWrite();
|
|
|
|
if ((dwRetCode == ERROR_SHARING_VIOLATION)
|
|
&& (++nTries < 11))
|
|
{
|
|
LogErrorMessage(L"Sharing violation on NTUSER.DAT (LoadProfile)");
|
|
Sleep(20 * nTries);
|
|
bTryTryAgain = true;
|
|
}
|
|
else
|
|
{
|
|
bTryTryAgain = false;
|
|
}
|
|
|
|
} while (bTryTryAgain);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
LONG lRetVal;
|
|
CHString sKey(pszSID);
|
|
|
|
sKey += _T("\\Software");
|
|
lRetVal = RegOpenKeyEx(HKEY_USERS, TOBSTRT(sKey), 0, KEY_QUERY_VALUE, &m_hKey);
|
|
ASSERT_BREAK(lRetVal == ERROR_SUCCESS);
|
|
}
|
|
|
|
// Restore original privilege level & end self-impersonation
|
|
//==========================================================
|
|
|
|
#ifdef NTONLY
|
|
RestorePrivilege() ;
|
|
#endif
|
|
|
|
return dwRetCode ;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::UserAccountFromProfile
|
|
*
|
|
* DESCRIPTION : Pulls the PSID out of the registry object, and creates
|
|
* a DOMAIN\UserName value.
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none.
|
|
*
|
|
* RETURNS : nothing
|
|
*
|
|
* COMMENTS : Registry Object must be preloaded to the correct profile
|
|
* key.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
DWORD CUserHive::UserAccountFromProfile( CRegistry& reg, CHString& strUserName )
|
|
{
|
|
DWORD dwReturn = ERROR_SUCCESS,
|
|
dwSidSize = 0;
|
|
|
|
if ( ( dwReturn = reg.GetCurrentBinaryKeyValue( L"Sid", NULL, &dwSidSize ) ) == ERROR_SUCCESS )
|
|
{
|
|
PSID psid = new byte [ dwSidSize ];
|
|
|
|
if ( NULL != psid )
|
|
{
|
|
try
|
|
{
|
|
|
|
if ( ( dwReturn = reg.GetCurrentBinaryKeyValue( L"Sid", (LPBYTE) psid, &dwSidSize ) ) == ERROR_SUCCESS )
|
|
{
|
|
CSid sid( psid );
|
|
|
|
// The sid account type must be valid and the lookup must have been
|
|
// successful.
|
|
|
|
if ( sid.IsOK() && sid.IsAccountTypeValid() )
|
|
{
|
|
sid.GetDomainAccountName( strUserName );
|
|
}
|
|
else
|
|
{
|
|
dwReturn = ERROR_NO_SUCH_USER;
|
|
}
|
|
}
|
|
}
|
|
catch ( ... )
|
|
{
|
|
delete [] psid;
|
|
throw ;
|
|
}
|
|
|
|
delete [] psid;
|
|
}
|
|
else
|
|
{
|
|
throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ;
|
|
}
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FUNCTION : CUserHive::Unload
|
|
*
|
|
* DESCRIPTION : Unloads key from HKEY_USERS if present
|
|
*
|
|
* INPUTS : none
|
|
*
|
|
* OUTPUTS : none
|
|
*
|
|
* RETURNS : Windows error code
|
|
*
|
|
* COMMENTS :
|
|
*
|
|
*****************************************************************************/
|
|
|
|
DWORD CUserHive::Unload(LPCWSTR pszKeyName)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
if (m_hKey != NULL)
|
|
{
|
|
RegCloseKey(m_hKey);
|
|
m_hKey = NULL;
|
|
}
|
|
|
|
#ifdef NTONLY
|
|
dwRetCode = AcquirePrivilege();
|
|
#endif
|
|
|
|
if(dwRetCode == ERROR_SUCCESS)
|
|
{
|
|
|
|
m_criticalSection.BeginWrite();
|
|
|
|
try
|
|
{
|
|
dwRetCode = RegUnLoadKey(HKEY_USERS, TOBSTRT(pszKeyName)) ;
|
|
}
|
|
catch ( ... )
|
|
{
|
|
m_criticalSection.EndWrite();
|
|
throw;
|
|
}
|
|
|
|
m_criticalSection.EndWrite();
|
|
|
|
#ifdef NTONLY
|
|
RestorePrivilege() ;
|
|
#endif
|
|
|
|
}
|
|
|
|
return dwRetCode ;
|
|
}
|