windows-nt/Source/XPSP1/NT/shell/lib/secutil/profileutil.cpp

343 lines
11 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
// --------------------------------------------------------------------------
// Module Name: ProfileUtil.cpp
//
// Copyright (c) 2000, Microsoft Corporation
//
// Class to handle profile loading and unloading without a token.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <sddl.h>
#include <lmaccess.h>
#include <lmapibuf.h>
#include <dsgetdc.h>
#include "ProfileUtil.h"
#include "TokenUtil.h"
#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
#define TBOOL(x) (BOOL)(x)
#define TW32(x) (DWORD)(x)
// --------------------------------------------------------------------------
// CUserProfile::s_szUserHiveFilename
//
// Purpose: Default user hive name.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
const TCHAR CUserProfile::s_szUserHiveFilename[] = TEXT("ntuser.dat");
// --------------------------------------------------------------------------
// CUserProfile::CUserProfile
//
// Arguments: pszUsername = User name of profile to load.
// pszDomain = Domain for the user.
//
// Returns: <none>
//
// Purpose: Opens a handle to the given user's hive. If the hive isn't
// loaded then the hive is loaded and a handle opened.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
CUserProfile::CUserProfile (const TCHAR *pszUsername, const TCHAR *pszDomain) :
_hKeyProfile(NULL),
_pszSID(NULL),
_fLoaded(false)
{
// Validate parameter.
if (!IsBadStringPtr(pszUsername, static_cast<UINT_PTR>(-1)))
{
PSID pSID;
// Convert the username to a SID.
pSID = UsernameToSID(pszUsername, pszDomain);
if (pSID != NULL)
{
// Convert the SID to a string.
if (ConvertSidToStringSid(pSID, &_pszSID) != FALSE)
{
// Attempt to open the user's hive.
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_USERS,
_pszSID,
0,
KEY_ALL_ACCESS,
&_hKeyProfile))
{
TCHAR szProfilePath[MAX_PATH];
// If that failed then convert the string to a profile path.
if (SIDStringToProfilePath(_pszSID, szProfilePath))
{
// Prevent buffer overrun.
if ((lstrlen(szProfilePath) + sizeof('\\') + ARRAYSIZE(s_szUserHiveFilename)) < ARRAYSIZE(szProfilePath))
{
CPrivilegeEnable privilege(SE_RESTORE_NAME);
// Enable SE_RESTORE_PRIVILEGE and create the
// path to the user hive. Then load the hive.
lstrcat(szProfilePath, TEXT("\\"));
lstrcat(szProfilePath, s_szUserHiveFilename);
if (ERROR_SUCCESS == RegLoadKey(HKEY_USERS, _pszSID, szProfilePath))
{
// Mark the hive as loaded and open the handle.
_fLoaded = true;
TW32(RegOpenKeyEx(HKEY_USERS,
_pszSID,
0,
KEY_ALL_ACCESS,
&_hKeyProfile));
}
}
}
}
}
(HLOCAL)LocalFree(pSID);
}
}
}
// --------------------------------------------------------------------------
// CUserProfile::~CUserProfile
//
// Arguments: <none>
//
// Returns: <none>
//
// Purpose: Releases resources used by this object.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
CUserProfile::~CUserProfile (void)
{
if (_hKeyProfile != NULL)
{
TBOOL(RegCloseKey(_hKeyProfile));
}
if (_fLoaded)
{
CPrivilegeEnable privilege(SE_RESTORE_NAME);
TW32(RegUnLoadKey(HKEY_USERS, _pszSID));
_fLoaded = false;
}
if (_pszSID != NULL)
{
(HLOCAL)LocalFree(_pszSID);
_pszSID = NULL;
}
}
// --------------------------------------------------------------------------
// CUserProfile::operator HKEY
//
// Arguments: <none>
//
// Returns: HKEY
//
// Purpose: Returns the HKEY to the user's hive.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
CUserProfile::operator HKEY (void) const
{
return(_hKeyProfile);
}
// --------------------------------------------------------------------------
// CUserProfile::UsernameToSID
//
// Arguments: pszUsername = User name to convert.
// pszDomain = Domain for the user.
//
// Returns: PSID
//
// Purpose: Uses the security accounts manager to look up the account by
// name and return the SID.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
PSID CUserProfile::UsernameToSID (const TCHAR *pszUsername, const TCHAR *pszDomain)
{
DWORD dwSIDSize, dwComputerNameSize, dwReferencedDomainSize;
SID_NAME_USE eSIDUse;
PSID pSID, pSIDResult;
WCHAR *pszDomainControllerName;
DOMAIN_CONTROLLER_INFO *pDCI;
TCHAR szComputerName[CNLEN + sizeof('\0')];
pSIDResult = NULL;
dwComputerNameSize = ARRAYSIZE(szComputerName);
if (GetComputerName(szComputerName, &dwComputerNameSize) == FALSE)
{
szComputerName[0] = TEXT('\0');
}
if ((pszDomain != NULL) &&
(lstrcmpi(szComputerName, pszDomain) != 0) &&
(ERROR_SUCCESS == DsGetDcName(NULL,
pszDomain,
NULL,
NULL,
0,
&pDCI)))
{
pszDomainControllerName = pDCI->DomainControllerName;
}
else
{
pDCI = NULL;
pszDomainControllerName = NULL;
}
dwSIDSize = dwReferencedDomainSize = 0;
(BOOL)LookupAccountName(pszDomainControllerName,
pszUsername,
NULL,
&dwSIDSize,
NULL,
&dwReferencedDomainSize,
&eSIDUse);
pSID = LocalAlloc(LMEM_FIXED, dwSIDSize);
if (pSID != NULL)
{
TCHAR *pszReferencedDomain;
pszReferencedDomain = static_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, dwReferencedDomainSize * sizeof(TCHAR)));
if (pszReferencedDomain != NULL)
{
if (LookupAccountName(pszDomainControllerName,
pszUsername,
pSID,
&dwSIDSize,
pszReferencedDomain,
&dwReferencedDomainSize,
&eSIDUse) != FALSE)
{
if (SidTypeUser == eSIDUse)
{
// If the account was successfully looked up and the
// account type is a user then return the result back
// to the caller and ensure that it's not released here.
pSIDResult = pSID;
pSID = NULL;
}
}
(HLOCAL)LocalFree(pszReferencedDomain);
}
if (pSID != NULL)
{
(HLOCAL)LocalFree(pSID);
}
}
if (pDCI != NULL)
{
(NET_API_STATUS)NetApiBufferFree(pDCI);
}
return(pSIDResult);
}
// --------------------------------------------------------------------------
// CUserProfile::SIDStringToProfilePath
//
// Arguments: pszSIDString = SID string to look up.
// pszProfilePath = Returned path to the profile.
//
// Returns: bool
//
// Purpose: Looks up the profile path for the given SID string in the
// location where userenv stores it. This doesn't change
// although no API exists for this information.
//
// History: 2000-06-21 vtan created
// --------------------------------------------------------------------------
bool CUserProfile::SIDStringToProfilePath (const TCHAR *pszSIDString, TCHAR *pszProfilePath)
{
bool fResult;
fResult = false;
if (!IsBadStringPtr(pszSIDString, static_cast<UINT_PTR>(-1)) && !IsBadWritePtr(pszProfilePath, MAX_PATH * sizeof(TCHAR)))
{
HKEY hKeyProfileList;
pszProfilePath[0] = TEXT('\0');
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"),
0,
KEY_QUERY_VALUE,
&hKeyProfileList))
{
HKEY hKeySID;
if (ERROR_SUCCESS == RegOpenKeyEx(hKeyProfileList,
pszSIDString,
0,
KEY_QUERY_VALUE,
&hKeySID))
{
DWORD dwType, dwProfilePathSize;
TCHAR szProfilePath[MAX_PATH];
dwProfilePathSize = ARRAYSIZE(szProfilePath);
if (ERROR_SUCCESS == RegQueryValueEx(hKeySID,
TEXT("ProfileImagePath"),
NULL,
&dwType,
reinterpret_cast<LPBYTE>(szProfilePath),
&dwProfilePathSize))
{
if (REG_EXPAND_SZ == dwType)
{
fResult = true;
if (ExpandEnvironmentStrings(szProfilePath, pszProfilePath, MAX_PATH) == 0)
{
dwType = REG_SZ;
}
}
if (REG_SZ == dwType)
{
fResult = true;
(TCHAR*)lstrcpy(pszProfilePath, szProfilePath);
}
}
TW32(RegCloseKey(hKeySID));
}
TW32(RegCloseKey(hKeyProfileList));
}
}
return(fResult);
}