2167 lines
53 KiB
C
2167 lines
53 KiB
C
#include "pch.h"
|
|
|
|
//*************************************************************
|
|
//
|
|
// CheckSlash()
|
|
//
|
|
// Purpose: Checks for an ending slash and adds one if
|
|
// it is missing.
|
|
//
|
|
// Parameters: lpDir - directory
|
|
//
|
|
// Return: Pointer to the end of the string
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/19/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
LPTSTR CheckSlash (LPTSTR lpDir)
|
|
{
|
|
LPTSTR lpEnd;
|
|
|
|
lpEnd = lpDir + lstrlen(lpDir);
|
|
|
|
if (*(lpEnd - 1) != TEXT('\\')) {
|
|
*lpEnd = TEXT('\\');
|
|
lpEnd++;
|
|
*lpEnd = TEXT('\0');
|
|
}
|
|
|
|
return lpEnd;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnodeRecurse()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values.
|
|
// Called by RegDelnode
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// lpSubKey - SubKey to delete
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL RegDelnodeRecurse (HKEY hKeyRoot, PWSTR lpSubKey)
|
|
{
|
|
PWSTR End;
|
|
LONG rc;
|
|
DWORD dwSize;
|
|
WCHAR szName[MAX_PATH];
|
|
HKEY hKey;
|
|
FILETIME ftWrite;
|
|
|
|
//
|
|
// First, see if we can delete the key without having
|
|
// to recurse.
|
|
//
|
|
|
|
|
|
rc = RegDeleteKey(hKeyRoot, lpSubKey);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
rc = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
if (rc == ERROR_FILE_NOT_FOUND) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
End = CheckSlash(lpSubKey);
|
|
|
|
//
|
|
// Enumerate the keys
|
|
//
|
|
|
|
dwSize = MAX_PATH;
|
|
rc = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
|
NULL, NULL, &ftWrite);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
|
|
do {
|
|
|
|
lstrcpy (End, szName);
|
|
|
|
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Enumerate again
|
|
//
|
|
|
|
dwSize = MAX_PATH;
|
|
|
|
rc = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL,
|
|
NULL, NULL, &ftWrite);
|
|
|
|
|
|
} while (rc == ERROR_SUCCESS);
|
|
}
|
|
|
|
End--;
|
|
*End = TEXT('\0');
|
|
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
|
|
//
|
|
// Try again to delete the key
|
|
//
|
|
|
|
rc = RegDeleteKey(hKeyRoot, lpSubKey);
|
|
|
|
if (rc == ERROR_SUCCESS) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// RegDelnode()
|
|
//
|
|
// Purpose: Deletes a registry key and all it's subkeys / values
|
|
//
|
|
// Parameters: hKeyRoot - Root key
|
|
// lpSubKey - SubKey to delete
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/3/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL RegDelnode (HKEY hKeyRoot, PWSTR lpSubKey)
|
|
{
|
|
WCHAR szDelKey[2 * MAX_PATH];
|
|
|
|
|
|
lstrcpy (szDelKey, lpSubKey);
|
|
|
|
return RegDelnodeRecurse(hKeyRoot, szDelKey);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateNestedDirectory()
|
|
//
|
|
// Purpose: Creates a subdirectory and all it's parents
|
|
// if necessary.
|
|
//
|
|
// Parameters: lpDirectory - Directory name
|
|
// lpSecurityAttributes - Security Attributes
|
|
//
|
|
// Return: > 0 if successful
|
|
// 0 if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/08/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
|
{
|
|
TCHAR szDirectory[2*MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
PACL Acl;
|
|
BOOL Present;
|
|
BOOL Defaulted;
|
|
|
|
//
|
|
// Check for NULL pointer
|
|
//
|
|
|
|
if (!lpDirectory || !(*lpDirectory)) {
|
|
DEBUGMSG ((DM_WARNING, "CreateNestedDirectory: Received a NULL pointer."));
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// First, see if we can create the directory without having
|
|
// to build parent directories.
|
|
//
|
|
|
|
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// If this directory exists already, this is OK too.
|
|
//
|
|
|
|
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
//
|
|
// Update the security
|
|
//
|
|
|
|
if (lpSecurityAttributes) {
|
|
|
|
if (!GetSecurityDescriptorDacl (
|
|
lpSecurityAttributes->lpSecurityDescriptor,
|
|
&Present,
|
|
&Acl,
|
|
&Defaulted
|
|
)) {
|
|
|
|
Present = FALSE;
|
|
|
|
}
|
|
|
|
if (Present && !Defaulted) {
|
|
|
|
if (!SetNamedSecurityInfo (
|
|
(PTSTR) lpDirectory,
|
|
SE_FILE_OBJECT,
|
|
DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
Acl,
|
|
NULL
|
|
)) {
|
|
|
|
return GetLastError();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return ERROR_ALREADY_EXISTS;
|
|
}
|
|
|
|
|
|
//
|
|
// No luck, copy the string to a buffer we can munge
|
|
//
|
|
|
|
lstrcpy (szDirectory, lpDirectory);
|
|
|
|
|
|
//
|
|
// Find the first subdirectory name
|
|
//
|
|
|
|
lpEnd = szDirectory;
|
|
|
|
if (szDirectory[1] == TEXT(':')) {
|
|
lpEnd += 3;
|
|
} else if (szDirectory[1] == TEXT('\\')) {
|
|
|
|
//
|
|
// Skip the first two slashes
|
|
//
|
|
|
|
lpEnd += 2;
|
|
|
|
//
|
|
// Find the slash between the server name and
|
|
// the share name.
|
|
//
|
|
|
|
while (*lpEnd && *lpEnd != TEXT('\\')) {
|
|
lpEnd++;
|
|
}
|
|
|
|
if (!(*lpEnd)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Skip the slash, and find the slash between
|
|
// the share name and the directory name.
|
|
//
|
|
|
|
lpEnd++;
|
|
|
|
while (*lpEnd && *lpEnd != TEXT('\\')) {
|
|
lpEnd++;
|
|
}
|
|
|
|
if (!(*lpEnd)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Leave pointer at the beginning of the directory.
|
|
//
|
|
|
|
lpEnd++;
|
|
|
|
|
|
} else if (szDirectory[0] == TEXT('\\')) {
|
|
lpEnd++;
|
|
}
|
|
|
|
while (*lpEnd) {
|
|
|
|
while (*lpEnd && *lpEnd != TEXT('\\')) {
|
|
lpEnd++;
|
|
}
|
|
|
|
if (*lpEnd == TEXT('\\')) {
|
|
*lpEnd = TEXT('\0');
|
|
|
|
if (!CreateDirectory (szDirectory, NULL)) {
|
|
|
|
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
|
DEBUGMSG ((DM_WARNING, "CreateNestedDirectory: CreateDirectory failed with %d.", GetLastError()));
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
*lpEnd = TEXT('\\');
|
|
lpEnd++;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Create the final directory
|
|
//
|
|
|
|
if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
|
|
return 1;
|
|
}
|
|
|
|
if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
return ERROR_ALREADY_EXISTS;
|
|
}
|
|
|
|
|
|
//
|
|
// Failed
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "CreateNestedDirectory: Failed to create the directory with error %d.", GetLastError()));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateSecureDirectory()
|
|
//
|
|
// Purpose: Creates a secure directory that only the user,
|
|
// admin, and system have access to in the normal case
|
|
// and for only the user and system in the restricted case.
|
|
//
|
|
//
|
|
// Parameters: lpDirectory - Directory Name
|
|
// pSid - Sid (used by CreateUserProfile)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/20/95 ericflo Created
|
|
// 9/30/98 ushaji added fRestricted flag
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL CreateSecureDirectory (LPTSTR lpDirectory, PSID pSid)
|
|
{
|
|
SECURITY_DESCRIPTOR sd;
|
|
SECURITY_ATTRIBUTES sa;
|
|
PACL pAcl = NULL;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Entering with <%s>", lpDirectory));
|
|
|
|
if (!pSid) {
|
|
|
|
//
|
|
// Attempt to create the directory
|
|
//
|
|
|
|
if (CreateNestedDirectory(lpDirectory, NULL)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Created the directory <%s>", lpDirectory));
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to created the directory <%s>", lpDirectory));
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the default ACL
|
|
//
|
|
|
|
pAcl = CreateDefaultAcl (pSid);
|
|
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Add the security descriptor to the sa structure
|
|
//
|
|
|
|
sa.nLength = sizeof(sa);
|
|
sa.lpSecurityDescriptor = &sd;
|
|
sa.bInheritHandle = FALSE;
|
|
|
|
|
|
//
|
|
// Attempt to create the directory
|
|
//
|
|
|
|
if (CreateNestedDirectory(lpDirectory, &sa)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Created the directory <%s>", lpDirectory));
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "CreateSecureDirectory: Failed to created the directory <%s>", lpDirectory));
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
FreeDefaultAcl (pAcl);
|
|
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
|
|
PACL
|
|
CreateDefaultAcl (
|
|
PSID pSid
|
|
)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidSystem = NULL, psidAdmin = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize system sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the Admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize admin sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (pSid)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
|
|
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
aceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, pSid)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to add ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "CreateDefaultAcl: Failed to get ace (%d). Error = %d", aceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
Exit:
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
return pAcl;
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeDefaultAcl (
|
|
PACL pAcl
|
|
)
|
|
{
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
OurConvertSidToStringSid (
|
|
IN PSID Sid,
|
|
OUT PWSTR *SidString
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
|
|
//
|
|
// Convert the sid into text format
|
|
//
|
|
|
|
NtStatus = RtlConvertSidToUnicodeString (&UnicodeString, Sid, TRUE);
|
|
|
|
if (!NT_SUCCESS (NtStatus)) {
|
|
|
|
DEBUGMSG ((
|
|
DM_WARNING,
|
|
"CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x",
|
|
NtStatus
|
|
));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
*SidString = UnicodeString.Buffer;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
DeleteSidString (
|
|
PWSTR SidString
|
|
)
|
|
{
|
|
UNICODE_STRING String;
|
|
|
|
if (!SidString) {
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString (&String, SidString);
|
|
RtlFreeUnicodeString (&String);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetProfileRoot (
|
|
IN PSID Sid,
|
|
OUT PWSTR ProfileDir
|
|
)
|
|
{
|
|
WCHAR LocalProfileKey[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD Size;
|
|
DWORD Type;
|
|
DWORD Attributes;
|
|
PWSTR SidString;
|
|
WCHAR ExpandedRoot[MAX_PATH];
|
|
|
|
ProfileDir[0] = 0;
|
|
|
|
if (!OurConvertSidToStringSid (Sid, &SidString)) {
|
|
DEBUGMSG ((DM_WARNING, "GetProfileRoot: Can't convert SID to string"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Check if this user's profile exists
|
|
//
|
|
|
|
lstrcpy (LocalProfileKey, PROFILE_LIST_PATH);
|
|
lstrcat (LocalProfileKey, TEXT("\\"));
|
|
lstrcat (LocalProfileKey, SidString);
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
Size = MAX_PATH;
|
|
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
|
|
&Type, (LPBYTE) ProfileDir, &Size);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
if (ProfileDir[0]) {
|
|
|
|
ExpandEnvironmentStrings (ProfileDir, ExpandedRoot, MAX_PATH);
|
|
Attributes = GetFileAttributes (ExpandedRoot);
|
|
|
|
if (Attributes == 0xFFFFFFFF || !(Attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
ProfileDir[0] = 0;
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: Profile %s is not vaild", SidString));
|
|
} else {
|
|
lstrcpy (ProfileDir, ExpandedRoot);
|
|
}
|
|
|
|
} else {
|
|
DEBUGMSG ((DM_VERBOSE, "GetProfileRoot: SID %s does not have a profile directory", SidString));
|
|
}
|
|
|
|
DeleteSidString (SidString);
|
|
|
|
return ProfileDir[0] != 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
UpdateProfileSecurity (
|
|
PSID Sid
|
|
)
|
|
{
|
|
WCHAR ProfileDir[MAX_PATH];
|
|
WCHAR ExpProfileDir[MAX_PATH];
|
|
WCHAR LocalProfileKey[MAX_PATH];
|
|
PWSTR SidString = NULL;
|
|
PWSTR End, Save;
|
|
LONG rc;
|
|
DWORD dwError;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
HKEY hKey;
|
|
BOOL b = FALSE;
|
|
BOOL UnloadProfile = FALSE;
|
|
|
|
__try {
|
|
//
|
|
// Convert the sid into text format
|
|
//
|
|
|
|
if (!OurConvertSidToStringSid (Sid, &SidString)) {
|
|
DEBUGMSG ((
|
|
DM_WARNING,
|
|
"UpdateProfileSecurity: Can't convert SID to string"
|
|
));
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Check if this user's profile exists already
|
|
//
|
|
|
|
lstrcpy(LocalProfileKey, PROFILE_LIST_PATH);
|
|
lstrcat(LocalProfileKey, TEXT("\\"));
|
|
lstrcat(LocalProfileKey, SidString);
|
|
|
|
ProfileDir[0] = 0;
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(ProfileDir);
|
|
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
|
|
&dwType, (LPBYTE) ProfileDir, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
if (!ProfileDir[0]) {
|
|
DEBUGMSG ((DM_WARNING, "UpdateProfileSecurity: No profile for specified user"));
|
|
SetLastError (ERROR_BAD_PROFILE);
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// The user has a profile, so update the security settings
|
|
//
|
|
|
|
ExpandEnvironmentStrings (
|
|
ProfileDir,
|
|
ExpProfileDir,
|
|
ARRAYSIZE(ExpProfileDir)
|
|
);
|
|
|
|
//
|
|
// Load the hive temporary so the security can be fixed
|
|
//
|
|
|
|
End = CheckSlash (ExpProfileDir);
|
|
Save = End - 1;
|
|
lstrcpy (End, L"NTUSER.DAT");
|
|
|
|
rc = MyRegLoadKey (HKEY_USERS, SidString, ExpProfileDir);
|
|
|
|
*Save = 0;
|
|
|
|
if (rc != ERROR_SUCCESS) {
|
|
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: Failed to load hive, error = %d.", rc));
|
|
SetLastError (rc);
|
|
|
|
__leave;
|
|
}
|
|
|
|
UnloadProfile = TRUE;
|
|
|
|
if (!SetupNewHive (SidString, Sid)) {
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: SetupNewHive failed, error = %d.", GetLastError()));
|
|
__leave;
|
|
|
|
}
|
|
|
|
//
|
|
// Fix the file system security
|
|
//
|
|
|
|
if (!CreateSecureDirectory (ExpProfileDir, Sid)) {
|
|
DEBUGMSG((DM_WARNING, "UpdateProfileSecurity: CreateSecureDirectory failed, error = %d.", GetLastError()));
|
|
__leave;
|
|
}
|
|
|
|
b = TRUE;
|
|
|
|
}
|
|
__finally {
|
|
dwError = GetLastError();
|
|
|
|
if (UnloadProfile) {
|
|
MyRegUnLoadKey (HKEY_USERS, SidString);
|
|
}
|
|
|
|
DeleteSidString (SidString);
|
|
|
|
SetLastError (dwError);
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeleteProfileRegistrySettings()
|
|
//
|
|
// Purpose: Deletes the specified profile from the
|
|
// registry.
|
|
//
|
|
// Parameters: lpSidString - Registry subkey
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/23/95 ericflo Created
|
|
// 5/20/99 jimschm Moved out of DeleteProfile
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL DeleteProfileRegistrySettings (LPTSTR lpSidString)
|
|
{
|
|
LONG lResult;
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szUserGuid[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD dwType, dwSize;
|
|
|
|
if (lpSidString && *lpSidString) {
|
|
|
|
lstrcpy(szTemp, PROFILE_LIST_PATH);
|
|
lstrcat(szTemp, TEXT("\\"));
|
|
lstrcat(szTemp, lpSidString);
|
|
|
|
//
|
|
// get the user guid
|
|
//
|
|
|
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTemp, 0, KEY_READ, &hKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Query for the user guid
|
|
//
|
|
|
|
dwSize = MAX_PATH * sizeof(TCHAR);
|
|
lResult = RegQueryValueEx (hKey, PROFILE_GUID, NULL, &dwType, (LPBYTE) szUserGuid, &dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "DeleteProfile: Failed to query profile guid with error %d", lResult));
|
|
}
|
|
else {
|
|
lstrcpy(szTemp, PROFILE_GUID_PATH);
|
|
lstrcat(szTemp, TEXT("\\"));
|
|
lstrcat(szTemp, szUserGuid);
|
|
|
|
//
|
|
// Delete the profile guid from the guid list
|
|
//
|
|
|
|
lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "DeleteProfile: failed to delete profile guid. Error = %d", lResult));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
lstrcpy(szTemp, PROFILE_LIST_PATH);
|
|
lstrcat(szTemp, TEXT("\\"));
|
|
lstrcat(szTemp, lpSidString);
|
|
|
|
lResult = RegDeleteKey(HKEY_LOCAL_MACHINE, szTemp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "DeleteProfile: Unable to delete registry entry. Error = %d", lResult));
|
|
SetLastError(lResult);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* GetUserSid
|
|
*
|
|
* Allocs space for the user sid, fills it in and returns a pointer. Caller
|
|
* The sid should be freed by calling DeleteUserSid.
|
|
*
|
|
* Note the sid returned is the user's real sid, not the per-logon sid.
|
|
*
|
|
* Returns pointer to sid or NULL on failure.
|
|
*
|
|
* History:
|
|
* 26-Aug-92 Davidc Created.
|
|
\***************************************************************************/
|
|
PSID GetUserSid (HANDLE UserToken)
|
|
{
|
|
PTOKEN_USER pUser, pTemp;
|
|
PSID pSid;
|
|
DWORD BytesRequired = 200;
|
|
NTSTATUS status;
|
|
|
|
|
|
//
|
|
// Allocate space for the user info
|
|
//
|
|
|
|
pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
|
|
|
|
|
|
if (pUser == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Read in the UserInfo
|
|
//
|
|
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
if (status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
//
|
|
// Allocate a bigger buffer and try again.
|
|
//
|
|
|
|
pTemp = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
|
|
if (pTemp == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
LocalFree (pUser);
|
|
return NULL;
|
|
}
|
|
|
|
pUser = pTemp;
|
|
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to query user info from user token, status = 0x%x",
|
|
status));
|
|
LocalFree(pUser);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BytesRequired = RtlLengthSid(pUser->User.Sid);
|
|
pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
|
|
if (pSid == NULL) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: Failed to allocate %d bytes",
|
|
BytesRequired));
|
|
LocalFree(pUser);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
|
|
|
|
LocalFree(pUser);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DEBUGMSG((DM_WARNING, "GetUserSid: RtlCopySid Failed. status = %d",
|
|
status));
|
|
LocalFree(pSid);
|
|
pSid = NULL;
|
|
}
|
|
|
|
|
|
return pSid;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* DeleteUserSid
|
|
*
|
|
* Deletes a user sid previously returned by GetUserSid()
|
|
*
|
|
* Returns nothing.
|
|
*
|
|
* History:
|
|
* 26-Aug-92 Davidc Created
|
|
*
|
|
\***************************************************************************/
|
|
VOID DeleteUserSid(PSID Sid)
|
|
{
|
|
LocalFree(Sid);
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MyRegLoadKey()
|
|
//
|
|
// Purpose: Loads a hive into the registry
|
|
//
|
|
// Parameters: hKey - Key to load the hive into
|
|
// lpSubKey - Subkey name
|
|
// lpFile - hive filename
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// Error number if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/22/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
LONG MyRegLoadKey(HKEY hKey, LPTSTR lpSubKey, LPTSTR lpFile)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOLEAN WasEnabled;
|
|
int error;
|
|
DWORD dwException;
|
|
WCHAR szException[20];
|
|
|
|
__try {
|
|
|
|
//
|
|
// Enable the restore privilege
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, TRUE, &WasEnabled);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
error = RegLoadKey(hKey, lpSubKey, lpFile);
|
|
|
|
//
|
|
// Restore the privilege to its previous state
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, TRUE, &WasEnabled);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
|
|
}
|
|
|
|
|
|
//
|
|
// Convert a sharing violation error to success since the hive
|
|
// is already loaded
|
|
//
|
|
|
|
if (error == ERROR_SHARING_VIOLATION) {
|
|
error = ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the hive was loaded
|
|
//
|
|
|
|
if (error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to load subkey <%s>, error =%d", lpSubKey, error));
|
|
}
|
|
|
|
} else {
|
|
error = ERROR_ACCESS_DENIED;
|
|
DEBUGMSG((DM_WARNING, "MyRegLoadKey: Failed to enable restore privilege to load registry key, error %u", error));
|
|
}
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
dwException = GetExceptionCode();
|
|
ASSERT(dwException == 0);
|
|
wsprintf(szException, L"!!!! 0x%x ", dwException);
|
|
OutputDebugString(szException);
|
|
OutputDebugString(L"Exception hit in MyRegLoadKey in userenv\n");
|
|
ASSERT(dwException == 0);
|
|
|
|
}
|
|
|
|
DEBUGMSG((DM_VERBOSE, "MyRegLoadKey: Returning %d.", error));
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// MyRegUnLoadKey()
|
|
//
|
|
// Purpose: Unloads a registry key
|
|
//
|
|
// Parameters: hKey - Registry handle
|
|
// lpSubKey - Subkey to be unloaded
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/19/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL MyRegUnLoadKey(HKEY hKey, LPTSTR lpSubKey)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
LONG error;
|
|
NTSTATUS Status;
|
|
BOOLEAN WasEnabled;
|
|
DWORD dwException;
|
|
WCHAR szException[20];
|
|
|
|
|
|
__try {
|
|
|
|
//
|
|
// Enable the restore privilege
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, TRUE, &WasEnabled);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
error = RegUnLoadKey(hKey, lpSubKey);
|
|
|
|
if ( error != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to unmount hive %x", error));
|
|
SetLastError(error);
|
|
bResult = FALSE;
|
|
}
|
|
|
|
//
|
|
// Restore the privilege to its previous state
|
|
//
|
|
|
|
Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, TRUE, &WasEnabled);
|
|
if (!NT_SUCCESS(Status)) {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnLoadKey: Failed to restore RESTORE privilege to previous enabled state"));
|
|
}
|
|
|
|
} else {
|
|
DEBUGMSG((DM_WARNING, "MyRegUnloadKey: Failed to enable restore privilege to unload registry key"));
|
|
Status = ERROR_ACCESS_DENIED;
|
|
SetLastError(Status);
|
|
bResult = FALSE;
|
|
}
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
dwException = GetExceptionCode();
|
|
ASSERT(dwException == 0);
|
|
wsprintf(szException, L"!!!! 0x%x ", dwException);
|
|
OutputDebugString(szException);
|
|
OutputDebugString(L"Exception hit in MyRegUnLoadKey in userenv\n");
|
|
ASSERT(dwException == 0);
|
|
}
|
|
|
|
DEBUGMSG((DM_VERBOSE, "MyRegUnloadKey: Returning %d, error %u.", bResult, GetLastError()));
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetDefaultUserHiveSecurity()
|
|
//
|
|
// Purpose: Initializes a user hive with the
|
|
// appropriate acls
|
|
//
|
|
// Parameters: pSid - Sid (used by CreateNewUser)
|
|
// RootKey - registry handle to hive root
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
// other error code if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/18/95 ericflo Created as part of
|
|
// SetupNewHive
|
|
// 3/29/98 adamed Moved out of SetupNewHive
|
|
// to this function
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetDefaultUserHiveSecurity(PSID pSid, HKEY RootKey)
|
|
{
|
|
DWORD Error;
|
|
SECURITY_DESCRIPTOR sd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
|
|
DWORD cbAcl, AceIndex;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Entering"));
|
|
|
|
|
|
//
|
|
// Create the security descriptor that will be applied to each key
|
|
//
|
|
|
|
//
|
|
// Give the user access by their real sid so they still have access
|
|
// when they logoff and logon again
|
|
//
|
|
|
|
psidUser = pSid;
|
|
bFreeSid = FALSE;
|
|
|
|
if (!psidUser) {
|
|
DEBUGMSG((DM_WARNING, "SetDefaultUserHiveSecurity: Failed to get user sid"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize system sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize admin sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the Restricted sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize restricted sid. Error = %d",
|
|
GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + (2*GetLengthSid(psidRestricted)) +
|
|
sizeof(ACL) +
|
|
(8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
AceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidUser)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for Restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidUser)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG((DM_VERBOSE, "SetDefaultUserHiveSecurity: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the security descriptor on the entire tree
|
|
//
|
|
|
|
Error = ApplySecurityToRegistryTree(RootKey, &sd);
|
|
|
|
if (ERROR_SUCCESS == Error) {
|
|
bRetVal = TRUE;
|
|
}
|
|
else
|
|
SetLastError(Error);
|
|
|
|
Exit:
|
|
|
|
//
|
|
// Free the sids and acl
|
|
//
|
|
|
|
if (bFreeSid && psidUser) {
|
|
DeleteUserSid (psidUser);
|
|
}
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetupNewHive()
|
|
//
|
|
// Purpose: Initializes the new user hive created by copying
|
|
// the default hive.
|
|
//
|
|
// Parameters: lpSidString - Sid string
|
|
// pSid - Sid (used by CreateNewUser)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/18/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetupNewHive(LPTSTR lpSidString, PSID pSid)
|
|
{
|
|
DWORD Error, IgnoreError;
|
|
HKEY RootKey;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetupNewHive: Entering"));
|
|
|
|
|
|
//
|
|
// Open the root of the user's profile
|
|
//
|
|
|
|
Error = RegOpenKeyEx(HKEY_USERS,
|
|
lpSidString,
|
|
0,
|
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
&RootKey);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to open root of user registry, error = %d", Error));
|
|
|
|
} else {
|
|
|
|
//
|
|
// First Secure the entire hive -- use security that
|
|
// will be sufficient for most of the hive.
|
|
// After this, we can add special settings to special
|
|
// sections of this hive.
|
|
//
|
|
|
|
if (SetDefaultUserHiveSecurity(pSid, RootKey)) {
|
|
|
|
TCHAR szSubKey[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
|
|
//
|
|
// Change the security on certain keys in the user's registry
|
|
// so that only Admin's and the OS have write access.
|
|
//
|
|
|
|
lstrcpy (szSubKey, lpSidString);
|
|
lpEnd = CheckSlash(szSubKey);
|
|
lstrcpy (lpEnd, WINDOWS_POLICIES_KEY);
|
|
|
|
if (!SecureUserKey(szSubKey, pSid)) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure windows policies key"));
|
|
}
|
|
|
|
lstrcpy (lpEnd, ROOT_POLICIES_KEY);
|
|
|
|
if (!SecureUserKey(szSubKey, pSid)) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to secure root policies key"));
|
|
}
|
|
|
|
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
Error = GetLastError();
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to apply security to user registry tree, error = %d", Error));
|
|
}
|
|
|
|
RegFlushKey (RootKey);
|
|
|
|
IgnoreError = RegCloseKey(RootKey);
|
|
if (IgnoreError != ERROR_SUCCESS) {
|
|
DEBUGMSG((DM_WARNING, "SetupNewHive: Failed to close reg key, error = %d", IgnoreError));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG((DM_VERBOSE, "SetupNewHive: Leaving with a return value of %d, error %u", bRetVal, Error));
|
|
|
|
if (!bRetVal)
|
|
SetLastError(Error);
|
|
return(bRetVal);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ApplySecurityToRegistryTree()
|
|
//
|
|
// Purpose: Applies the passed security descriptor to the passed
|
|
// key and all its descendants. Only the parts of
|
|
// the descriptor inddicated in the security
|
|
// info value are actually applied to each registry key.
|
|
//
|
|
// Parameters: RootKey - Registry key
|
|
// pSD - Security Descriptor
|
|
//
|
|
// Return: ERROR_SUCCESS if successful
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/19/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
|
|
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD SubKeyIndex;
|
|
LPTSTR SubKeyName;
|
|
HKEY SubKey;
|
|
DWORD cchSubKeySize = MAX_PATH + 1;
|
|
|
|
|
|
|
|
//
|
|
// First apply security
|
|
//
|
|
|
|
RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
|
|
|
|
|
|
//
|
|
// Open each sub-key and apply security to its sub-tree
|
|
//
|
|
|
|
SubKeyIndex = 0;
|
|
|
|
SubKeyName = GlobalAlloc (GPTR, cchSubKeySize * sizeof(TCHAR));
|
|
|
|
if (!SubKeyName) {
|
|
DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Failed to allocate memory, error = %d", GetLastError()));
|
|
return GetLastError();
|
|
}
|
|
|
|
while (TRUE) {
|
|
|
|
//
|
|
// Get the next sub-key name
|
|
//
|
|
|
|
Error = RegEnumKey(RootKey, SubKeyIndex, SubKeyName, cchSubKeySize);
|
|
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
if (Error == ERROR_NO_MORE_ITEMS) {
|
|
|
|
//
|
|
// Successful end of enumeration
|
|
//
|
|
|
|
Error = ERROR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_WARNING, "ApplySecurityToRegistryTree: Registry enumeration failed with error = %d", Error));
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the sub-key
|
|
//
|
|
|
|
Error = RegOpenKeyEx(RootKey,
|
|
SubKeyName,
|
|
0,
|
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
&SubKey);
|
|
|
|
if (Error == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Apply security to the sub-tree
|
|
//
|
|
|
|
ApplySecurityToRegistryTree(SubKey, pSD);
|
|
|
|
|
|
//
|
|
// We're finished with the sub-key
|
|
//
|
|
|
|
RegCloseKey(SubKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Go enumerate the next sub-key
|
|
//
|
|
|
|
SubKeyIndex ++;
|
|
}
|
|
|
|
|
|
GlobalFree (SubKeyName);
|
|
|
|
return Error;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SecureUserKey()
|
|
//
|
|
// Purpose: Sets security on a key in the user's hive
|
|
// so only admin's can change it.
|
|
//
|
|
// Parameters: lpKey - Key to secure
|
|
// pSid - Sid (used by CreateNewUser)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 6/20/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SecureUserKey(LPTSTR lpKey, PSID pSid)
|
|
{
|
|
DWORD Error;
|
|
HKEY RootKey;
|
|
SECURITY_DESCRIPTOR sd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pAcl = NULL;
|
|
PSID psidUser = NULL, psidSystem = NULL, psidAdmin = NULL, psidRestricted = NULL;
|
|
DWORD cbAcl, AceIndex, dwDisp;
|
|
ACE_HEADER * lpAceHeader;
|
|
BOOL bRetVal = FALSE;
|
|
BOOL bFreeSid = TRUE;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Entering"));
|
|
|
|
|
|
//
|
|
// Create the security descriptor
|
|
//
|
|
|
|
//
|
|
// Give the user access by their real sid so they still have access
|
|
// when they logoff and logon again
|
|
//
|
|
|
|
psidUser = pSid;
|
|
bFreeSid = FALSE;
|
|
|
|
if (!psidUser) {
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to get user sid"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize system sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the admin sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
|
|
0, 0, 0, 0, &psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize admin sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the restricted sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_RESTRICTED_CODE_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize restricted sid. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for the ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (psidUser)) + (2 * GetLengthSid (psidSystem)) +
|
|
(2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidRestricted)) +
|
|
sizeof(ACL) +
|
|
(8 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pAcl) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize acl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add Aces for User, System, and Admin. Non-inheritable ACEs first
|
|
//
|
|
|
|
AceIndex = 0;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidUser)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_READ, psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Now the inheritable ACEs
|
|
//
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidUser)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for user. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for system. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for admin. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
AceIndex++;
|
|
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ, psidRestricted)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to add ace for restricted. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!GetAce(pAcl, AceIndex, &lpAceHeader)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to get ace (%d). Error = %d", AceIndex, GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to initialize security descriptor. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Failed to set security descriptor dacl. Error = %d", GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the root of the user's profile
|
|
//
|
|
|
|
Error = RegCreateKeyEx(HKEY_USERS,
|
|
lpKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL,
|
|
NULL,
|
|
&RootKey,
|
|
&dwDisp);
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to open root of user registry, error = %d", Error));
|
|
|
|
} else {
|
|
|
|
//
|
|
// Set the security descriptor on the key
|
|
//
|
|
|
|
Error = ApplySecurityToRegistryTree(RootKey, &sd);
|
|
|
|
|
|
if (Error == ERROR_SUCCESS) {
|
|
bRetVal = TRUE;
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((DM_WARNING, "SecureUserKey: Failed to apply security to registry key, error = %d", Error));
|
|
SetLastError(Error);
|
|
}
|
|
|
|
RegCloseKey(RootKey);
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
//
|
|
// Free the sids and acl
|
|
//
|
|
|
|
if (bFreeSid && psidUser) {
|
|
DeleteUserSid (psidUser);
|
|
}
|
|
|
|
if (psidRestricted) {
|
|
FreeSid(psidRestricted);
|
|
}
|
|
|
|
if (psidSystem) {
|
|
FreeSid(psidSystem);
|
|
}
|
|
|
|
if (psidAdmin) {
|
|
FreeSid(psidAdmin);
|
|
}
|
|
|
|
if (pAcl) {
|
|
GlobalFree (pAcl);
|
|
}
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DEBUGMSG ((DM_VERBOSE, "SecureUserKey: Leaving with a return value of %d", bRetVal));
|
|
|
|
|
|
return(bRetVal);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ProduceWFromA()
|
|
//
|
|
// Purpose: Creates a buffer for a Unicode string and copies
|
|
// the ANSI text into it (converting in the process)
|
|
//
|
|
// Parameters: pszA - ANSI string
|
|
//
|
|
//
|
|
// Return: Unicode pointer if successful
|
|
// NULL if an error occurs
|
|
//
|
|
// Comments: The caller needs to free this pointer.
|
|
//
|
|
//
|
|
// History: Date Author Comment
|
|
// 5/24/95 ericflo Ported
|
|
//
|
|
//*************************************************************
|
|
|
|
LPWSTR ProduceWFromA(LPCSTR pszA)
|
|
{
|
|
LPWSTR pszW;
|
|
int cch;
|
|
|
|
if (!pszA)
|
|
return (LPWSTR)pszA;
|
|
|
|
cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
|
|
|
|
if (cch == 0)
|
|
cch = 1;
|
|
|
|
pszW = LocalAlloc(LPTR, cch * sizeof(WCHAR));
|
|
|
|
if (pszW) {
|
|
if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, -1, pszW, cch)) {
|
|
LocalFree(pszW);
|
|
pszW = NULL;
|
|
}
|
|
}
|
|
|
|
return pszW;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// IsUserAnAdminMember()
|
|
//
|
|
// Purpose: Determines if the user is a member of the administrators group.
|
|
//
|
|
// Parameters: hToken - User's token
|
|
//
|
|
// Return: TRUE if user is a admin
|
|
// FALSE if not
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 7/25/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL IsUserAnAdminMember(HANDLE hToken)
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
NTSTATUS Status;
|
|
BOOL FoundAdmins = FALSE;
|
|
PSID AdminsDomainSid=NULL;
|
|
HANDLE hImpToken = NULL;
|
|
|
|
//
|
|
// Create Admins domain sid.
|
|
//
|
|
|
|
|
|
Status = RtlAllocateAndInitializeSid(
|
|
&authNT,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&AdminsDomainSid
|
|
);
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
//
|
|
// Test if user is in the Admins domain
|
|
//
|
|
|
|
if (!DuplicateTokenEx(hToken, TOKEN_IMPERSONATE | TOKEN_QUERY,
|
|
NULL, SecurityImpersonation, TokenImpersonation,
|
|
&hImpToken)) {
|
|
DEBUGMSG((DM_WARNING, "IsUserAnAdminMember: DuplicateTokenEx failed with error %d", GetLastError()));
|
|
FoundAdmins = FALSE;
|
|
hImpToken = NULL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!CheckTokenMembership(hImpToken, AdminsDomainSid, &FoundAdmins)) {
|
|
DEBUGMSG((DM_WARNING, "IsUserAnAdminmember: CheckTokenMembership failed for AdminsDomainSid with error %d", GetLastError()));
|
|
FoundAdmins = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Tidy up
|
|
//
|
|
|
|
Exit:
|
|
|
|
if (hImpToken)
|
|
CloseHandle(hImpToken);
|
|
|
|
if (AdminsDomainSid)
|
|
RtlFreeSid(AdminsDomainSid);
|
|
|
|
return(FoundAdmins);
|
|
}
|
|
|