|
|
//*************************************************************
// File name: profile.c
//
// Description: Fixes hard coded paths in the registry for
// special folder locations. Also fixes security
// on a few registry keys.
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1996
// All rights reserved
//
//*************************************************************
#include <windows.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <xpsp1res.h>
#include <userenv.h>
#include <userenvp.h>
#include <tchar.h>
#include "shmgdefs.h"
//*************************************************************
//
// 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
// 6/16/96 bobday Stolen directly from USERENV
//
//*************************************************************
DWORD ApplySecurityToRegistryTree(HKEY RootKey, PSECURITY_DESCRIPTOR pSD)
{ DWORD Error; DWORD SubKeyIndex; LPTSTR SubKeyName; HKEY SubKey; DWORD cchSubKeySize = MAX_PATH + 1;
//
// First apply security
//
Error = RegSetKeySecurity(RootKey, DACL_SECURITY_INFORMATION, pSD);
if (Error != ERROR_SUCCESS) { return Error; }
//
// Open each sub-key and apply security to its sub-tree
//
SubKeyIndex = 0;
SubKeyName = GlobalAlloc (GPTR, cchSubKeySize * sizeof(TCHAR));
if (!SubKeyName) { 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 {
}
break; }
//
// Open the sub-key
//
Error = RegOpenKeyEx(RootKey, SubKeyName, 0, WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL, &SubKey);
if (Error != ERROR_SUCCESS) { break; }
//
// Apply security to the sub-tree
//
Error = ApplySecurityToRegistryTree(SubKey, pSD);
//
// We're finished with the sub-key
//
RegCloseKey(SubKey);
//
// See if we set the security on the sub-tree successfully.
//
if (Error != ERROR_SUCCESS) { break; }
//
// Go enumerate the next sub-key
//
SubKeyIndex ++; }
GlobalFree (SubKeyName);
return Error;
}
//*************************************************************
//
// MakeKeyOrTreeSecure()
//
// Purpose: Sets the attributes on the registry key and possibly sub-keys
// such that Administrators and the OS can delete it and Everyone
// else has read permission only (OR general read/write access)
//
// Parameters: RootKey - Key to set security on
// fWrite - Allow write (or just read)
//
// Return: (BOOL) TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 11/6/95 ericflo Created
// 06/16/96 bobday Ported from MakeFileSecure in USERENV
//
//*************************************************************
BOOL MakeKeyOrTreeSecure (HKEY RootKey, BOOL fWrite) { SECURITY_DESCRIPTOR sd; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY; PACL pAcl = NULL; PSID psidSystem = NULL, psidAdmin = NULL, psidEveryone = NULL; DWORD cbAcl, aceIndex; ACE_HEADER * lpAceHeader; BOOL bRetVal = FALSE; DWORD Error; DWORD dwAccess;
if (fWrite) { dwAccess = KEY_ALL_ACCESS; } else { dwAccess = KEY_READ; }
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { 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)) { goto Exit; }
//
// Get the World sid
//
if (!AllocateAndInitializeSid(&authWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryone)) {
goto Exit; }
//
// Allocate space for the ACL
//
cbAcl = (3 * GetLengthSid (psidSystem)) + (3 * 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)) { goto Exit; }
//
// Add Aces. Non-inheritable ACEs first
//
aceIndex = 0; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidSystem)) { goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, KEY_ALL_ACCESS, psidAdmin)) { goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccess, psidEveryone)) { goto Exit; }
//
// Now the inheritable ACEs
//
if (fWrite) { dwAccess = GENERIC_ALL; } else { dwAccess = GENERIC_READ; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, dwAccess, psidEveryone)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { goto Exit; }
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { goto Exit; }
//
// Set the security
//
Error = ApplySecurityToRegistryTree(RootKey, &sd);
if (Error == ERROR_SUCCESS) { bRetVal = TRUE; }
Exit:
if (psidSystem) { FreeSid(psidSystem); }
if (psidAdmin) { FreeSid(psidAdmin); }
if (psidEveryone) { FreeSid(psidEveryone); }
if (pAcl) { GlobalFree (pAcl); }
return bRetVal; }
void FixWindowsProfileSecurity( void ) { HKEY hkeyWindows; HKEY hkeyShellExt; DWORD Error;
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows"), 0, WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL, &hkeyWindows);
if (Error == ERROR_SUCCESS) { MakeKeyOrTreeSecure(hkeyWindows, TRUE); RegCloseKey(hkeyWindows); }
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions"), 0, WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL, &hkeyShellExt); if (Error == ERROR_SUCCESS) { MakeKeyOrTreeSecure(hkeyShellExt, FALSE); RegCloseKey(hkeyShellExt); } }
void FixUserProfileSecurity( void ) { HKEY hkeyPolicies; DWORD Error;
Error = RegOpenKeyEx( HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies"), 0, WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL, &hkeyPolicies);
if (Error == ERROR_SUCCESS) { MakeKeyOrTreeSecure(hkeyPolicies, FALSE); RegCloseKey(hkeyPolicies); } }
void FixPoliciesSecurity( void ) { HKEY hkeyPolicies; DWORD Error, dwDisp;
Error = RegCreateKeyEx( HKEY_CURRENT_USER, TEXT("Software\\Policies"), 0, NULL, REG_OPTION_NON_VOLATILE, WRITE_DAC | KEY_ENUMERATE_SUB_KEYS | READ_CONTROL, NULL, &hkeyPolicies, &dwDisp);
if (Error == ERROR_SUCCESS) { MakeKeyOrTreeSecure(hkeyPolicies, FALSE); RegCloseKey(hkeyPolicies); } }
void SetSystemBitOnCAPIDir(void) { HRESULT hr; TCHAR szPath[MAX_PATH]; TCHAR szAppData[MAX_PATH]; DWORD FileAttributes;
if (S_OK == SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, szAppData)){
//
// It is better to use tcscpy and tcscat. This is just a temp fix and it is build with
// Unicode anyway. Not worth to include extra header file.
// We do not check error case here. This is just a best effort. If we got error, so what?
// MAX_PATH should be enough for these DIRs. Not worth to take care of \\?\ format.
//
lstrcpyn(szPath, szAppData, ARRAYSIZE(szPath)); StrCatBuff(szPath, TEXT("\\Microsoft\\Protect"), ARRAYSIZE(szPath)); FileAttributes = GetFileAttributes(szPath); if ((FileAttributes != -1) && ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) == 0)) { FileAttributes |= FILE_ATTRIBUTE_SYSTEM; SetFileAttributes(szPath, FileAttributes); }
lstrcpyn(szPath, szAppData, ARRAYSIZE(szPath)); StrCatBuff(szPath, TEXT("\\Microsoft\\Crypto"), ARRAYSIZE(szPath)); FileAttributes = GetFileAttributes(szPath); if ((FileAttributes != -1) && ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) == 0)) { FileAttributes |= FILE_ATTRIBUTE_SYSTEM; SetFileAttributes(szPath, FileAttributes); } }
}
void SetScreensaverOnFriendlyUI() { if (IsOS(OS_FRIENDLYLOGONUI) && IsOS(OS_FASTUSERSWITCHING)) { HKEY hkey;
if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"), 0, KEY_SET_VALUE, &hkey) == ERROR_SUCCESS) { TCHAR szTemp[MAX_PATH];
RegSetValueEx(hkey, TEXT("ScreenSaveActive"), 0, REG_SZ, (BYTE*)TEXT("1"), sizeof(TEXT("1"))); if (RegQueryValueEx(hkey, TEXT("SCRNSAVE.EXE"), NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { // if the user dosen't already have a screensaver set, then choose one for them!
if (ExpandEnvironmentStrings(TEXT("%SystemRoot%\\System32\\logon.scr"), szTemp, ARRAYSIZE(szTemp))) { RegSetValueEx(hkey, TEXT("SCRNSAVE.EXE"), 0, REG_SZ, (BYTE*)szTemp, (lstrlen(szTemp) + 1) * sizeof(TCHAR)); } }
RegCloseKey(hkey); } } }
#define OTHERSIDS_EVERYONE 1
#define OTHERSIDS_POWERUSERS 2
BOOL MakeFileSecure (LPTSTR lpFile, DWORD dwOtherSids) { SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY authWORLD = SECURITY_WORLD_SID_AUTHORITY; PACL pAcl = NULL; PSID psidSystem = NULL, psidAdmin = NULL, psidUsers = NULL, psidPowerUsers = NULL; PSID psidEveryOne = NULL; DWORD cbAcl, aceIndex; ACE_HEADER * lpAceHeader; BOOL bRetVal = FALSE; BOOL bAddPowerUsersAce=TRUE; BOOL bAddEveryOneAce=FALSE; DWORD dwAccMask;
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &psidSystem)) { 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)) { goto Exit; }
//
// Get the users sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &psidUsers)) {
goto Exit; }
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidSystem)) + (2 * GetLengthSid (psidAdmin)) + (2 * GetLengthSid (psidUsers)) + sizeof(ACL) + (6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
//
// Get the power users sid, if required.
// Don't fail if you don't get because it might not be available on DCs??
//
bAddPowerUsersAce = TRUE; if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0, 0, &psidPowerUsers)) {
bAddPowerUsersAce = FALSE; }
if (bAddPowerUsersAce) cbAcl += (2 * GetLengthSid (psidPowerUsers)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
//
// Get the EveryOne sid, if required.
//
if (dwOtherSids & OTHERSIDS_EVERYONE) { bAddEveryOneAce = TRUE; if (!AllocateAndInitializeSid(&authWORLD, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryOne)) {
goto Exit; } }
if (bAddEveryOneAce) cbAcl += (2 * GetLengthSid (psidEveryOne)) + (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl); if (!pAcl) { goto Exit; }
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) { goto Exit; }
//
// Add Aces. Non-inheritable ACEs first
//
aceIndex = 0; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) { goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) { goto Exit; }
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidUsers)) { goto Exit; }
if (bAddPowerUsersAce) {
//
// By default give read permissions, otherwise give modify permissions
//
dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)): (GENERIC_READ | GENERIC_EXECUTE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*dwAccMask,*/ psidPowerUsers)) { goto Exit; } }
if (bAddEveryOneAce) { aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidEveryOne)) { goto Exit; } }
//
// Now the inheritable ACEs
//
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++; if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidUsers)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
if (bAddPowerUsersAce) { aceIndex++; dwAccMask = (dwOtherSids & OTHERSIDS_POWERUSERS) ? (FILE_ALL_ACCESS ^ (WRITE_DAC | WRITE_OWNER)): (GENERIC_READ | GENERIC_EXECUTE);
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*dwAccMask,*/ psidPowerUsers)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); }
if (bAddEveryOneAce) { aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, /*GENERIC_READ | GENERIC_EXECUTE,*/ psidEveryOne)) { goto Exit; }
if (!GetAce(pAcl, aceIndex, &lpAceHeader)) { goto Exit; }
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); }
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { goto Exit; }
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { goto Exit; }
//
// Set the security
//
if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, &sd)) { bRetVal = TRUE; } else { }
Exit:
if (psidSystem) { FreeSid(psidSystem); }
if (psidAdmin) { FreeSid(psidAdmin); }
if (psidUsers) { FreeSid(psidUsers); }
if ((bAddPowerUsersAce) && (psidPowerUsers)) { FreeSid(psidPowerUsers); }
if ((bAddEveryOneAce) && (psidEveryOne)) { FreeSid(psidEveryOne); }
if (pAcl) { GlobalFree (pAcl); }
return bRetVal; }
#ifdef SHMG_DBG
void SHMGLogErrMsg(char *szErrMsg, DWORD dwError) { DWORD dwBytesWritten = 0; char szMsg[256]; static HANDLE hLogFile = 0;
if (!hLogFile) { hLogFile = CreateFile(_T("shmgrate.log"), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ); } sprintf(szMsg, "%s : (%X)\r\n", szErrMsg, dwError); WriteFile(hLogFile, szMsg, strlen(szMsg), &dwBytesWritten, 0); }
#endif
void FixHtmlHelp( void ) { TCHAR AppDataPath[MAX_PATH*2]; TCHAR HtmlHelpPath[MAX_PATH];
SHMGLogErrMsg("FixHtmlHelp Called",0); if (SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, AppDataPath) == S_OK && LoadString( GetModuleHandle(NULL), IDS_HTML_HELP_DIR, HtmlHelpPath, sizeof(HtmlHelpPath)/sizeof(WCHAR) ) > 0) { _tcscat( AppDataPath, HtmlHelpPath ); if (CreateDirectory( AppDataPath, NULL )) { if (!MakeFileSecure(AppDataPath,OTHERSIDS_EVERYONE|OTHERSIDS_POWERUSERS)) SHMGLogErrMsg("Could not apply security attributes", 0); } else SHMGLogErrMsg("Could not create the directory", GetLastError()); } else SHMGLogErrMsg("Could not get APPDATA path", GetLastError()); }
// Add the SP1 "Configure Programs" shortcut to the common start menu
// On a clean install, this is handled by syssetup.inf, but on a
// RTM->SP1 upgrade, we need to do it by hand.
//
void AddConfigurePrograms() { if (!IsOS(OS_ANYSERVER)) { TCHAR szPath[MAX_PATH];
if (GetSystemDirectory(szPath, ARRAYSIZE(szPath)) && PathAppend(szPath, TEXT("XPSP1RES.DLL"))) { HINSTANCE hinstSp1 = LoadLibraryEx(szPath, NULL, LOAD_LIBRARY_AS_DATAFILE); if (hinstSp1) { TCHAR szTitle[MAX_PATH]; LoadString(hinstSp1, IDS_APPWIZ_CONFIGUREPROGRAMS, szTitle, ARRAYSIZE(szTitle)); CreateLinkFile(CSIDL_COMMON_STARTMENU, NULL, szTitle, TEXT("control.exe appwiz.cpl,,3"), TEXT("moricons.dll"), -114, NULL, 0, SW_SHOWNORMAL, TEXT("@xpsp1res.dll,-10078")); if (S_OK == SHGetFolderPath(NULL, CSIDL_COMMON_STARTMENU, NULL, SHGFP_TYPE_CURRENT, szPath) && PathAppend(szPath, szTitle) && PathAddExtension(szPath, TEXT(".lnk"))) { SHSetLocalizedName(szPath, L"xpsp1res.dll", IDS_APPWIZ_CONFIGUREPROGRAMS); } } FreeLibrary(hinstSp1); } } }
|