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.
4476 lines
137 KiB
4476 lines
137 KiB
//*************************************************************
|
|
//
|
|
// SETUP.C - API's used by setup to create groups/items
|
|
//
|
|
// Microsoft Confidential
|
|
// Copyright (c) Microsoft Corporation 1995
|
|
// All rights reserved
|
|
//
|
|
//*************************************************************
|
|
|
|
#include <uenv.h>
|
|
#include <sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor
|
|
#include <aclapi.h>
|
|
#include "strsafe.h"
|
|
|
|
|
|
// See ConvertStringSecurityDescriptorToSecurityDescriptor documentation
|
|
// for a description of the string security descriptor format.
|
|
//
|
|
// These ACLs are setup to allow
|
|
// System, Administrators, Creator-Owner: Full Control
|
|
// Power Users: Modify (RWXD)
|
|
// Users: Read (RX)
|
|
// Users: Write (folders only)
|
|
//
|
|
// The combination of "Users: Write (folders only)" and the Creator-Owner ACE
|
|
// means that restricted users can create subfolders and files, and have full
|
|
// control to files that they create, but they cannot modify or delete files
|
|
// created by someone else.
|
|
|
|
const TCHAR c_szCommonDocumentsACL[] = TEXT("D:P(A;CIOI;GA;;;SY)(A;CIOI;GA;;;BA)(A;CIOIIO;GA;;;CO)(A;CIOI;GRGWGXSD;;;PU)(A;CIOI;GRGX;;;BU)(A;CI;0x116;;;BU)");
|
|
const TCHAR c_szCommonAppDataACL[] = TEXT("D:P(A;CIOI;GA;;;SY)(A;CIOI;GA;;;BA)(A;CIOIIO;GA;;;CO)(A;CIOI;GRGWGXSD;;;PU)(A;CIOI;GRGX;;;BU)(A;CI;0x116;;;BU)");
|
|
|
|
const TCHAR c_szProfileEnvName[] = TEXT("PROFILES");
|
|
|
|
BOOL PrependPath(LPCTSTR szFile, LPTSTR szResult, UINT cchResult);
|
|
BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
|
|
LPTSTR lpProfileName);
|
|
void HideSpecialProfiles(void);
|
|
void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath);
|
|
|
|
HRESULT ReaclProfileListEntries();
|
|
HRESULT CallFaxServiceAPI();
|
|
HRESULT PrepareEnvironmentVariables();
|
|
HRESULT SecureCommonProfiles();
|
|
HRESULT SecurePerUserProfiles();
|
|
|
|
|
|
//
|
|
// Tell whether the setup is a clean install
|
|
//
|
|
|
|
static BOOL g_bCleanInstall;
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateGroup()
|
|
//
|
|
// Purpose: Creates a program group (sub-directory)
|
|
//
|
|
// Parameters: lpGroupName - Name of group
|
|
// bCommonGroup - Common or Personal group
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/08/95 ericflo Created
|
|
// 3/29/00 AlexArm Split into CreateGroup
|
|
// and CreateGroupEx
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
|
|
{
|
|
//
|
|
// Call CreateGroupEx with no name.
|
|
//
|
|
return CreateGroupEx( lpGroupName, bCommonGroup, NULL, 0 );
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateGroupEx()
|
|
//
|
|
// Purpose: Creates a program group (sub-directory) and sets
|
|
// the localized name for the program group
|
|
//
|
|
// Parameters: lpGroupName - Name of group
|
|
// bCommonGroup - Common or Personal group
|
|
// lpResourceModuleName - Name of the resource module.
|
|
// uResourceID - Resource ID for the MUI display name.
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/08/95 ericflo Created
|
|
// 3/29/00 AlexArm Split into CreateGroup
|
|
// and CreateGroupEx
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateGroupEx(LPCWSTR lpGroupName, BOOL bCommonGroup,
|
|
LPCWSTR lpResourceModuleName, UINT uResourceID)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
LPTSTR lpAdjustedGroupName;
|
|
int csidl;
|
|
PSHELL32_API pShell32Api;
|
|
DWORD dwResult;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Validate parameters
|
|
//
|
|
|
|
if (!lpGroupName || !(*lpGroupName)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: Failing due to NULL group name.")));
|
|
return FALSE;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Entering with <%s>."), lpGroupName));
|
|
|
|
|
|
if ( ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Extract the CSIDL (if any) from lpGroupName
|
|
//
|
|
|
|
csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
|
|
|
|
if (-1 != csidl)
|
|
{
|
|
//
|
|
// Use this csidl
|
|
// WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE,
|
|
TEXT("CreateGroupEx: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
|
|
csidl));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Default to CSIDL_..._PROGRAMS
|
|
//
|
|
csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
|
|
}
|
|
|
|
//
|
|
// Get the programs directory
|
|
//
|
|
|
|
if (!GetSpecialFolderPath (csidl, szDirectory)) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Now append the requested directory
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CheckSlashEx failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedGroupName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: StringCchCopy failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Create the group (directory)
|
|
//
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling CreatedNestedDirectory with <%s>"),
|
|
szDirectory));
|
|
|
|
if (!CreateNestedDirectory(szDirectory, NULL)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CreatedNestedDirectory failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the localized name is specified, set it.
|
|
//
|
|
if (lpResourceModuleName != NULL) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Calling SHSetLocalizedName.")));
|
|
dwResult = pShell32Api->pfnShSetLocalizedName(szDirectory,
|
|
lpResourceModuleName, uResourceID);
|
|
if (dwResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: SHSetLocalizedName failed <0x%x>."),
|
|
dwResult));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
pShell32Api->pfnShChangeNotify (SHCNE_MKDIR, SHCNF_PATH, szDirectory, NULL);
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateGroupEx: Leaving successfully.")));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeleteGroup()
|
|
//
|
|
// Purpose: Deletes a program group (sub-directory)
|
|
//
|
|
// Parameters: lpGroupName - Name of group
|
|
// bCommonGroup - Common or Personal group
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/10/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI DeleteGroup(LPCTSTR lpGroupName, BOOL bCommonGroup)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
LPTSTR lpAdjustedGroupName;
|
|
int csidl;
|
|
PSHELL32_API pShell32Api;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Validate parameters
|
|
//
|
|
|
|
if (!lpGroupName || !(*lpGroupName)) {
|
|
DebugMsg((DM_WARNING, TEXT("DeleteGroup: Failing due to NULL group name.")));
|
|
return FALSE;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Entering with <%s>."), lpGroupName));
|
|
|
|
if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Extract the CSIDL (if any) from lpGroupName
|
|
//
|
|
|
|
csidl = ExtractCSIDL(lpGroupName, &lpAdjustedGroupName);
|
|
|
|
if (-1 != csidl)
|
|
{
|
|
//
|
|
// Use this csidl
|
|
// WARNING: if a CSIDL is provided, the bCommonGroup flag is meaningless
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE,
|
|
TEXT("DeleteGroup: CSIDL = <0x%x> contained in lpGroupName replaces csidl."),
|
|
csidl));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Default to CSIDL_..._PROGRAMS
|
|
//
|
|
|
|
csidl = bCommonGroup ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS;
|
|
}
|
|
|
|
//
|
|
// Get the programs directory
|
|
//
|
|
|
|
if (!GetSpecialFolderPath (csidl, szDirectory)) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Now append the requested directory
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: CheckSlashEx failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedGroupName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateGroupEx: StringCchCopy failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Delete the group (directory)
|
|
//
|
|
|
|
if (!Delnode(szDirectory)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Delnode failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Success
|
|
//
|
|
pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szDirectory, NULL);
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteGroup: Leaving successfully.")));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateLinkFile()
|
|
//
|
|
// Purpose: Creates a link file in the specified directory
|
|
//
|
|
// Parameters: cidl - CSIDL_ of a special folder
|
|
// lpSubDirectory - Subdirectory of special folder
|
|
// lpFileName - File name of item
|
|
// lpCommandLine - Command line (including args)
|
|
// lpIconPath - Icon path (can be NULL)
|
|
// iIconIndex - Index of icon in icon path
|
|
// lpWorkingDir - Working directory
|
|
// wHotKey - Hot key
|
|
// iShowCmd - ShowWindow flag
|
|
// lpDescription - Description of the item
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 3/26/98 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateLinkFile(INT csidl, LPCTSTR lpSubDirectory,
|
|
LPCTSTR lpFileName, LPCTSTR lpCommandLine,
|
|
LPCTSTR lpIconPath, int iIconIndex,
|
|
LPCTSTR lpWorkingDirectory, WORD wHotKey,
|
|
int iShowCmd, LPCTSTR lpDescription)
|
|
{
|
|
return CreateLinkFileEx(csidl, lpSubDirectory, lpFileName, lpCommandLine,
|
|
lpIconPath, iIconIndex, lpWorkingDirectory, wHotKey,
|
|
iShowCmd, lpDescription, NULL, 0);
|
|
}
|
|
//*************************************************************
|
|
//
|
|
// CreateLinkFileEx()
|
|
//
|
|
// Purpose: Creates a link file in the specified directory
|
|
//
|
|
// Parameters: cidl - CSIDL_ of a special folder
|
|
// lpSubDirectory - Subdirectory of special folder
|
|
// lpFileName - File name of item
|
|
// lpCommandLine - Command line (including args)
|
|
// lpIconPath - Icon path (can be NULL)
|
|
// iIconIndex - Index of icon in icon path
|
|
// lpWorkingDir - Working directory
|
|
// wHotKey - Hot key
|
|
// iShowCmd - ShowWindow flag
|
|
// lpDescription - Description of the item
|
|
// lpResourceModuleName - Name of the resource module.
|
|
// uResourceID - Resource ID for the MUI display name.
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 3/26/98 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
|
|
BOOL WINAPI CreateLinkFileEx(INT csidl, LPCTSTR lpSubDirectory,
|
|
LPCTSTR lpFileName, LPCTSTR lpCommandLine,
|
|
LPCTSTR lpIconPath, int iIconIndex,
|
|
LPCTSTR lpWorkingDirectory, WORD wHotKey,
|
|
int iShowCmd, LPCTSTR lpDescription,
|
|
LPCWSTR lpResourceModuleName, UINT uResourceID)
|
|
{
|
|
TCHAR szItem[MAX_PATH];
|
|
TCHAR szArgs[MAX_PATH];
|
|
TCHAR szLinkName[MAX_PATH];
|
|
TCHAR szPath[MAX_PATH];
|
|
LPTSTR lpArgs, lpEnd;
|
|
IShellLink *psl;
|
|
IPersistFile *ppf;
|
|
BOOL bRetVal = FALSE;
|
|
HINSTANCE hInstOLE32 = NULL;
|
|
PFNCOCREATEINSTANCE pfnCoCreateInstance;
|
|
PFNCOINITIALIZE pfnCoInitialize;
|
|
PFNCOUNINITIALIZE pfnCoUninitialize;
|
|
LPTSTR lpAdjustedSubDir = NULL;
|
|
PSHELL32_API pShell32Api;
|
|
PSHLWAPI_API pShlwapiApi;
|
|
DWORD dwResult;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
#if DBG
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Entering.")));
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: csidl = <0x%x>."), csidl));
|
|
if (lpSubDirectory && *lpSubDirectory) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpSubDirectory = <%s>."), lpSubDirectory));
|
|
}
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpFileName = <%s>."), lpFileName));
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpCommandLine = <%s>."), lpCommandLine));
|
|
|
|
if (lpIconPath) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpIconPath = <%s>."), lpIconPath));
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iIconIndex = <%d>."), iIconIndex));
|
|
}
|
|
|
|
if (lpWorkingDirectory) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpWorkingDirectory = <%s>."), lpWorkingDirectory));
|
|
} else {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null working directory. Setting to %%HOMEDRIVE%%%%HOMEPATH%%")));
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: wHotKey = <%d>."), wHotKey));
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: iShowCmd = <%d>."), iShowCmd));
|
|
|
|
if (lpDescription) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: lpDescription = <%s>."), lpDescription));
|
|
} else {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Null description.")));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Load a few functions we need
|
|
//
|
|
|
|
hInstOLE32 = LoadLibrary (TEXT("ole32.dll"));
|
|
|
|
if (!hInstOLE32) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to load ole32 with %d."),
|
|
GetLastError()));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
pfnCoCreateInstance = (PFNCOCREATEINSTANCE)GetProcAddress (hInstOLE32,
|
|
"CoCreateInstance");
|
|
|
|
if (!pfnCoCreateInstance) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoCreateInstance with %d."),
|
|
GetLastError()));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
pfnCoInitialize = (PFNCOINITIALIZE)GetProcAddress (hInstOLE32,
|
|
"CoInitialize");
|
|
|
|
if (!pfnCoInitialize) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoInitialize with %d."),
|
|
GetLastError()));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
pfnCoUninitialize = (PFNCOUNINITIALIZE)GetProcAddress (hInstOLE32,
|
|
"CoUninitialize");
|
|
|
|
if (!pfnCoUninitialize) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to find CoUninitialize with %d."),
|
|
GetLastError()));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
pShlwapiApi = LoadShlwapiApi();
|
|
|
|
if ( !pShlwapiApi ) {
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
//
|
|
// Get the special folder directory
|
|
// First check if there is a CSIDL in the subdirectory
|
|
//
|
|
|
|
if (lpSubDirectory && *lpSubDirectory) {
|
|
|
|
int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
|
|
|
|
if (-1 != csidl2)
|
|
{
|
|
csidl = csidl2;
|
|
DebugMsg((DM_VERBOSE,
|
|
TEXT("CreateLinkFileEx: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
|
|
csidl));
|
|
}
|
|
}
|
|
|
|
szLinkName[0] = TEXT('\0');
|
|
if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to get profiles directory.")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
if (lpAdjustedSubDir && *lpAdjustedSubDir) {
|
|
|
|
if (szLinkName[0] != TEXT('\0')) {
|
|
lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: CheckSlashEx failed")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
} else {
|
|
lpEnd = szLinkName;
|
|
cchEnd = ARRAYSIZE(szLinkName);
|
|
}
|
|
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedSubDir);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCopy failed")));
|
|
goto ExitNoFree;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Create the target directory
|
|
//
|
|
|
|
if (!CreateNestedDirectory(szLinkName, NULL)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Failed to create subdirectory <%s> with %d"),
|
|
szLinkName, GetLastError()));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
//
|
|
// Now tack on the filename and extension.
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: CheckSlashEx failed")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpFileName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCopy failed")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
hr = StringCchCat (lpEnd, cchEnd, c_szLNK);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: StringCchCat failed")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Split the command line into the executable name
|
|
// and arguments.
|
|
//
|
|
|
|
StringCchCopy (szItem, ARRAYSIZE(szItem), lpCommandLine);
|
|
|
|
lpArgs = pShlwapiApi->pfnPathGetArgs(szItem);
|
|
|
|
if (*lpArgs) {
|
|
StringCchCopy (szArgs, ARRAYSIZE(szArgs), lpArgs);
|
|
|
|
lpArgs--;
|
|
while (*lpArgs == TEXT(' ')) {
|
|
lpArgs--;
|
|
}
|
|
lpArgs++;
|
|
*lpArgs = TEXT('\0');
|
|
} else {
|
|
szArgs[0] = TEXT('\0');
|
|
}
|
|
|
|
pShlwapiApi->pfnPathUnquoteSpaces (szItem);
|
|
|
|
|
|
//
|
|
// Create an IShellLink object
|
|
//
|
|
|
|
pfnCoInitialize(NULL);
|
|
|
|
if (FAILED(pfnCoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IShellLink, (LPVOID*)&psl)))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: Could not create instance of IShellLink .")));
|
|
goto ExitNoFree;
|
|
}
|
|
|
|
|
|
//
|
|
// Query for IPersistFile
|
|
//
|
|
|
|
if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateLinkFileEx: QueryInterface of IShellLink failed.")));
|
|
goto ExitFreePSL;
|
|
}
|
|
|
|
//
|
|
// Set the item information
|
|
//
|
|
|
|
if (lpDescription) {
|
|
psl->lpVtbl->SetDescription(psl, lpDescription);
|
|
}
|
|
|
|
PrependPath(szItem, szPath, ARRAYSIZE(szPath));
|
|
psl->lpVtbl->SetPath(psl, szPath);
|
|
|
|
|
|
psl->lpVtbl->SetArguments(psl, szArgs);
|
|
if (lpWorkingDirectory) {
|
|
psl->lpVtbl->SetWorkingDirectory(psl, lpWorkingDirectory);
|
|
} else {
|
|
psl->lpVtbl->SetWorkingDirectory(psl, TEXT("%HOMEDRIVE%%HOMEPATH%"));
|
|
}
|
|
|
|
PrependPath(lpIconPath, szPath, ARRAYSIZE(szPath));
|
|
psl->lpVtbl->SetIconLocation(psl, szPath, iIconIndex);
|
|
|
|
psl->lpVtbl->SetHotkey(psl, wHotKey);
|
|
psl->lpVtbl->SetShowCmd(psl, iShowCmd);
|
|
|
|
|
|
//
|
|
// If the localized name is specified, set it.
|
|
//
|
|
|
|
if (lpResourceModuleName != NULL) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Calling SHSetLocalizedName on link <%s>."), szLinkName));
|
|
ppf->lpVtbl->Save(ppf, szLinkName, TRUE);
|
|
dwResult = pShell32Api->pfnShSetLocalizedName(szLinkName,
|
|
lpResourceModuleName, uResourceID);
|
|
if (dwResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: SHSetLocalizedName failed <0x%x>."),
|
|
dwResult));
|
|
goto ExitFreePSL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save the item to disk
|
|
//
|
|
|
|
bRetVal = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
|
|
|
|
if (bRetVal) {
|
|
pShell32Api->pfnShChangeNotify (SHCNE_CREATE, SHCNF_PATH, szLinkName, NULL);
|
|
}
|
|
|
|
//
|
|
// Release the IPersistFile object
|
|
//
|
|
|
|
ppf->lpVtbl->Release(ppf);
|
|
|
|
|
|
ExitFreePSL:
|
|
|
|
//
|
|
// Release the IShellLink object
|
|
//
|
|
|
|
psl->lpVtbl->Release(psl);
|
|
|
|
pfnCoUninitialize();
|
|
|
|
ExitNoFree:
|
|
|
|
if (hInstOLE32) {
|
|
FreeLibrary (hInstOLE32);
|
|
}
|
|
|
|
//
|
|
// Finished.
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateLinkFileEx: Leaving with status of %d."), bRetVal));
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// DeleteLinkFile()
|
|
//
|
|
// Purpose: Deletes the specified link file
|
|
//
|
|
// Parameters: csidl - CSIDL of a special folder
|
|
// lpSubDirectory - Subdirectory of special folder
|
|
// lpFileName - File name of item
|
|
// bDeleteSubDirectory - Delete the subdirectory if possible
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 3/26/98 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI DeleteLinkFile(INT csidl, LPCTSTR lpSubDirectory,
|
|
LPCTSTR lpFileName, BOOL bDeleteSubDirectory)
|
|
{
|
|
TCHAR szLinkName[MAX_PATH];
|
|
LPTSTR lpEnd;
|
|
LPTSTR lpAdjustedSubDir = NULL;
|
|
PSHELL32_API pShell32Api;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
#if DBG
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Entering.")));
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: csidl = 0x%x."), csidl));
|
|
if (lpSubDirectory && *lpSubDirectory) {
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpSubDirectory = <%s>."), lpSubDirectory));
|
|
}
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: lpFileName = <%s>."), lpFileName));
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: bDeleteSubDirectory = %d."), bDeleteSubDirectory));
|
|
|
|
#endif
|
|
|
|
if (ERROR_SUCCESS != LoadShell32Api( &pShell32Api ) ) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the special folder directory
|
|
// First check if there is a CSIDL in the subdirectory
|
|
//
|
|
|
|
if (lpSubDirectory && *lpSubDirectory) {
|
|
|
|
int csidl2 = ExtractCSIDL(lpSubDirectory, &lpAdjustedSubDir);
|
|
|
|
if (-1 != csidl2)
|
|
{
|
|
csidl = csidl2;
|
|
DebugMsg((DM_VERBOSE,
|
|
TEXT("CreateLinkFile: CSIDL = <0x%x> contained in lpSubDirectory replaces csidl."),
|
|
csidl));
|
|
}
|
|
}
|
|
|
|
szLinkName[0] = TEXT('\0');
|
|
if (csidl && !GetSpecialFolderPath (csidl, szLinkName)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpAdjustedSubDir && *lpAdjustedSubDir) {
|
|
|
|
if (szLinkName[0] != TEXT('\0')) {
|
|
lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: CheckSlashEx failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
} else {
|
|
lpEnd = szLinkName;
|
|
cchEnd = ARRAYSIZE(szLinkName);
|
|
}
|
|
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpAdjustedSubDir);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCopy failed")));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now tack on the filename and extension.
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szLinkName, ARRAYSIZE(szLinkName), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: CheckSlashEx failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, lpFileName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCopy failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCat (lpEnd, cchEnd, c_szLNK);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DeleteLinkFile: StringCchCat failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Delete the file
|
|
//
|
|
|
|
if (!DeleteFile (szLinkName)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Failed to delete <%s>. Error = %d"),
|
|
szLinkName, GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
pShell32Api->pfnShChangeNotify (SHCNE_DELETE, SHCNF_PATH, szLinkName, NULL);
|
|
|
|
//
|
|
// Delete the subdirectory if appropriate (and possible).
|
|
//
|
|
|
|
if (bDeleteSubDirectory) {
|
|
*(lpEnd-1) = TEXT('\0');
|
|
if (RemoveDirectory(szLinkName)) {
|
|
pShell32Api->pfnShChangeNotify (SHCNE_RMDIR, SHCNF_PATH, szLinkName, NULL);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DeleteLinkFile: Leaving successfully.")));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// PrependPath()
|
|
//
|
|
// Purpose: Expands the given filename to have %systemroot%
|
|
// if appropriate
|
|
//
|
|
// Parameters: lpFile - File to check
|
|
// lpResult - Result buffer (MAX_PATH chars in size)
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/11/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL PrependPath(LPCTSTR lpFile, LPTSTR lpResult, UINT cchResult)
|
|
{
|
|
TCHAR szReturn [MAX_PATH];
|
|
LPTSTR lpFileName;
|
|
DWORD dwSysLen;
|
|
|
|
|
|
//
|
|
// Verbose Output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("PrependPath: Entering with <%s>"),
|
|
lpFile ? lpFile : TEXT("NULL")));
|
|
|
|
|
|
if (!lpFile || !*lpFile) {
|
|
DebugMsg((DM_VERBOSE, TEXT("PrependPath: lpFile is NULL, setting lpResult to a null string")));
|
|
*lpResult = TEXT('\0');
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Call SearchPath to find the filename
|
|
//
|
|
|
|
if (!SearchPath (NULL, lpFile, TEXT(".exe"), MAX_PATH, szReturn, &lpFileName)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("PrependPath: SearchPath failed with error %d. Using input string"), GetLastError()));
|
|
StringCchCopy (lpResult, cchResult, lpFile);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
UnExpandSysRoot(szReturn, lpResult, cchResult);
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("PrependPath: Leaving with <%s>"), lpResult));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// SetFilePermissions()
|
|
//
|
|
// Purpose: Sets the given permissions on a file or directory
|
|
//
|
|
// Parameters: lpFile - File to set security on
|
|
// pszSD - String security descriptor
|
|
//
|
|
// Return: (BOOL) TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 01/25/2001 jeffreys Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL SetFilePermissions(LPCTSTR lpFile, LPCTSTR pszSD)
|
|
{
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
BOOL bRetVal = FALSE;
|
|
|
|
if (ConvertStringSecurityDescriptorToSecurityDescriptor(pszSD, SDDL_REVISION, &pSD, NULL) && pSD)
|
|
{
|
|
//
|
|
// Set the security
|
|
//
|
|
if (SetFileSecurity (lpFile, DACL_SECURITY_INFORMATION, pSD))
|
|
{
|
|
bRetVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SetFilePermissions: SetFileSecurity failed. Error = %d"), GetLastError()));
|
|
}
|
|
|
|
LocalFree(pSD);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SetFilePermissions: ConvertStringSDToSD failed. Error = %d"), GetLastError()));
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ConvertCommonGroups()
|
|
//
|
|
// Purpose: Calls grpconv.exe to convert progman common groups
|
|
// to Explorer common groups, and create floppy links.
|
|
//
|
|
// NT 4 appended " (Common)" to the common groups. For
|
|
// NT 5, we are going to remove this tag.
|
|
//
|
|
// Parameters: none
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 10/1/95 ericflo Created
|
|
// 12/5/96 ericflo Remove common tag
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL ConvertCommonGroups (void)
|
|
{
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION ProcessInformation;
|
|
BOOL Result;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
TCHAR szBuffer2[MAX_PATH];
|
|
DWORD dwType, dwSize, dwConvert;
|
|
BOOL bRunGrpConv = TRUE;
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
HANDLE hFile;
|
|
WIN32_FIND_DATA fd;
|
|
TCHAR szCommon[30] = {0};
|
|
UINT cchCommon, cchFileName;
|
|
LPTSTR lpTag, lpEnd, lpEnd2;
|
|
UINT cchEnd, cchEnd2;
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Entering.")));
|
|
|
|
|
|
//
|
|
// Check if we have run grpconv before.
|
|
//
|
|
|
|
lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
TEXT("Software\\Program Groups"),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(dwConvert);
|
|
|
|
lResult = RegQueryValueEx (hKey,
|
|
TEXT("ConvertedToLinks"),
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&dwConvert,
|
|
&dwSize);
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// If dwConvert is 1, then grpconv has run before.
|
|
// Don't run it again.
|
|
//
|
|
|
|
if (dwConvert) {
|
|
bRunGrpConv = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now set the value to prevent grpconv from running in the future
|
|
//
|
|
|
|
dwConvert = 1;
|
|
RegSetValueEx (hKey,
|
|
TEXT("ConvertedToLinks"),
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwConvert,
|
|
sizeof(dwConvert));
|
|
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
if (bRunGrpConv) {
|
|
|
|
//
|
|
// Initialize process startup info
|
|
//
|
|
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.lpReserved = NULL;
|
|
si.lpDesktop = NULL;
|
|
si.lpTitle = NULL;
|
|
si.dwFlags = 0;
|
|
si.lpReserved2 = NULL;
|
|
si.cbReserved2 = 0;
|
|
|
|
|
|
//
|
|
// Spawn grpconv
|
|
//
|
|
|
|
StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), TEXT("grpconv -n"));
|
|
|
|
Result = CreateProcess(
|
|
NULL,
|
|
szBuffer,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&ProcessInformation
|
|
);
|
|
|
|
if (!Result) {
|
|
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: grpconv failed to start due to error %d."), GetLastError()));
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Wait for up to 2 minutes
|
|
//
|
|
|
|
WaitForSingleObject(ProcessInformation.hProcess, 120000);
|
|
|
|
//
|
|
// Close our handles to the process and thread
|
|
//
|
|
|
|
CloseHandle(ProcessInformation.hProcess);
|
|
CloseHandle(ProcessInformation.hThread);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Loop through all the program groups in the All Users profile
|
|
// and remove the " (Common)" tag.
|
|
//
|
|
|
|
LoadString (g_hDllInstance, IDS_COMMON, szCommon, 30);
|
|
cchCommon = lstrlen (szCommon);
|
|
|
|
if (!GetSpecialFolderPath (CSIDL_COMMON_PROGRAMS, szBuffer2)) {
|
|
return FALSE;
|
|
}
|
|
StringCchCopy (szBuffer, ARRAYSIZE(szBuffer), szBuffer2);
|
|
|
|
lpEnd = CheckSlashEx (szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
|
|
lpEnd2 = CheckSlashEx (szBuffer2, ARRAYSIZE(szBuffer2), &cchEnd2);
|
|
if (!lpEnd || !lpEnd2)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: CheckSlashEx failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_szStarDotStar);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
|
|
return FALSE;
|
|
}
|
|
|
|
hFile = FindFirstFile (szBuffer, &fd);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
|
|
|
do {
|
|
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
cchFileName = lstrlen (fd.cFileName);
|
|
|
|
if (cchFileName > cchCommon) {
|
|
lpTag = fd.cFileName + cchFileName - cchCommon;
|
|
|
|
if (!lstrcmpi(lpTag, szCommon)) {
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, fd.cFileName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
|
|
continue;
|
|
}
|
|
*lpTag = TEXT('\0');
|
|
hr = StringCchCopy (lpEnd2, cchEnd2, fd.cFileName);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ConvertCommonGroups: StringCchCopy failed.")));
|
|
continue;
|
|
}
|
|
|
|
if (MoveFileEx (szBuffer, szBuffer2, MOVEFILE_REPLACE_EXISTING)) {
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Successfully changed group name:")));
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
|
|
|
|
} else {
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Failed to change group name with error %d."), GetLastError()));
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Orginial: %s"), szBuffer));
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: New: %s"), szBuffer2));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (FindNextFile(hFile, &fd));
|
|
|
|
FindClose (hFile);
|
|
}
|
|
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ConvertCommonGroups: Leaving Successfully.")));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// DetermineProfilesLocation()
|
|
//
|
|
// Purpose: Determines if the profiles directory
|
|
// should be in the old NT4 location or
|
|
// the new NT5 location
|
|
//
|
|
// Parameters: none
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI DetermineProfilesLocation (BOOL bCleanInstall)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
TCHAR szDest[MAX_PATH];
|
|
PTSTR szCurDest;
|
|
PCTSTR szLookAhead;
|
|
WIN32_FILE_ATTRIBUTE_DATA fad;
|
|
DWORD dwSize, dwDisp;
|
|
HKEY hKey;
|
|
LPTSTR lpEnd;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Save the clean install flag
|
|
//
|
|
|
|
g_bCleanInstall = bCleanInstall;
|
|
|
|
//
|
|
// First, try to delete the previous userenv logs
|
|
//
|
|
|
|
DeletePreviousLogFiles();
|
|
|
|
//
|
|
// Check for an unattended entry first
|
|
//
|
|
|
|
if (bCleanInstall) {
|
|
|
|
if (FAILED(SafeExpandEnvironmentStrings (TEXT("%SystemRoot%\\System32\\$winnt$.inf"), szDirectory,
|
|
ARRAYSIZE(szDirectory)))) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d"), GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
szDest[0] = TEXT('\0');
|
|
GetPrivateProfileString (TEXT("guiunattended"), TEXT("profilesdir"), TEXT(""),
|
|
szDest, MAX_PATH, szDirectory);
|
|
|
|
if (szDest[0] != TEXT('\0')) {
|
|
|
|
//
|
|
// Since $winnt$.inf is an INF, we must strip out %% pairs
|
|
//
|
|
|
|
szCurDest = szDest;
|
|
szLookAhead = szDest;
|
|
|
|
#ifdef UNICODE
|
|
while (*szLookAhead) {
|
|
if (szLookAhead[0] == L'%' && szLookAhead[1] == L'%') {
|
|
szLookAhead++; // pair of %%; skip one char
|
|
}
|
|
|
|
*szCurDest++ = *szLookAhead++;
|
|
}
|
|
#else
|
|
//
|
|
// This code path is not compiled so it has not been tested
|
|
//
|
|
|
|
#error Code written but not tested!
|
|
|
|
while (*szLookAhead) {
|
|
|
|
if (IsDbcsLeadByte (*szLookAhead)) {
|
|
|
|
*szCurDest++ = *szLookAhead++; // copy first half of byte pair
|
|
|
|
} else if (*szLookAhead == '%') {
|
|
|
|
if (!IsDbcsLeadByte (szLookAhead[1]) && szLookAhead[1] == '%') {
|
|
szLookAhead++; // pair of %%; skip one char
|
|
}
|
|
}
|
|
|
|
*szCurDest++ = *szLookAhead++;
|
|
}
|
|
|
|
#endif
|
|
|
|
*szCurDest = 0;
|
|
|
|
//
|
|
// The unattend profile directory exists. We need to set this
|
|
// path in the registry
|
|
//
|
|
|
|
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDest,
|
|
((lstrlen(szDest) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using unattend location %s for user profiles"), szDest));
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// By default, the OS will try to use the new location for
|
|
// user profiles, but if we are doing an upgrade of a machine
|
|
// with profiles in the NT4 location, we want to continue
|
|
// to use that location.
|
|
//
|
|
// Build a test path to the old All Users directory on NT4
|
|
// to determine which location to use.
|
|
//
|
|
|
|
if (FAILED(SafeExpandEnvironmentStrings (NT4_PROFILES_DIRECTORY, szDirectory,
|
|
ARRAYSIZE(szDirectory)))) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: ExpandEnvironmentStrings failed with error %d, setting the dir unexpanded"), GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: CheckSlashEx failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, ALL_USERS);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: StringCchCopy failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
|
|
|
|
//
|
|
// An app was found that creates an "All Users" directory under NT4 profiles directory
|
|
// Check for Default User as well.
|
|
//
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, DEFAULT_USER);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: StringCchCopy failed")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFileAttributesEx (szDirectory, GetFileExInfoStandard, &fad)) {
|
|
|
|
//
|
|
// The old profiles directory exists. We need to set this
|
|
// path in the registry
|
|
//
|
|
|
|
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
if (RegSetValueEx (hKey, PROFILES_DIRECTORY,
|
|
0, REG_EXPAND_SZ, (LPBYTE) NT4_PROFILES_DIRECTORY,
|
|
((lstrlen(NT4_PROFILES_DIRECTORY) + 1) * sizeof(TCHAR))) == ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("DetermineProfilesLocation: Using NT4 location for user profiles")));
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the profiles directory exists.
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateSecureAdminDirectory(szDirectory, OTHERSIDS_EVERYONE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create profiles subdirectory <%s>. Error = %d."),
|
|
szDirectory, GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Decide where the Default User profile should be
|
|
//
|
|
|
|
if (!CheckProfile (szDirectory, DEFAULT_USER_PROFILE, DEFAULT_USER)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check default user profile Error = %d."),
|
|
GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the profiles\Default User directory exists
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query default user profile directory.")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_EVERYONE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create Default User subdirectory <%s>. Error = %d."),
|
|
szDirectory, GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
SetFileAttributes (szDirectory, FILE_ATTRIBUTE_HIDDEN);
|
|
|
|
|
|
//
|
|
// Decide where the All Users profile should be
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetProfilesDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query profiles directory root.")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!CheckProfile (szDirectory, ALL_USERS_PROFILE, ALL_USERS)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to check all users profile Error = %d."),
|
|
GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Check if the profiles\All Users directory exists
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to query all users profile directory.")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Give additional permissions for power users/everyone
|
|
//
|
|
|
|
if (!CreateSecureAdminDirectory (szDirectory, OTHERSIDS_POWERUSERS | OTHERSIDS_EVERYONE)) {
|
|
DebugMsg((DM_WARNING, TEXT("DetermineProfilesLocation: Failed to create All Users subdirectory <%s>. Error = %d."),
|
|
szDirectory, GetLastError()));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Hide some special profiles like NetworkService etc.
|
|
//
|
|
|
|
if (!bCleanInstall) {
|
|
HideSpecialProfiles();
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// InitializeProfiles()
|
|
//
|
|
// Purpose: Confirms / Creates the profile, Default User,
|
|
// and All Users directories, and converts any
|
|
// existing common groups.
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments: This should only be called by GUI mode setup!
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/08/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI InitializeProfiles (BOOL bGuiModeSetup)
|
|
{
|
|
TCHAR szDirectory[MAX_PATH];
|
|
TCHAR szSystemProfile[MAX_PATH];
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szTemp2[MAX_PATH];
|
|
DWORD dwSize;
|
|
DWORD dwDisp;
|
|
LPTSTR lpEnd;
|
|
DWORD i;
|
|
HKEY hKey;
|
|
BOOL bRetVal = FALSE;
|
|
DWORD dwErr;
|
|
PSHELL32_API pShell32Api;
|
|
HRESULT hr;
|
|
UINT cchEnd;
|
|
|
|
dwErr = GetLastError();
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Entering.")));
|
|
|
|
|
|
if (!bGuiModeSetup) {
|
|
|
|
//
|
|
// block loading user profile
|
|
//
|
|
|
|
if (g_hProfileSetup) {
|
|
ResetEvent (g_hProfileSetup);
|
|
}
|
|
}
|
|
|
|
|
|
dwErr = LoadShell32Api( &pShell32Api );
|
|
|
|
if ( dwErr != ERROR_SUCCESS ) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the USERPROFILE environment variable
|
|
//
|
|
|
|
hr = SafeExpandEnvironmentStrings(SYSTEM_PROFILE_LOCATION, szSystemProfile, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to enpand env string for system profile.")));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Requery for the default user profile directory (expanded version)
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
|
|
dwErr = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the USERPROFILE environment variable
|
|
//
|
|
|
|
if (!SetEnvironmentVariable (TEXT("USERPROFILE"), szDirectory))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to set env var for user profile.")));
|
|
}
|
|
|
|
//
|
|
// Create all the folders under Default User
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to CheckSlashEx.")));
|
|
dwErr = ERROR_BAD_PATHNAME;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Loop through the shell folders
|
|
//
|
|
|
|
for (i=0; i < g_dwNumShellFolders; i++) {
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!CreateNestedDirectory(szDirectory, NULL)) {
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
|
|
szDirectory, dwErr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (c_ShellFolders[i].iFolderResourceID != 0) {
|
|
// NOTE this returns an HRESULT
|
|
dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
|
|
c_ShellFolders[i].lpFolderResourceDLL,
|
|
c_ShellFolders[i].iFolderResourceID );
|
|
if (FAILED(dwErr)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
|
|
szDirectory, dwErr));
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (c_ShellFolders[i].bHidden) {
|
|
SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Remove the %USERPROFILE%\Personal directory if it exists.
|
|
// Windows NT 4.0 had a Personal folder in the root of the
|
|
// user's profile. NT 5.0 renames this folder to My Documents
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_SH_PERSONAL2, szTemp, ARRAYSIZE(szTemp))) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy personal2.")));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
RemoveDirectory(szDirectory);
|
|
}
|
|
|
|
|
|
//
|
|
// Migrate the Template Directory if it exists. Copy it from %systemroot%\shellnew
|
|
// to Templates directory under default user. Do the same for existing profiles.
|
|
//
|
|
|
|
if ((LoadString (g_hDllInstance, IDS_SH_TEMPLATES2, szTemp, ARRAYSIZE(szTemp))) &&
|
|
(SUCCEEDED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2)))) &&
|
|
(LoadString (g_hDllInstance, IDS_SH_TEMPLATES, szTemp, ARRAYSIZE(szTemp)))) {
|
|
|
|
//
|
|
// if all of the above succeeded
|
|
//
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy template.")));
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Copying <%s> to %s."), szTemp2, szDirectory));
|
|
CopyProfileDirectory(szTemp2, szDirectory, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Remove %USERPROFILE%\Temp if it exists. The Temp directory
|
|
// will now be in the Local Settings folder
|
|
//
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, TEXT("Temp"));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Delnode(szDirectory);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy temp.")));
|
|
}
|
|
|
|
//
|
|
// Remove %USERPROFILE%\Temporary Internet Files if it exists. The
|
|
// Temporary Internet Files directory will now be in the Local Settings
|
|
// folder
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_TEMPINTERNETFILES, szTemp, ARRAYSIZE(szTemp))) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Delnode(szDirectory);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy temp internet files.")));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Remove %USERPROFILE%\History if it exists. The History
|
|
// directory will now be in the Local Settings folder
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_HISTORY, szTemp, ARRAYSIZE(szTemp))) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Delnode(szDirectory);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy history.")));
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Set the User Shell Folder paths in the registry
|
|
//
|
|
|
|
hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), USER_SHELL_FOLDERS, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to append user shell folders to .default.")));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%USERPROFILE%"));
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
|
|
if (RegCreateKeyEx (HKEY_USERS, szTemp,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
for (i=0; i < g_dwNumShellFolders; i++) {
|
|
|
|
if (c_ShellFolders[i].bAddCSIDL) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Set the Shell Folder paths in the registry
|
|
//
|
|
|
|
hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), SHELL_FOLDERS, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to append user shell folders to .default.")));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query default user profile directory.")));
|
|
dwErr = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: CheckSlashEx failed.")));
|
|
dwErr = ERROR_BAD_PATHNAME;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegCreateKeyEx (HKEY_USERS, szTemp,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
for (i=0; i < g_dwNumShellFolders; i++) {
|
|
|
|
if (c_ShellFolders[i].bAddCSIDL) {
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy shell folder %s."), c_ShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
RegSetValueEx (hKey, c_ShellFolders[i].lpFolderName,
|
|
0, REG_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
//
|
|
// Set the per user TEMP and TMP environment variables
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_SH_TEMP,
|
|
szTemp, ARRAYSIZE(szTemp))) {
|
|
|
|
StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%USERPROFILE%"));
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
|
|
LoadString (g_hDllInstance, IDS_SH_LOCALSETTINGS,
|
|
lpEnd, cchEnd);
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (lpEnd)
|
|
{
|
|
hr = StringCchCopy(lpEnd, cchEnd, szTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (RegCreateKeyEx (HKEY_USERS, TEXT(".Default\\Environment"),
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
RegSetValueEx (hKey, TEXT("TEMP"),
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
|
|
RegSetValueEx (hKey, TEXT("TMP"),
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Set the user preference exclusion list. This will
|
|
// prevent the Local Settings folder from roaming
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_EXCLUSIONLIST,
|
|
szDirectory, ARRAYSIZE(szDirectory))) {
|
|
|
|
hr = AppendName(szTemp, ARRAYSIZE(szTemp), TEXT(".Default"), WINLOGON_KEY, NULL, NULL);
|
|
|
|
if (RegCreateKeyEx (HKEY_USERS, szTemp,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
RegSetValueEx (hKey, TEXT("ExcludeProfileDirs"),
|
|
0, REG_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Requery for the all users profile directory (expanded version)
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetAllUsersProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to query all users profile directory.")));
|
|
dwErr = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Set the ALLUSERSPROFILE environment variable
|
|
//
|
|
|
|
SetEnvironmentVariable (TEXT("ALLUSERSPROFILE"), szDirectory);
|
|
|
|
|
|
//
|
|
// Create all the folders under All Users
|
|
//
|
|
|
|
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: CheckSlashEx failed.")));
|
|
dwErr = ERROR_BAD_PATHNAME;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Loop through the shell folders
|
|
//
|
|
|
|
for (i=0; i < g_dwNumCommonShellFolders; i++) {
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
|
|
c_CommonShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!CreateNestedDirectory(szDirectory, NULL)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to create the destination directory <%s>. Error = %d"),
|
|
szDirectory, GetLastError()));
|
|
dwErr = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
if (c_CommonShellFolders[i].iFolderResourceID != 0) {
|
|
// NOTE this returns an HRESULT
|
|
dwErr = pShell32Api->pfnShSetLocalizedName( szDirectory,
|
|
c_CommonShellFolders[i].lpFolderResourceDLL,
|
|
c_CommonShellFolders[i].iFolderResourceID );
|
|
if (FAILED(dwErr)) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SHSetLocalizedName failed for directory <%s>. Error = %d"),
|
|
szDirectory, dwErr));
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (c_CommonShellFolders[i].bHidden) {
|
|
SetFileAttributes(szDirectory, GetFileAttributes(szDirectory) | FILE_ATTRIBUTE_HIDDEN);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Unsecure the Documents and App Data folders in the All Users profile
|
|
//
|
|
|
|
if (LoadString (g_hDllInstance, IDS_SH_SHAREDDOCS, szTemp, ARRAYSIZE(szTemp))) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SetFilePermissions(szDirectory, c_szCommonDocumentsACL);
|
|
}
|
|
}
|
|
|
|
if (LoadString (g_hDllInstance, IDS_SH_APPDATA, szTemp, ARRAYSIZE(szTemp))) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SetFilePermissions(szDirectory, c_szCommonAppDataACL);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Set the User Shell Folder paths in the registry
|
|
//
|
|
|
|
StringCchCopy (szDirectory, ARRAYSIZE(szDirectory), TEXT("%ALLUSERSPROFILE%"));
|
|
lpEnd = CheckSlashEx (szDirectory, ARRAYSIZE(szDirectory), &cchEnd);
|
|
|
|
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
for (i=0; i < g_dwNumCommonShellFolders; i++) {
|
|
|
|
if (c_ShellFolders[i].bAddCSIDL) {
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
|
|
c_CommonShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
//
|
|
// On 64-bit NT, we need to create the user shell folders in
|
|
// the 32-bit view of the registry so that 32-bit app calls
|
|
// to SHGetFolderPath(...CSIDL_COMMON_APPDATA...) would succeed.
|
|
//
|
|
if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, USER_SHELL_FOLDERS32,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
for (i=0; i < g_dwNumCommonShellFolders; i++) {
|
|
|
|
if (c_ShellFolders[i].bAddCSIDL) {
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: Failed to copy <%s>."),
|
|
c_CommonShellFolders[i].szFolderLocation));
|
|
dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
RegSetValueEx (hKey, c_CommonShellFolders[i].lpFolderName,
|
|
0, REG_EXPAND_SZ, (LPBYTE) szDirectory,
|
|
((lstrlen(szDirectory) + 1) * sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Convert any Program Manager common groups
|
|
//
|
|
|
|
if (!ConvertCommonGroups()) {
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ConvertCommonGroups failed.")));
|
|
}
|
|
|
|
//
|
|
// Reacl the ProfileList entries
|
|
//
|
|
|
|
hr = ReaclProfileListEntries();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: ReaclProfileListEntries failed, hr = %08X"), hr));
|
|
}
|
|
|
|
//
|
|
// Reacl the user profile folders in case of upgrade
|
|
//
|
|
|
|
if (!g_bCleanInstall)
|
|
{
|
|
SecureUserProfiles();
|
|
}
|
|
|
|
//
|
|
// Set the PROFILES env var, will used by the security template to skip
|
|
// applying the template on the profile directory
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szTemp);
|
|
if (GetProfilesDirectoryEx(szTemp, &dwSize, TRUE))
|
|
{
|
|
if (SetEnvironmentVariable(c_szProfileEnvName, szTemp))
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: set env var <%s>=%s"), c_szProfileEnvName, szTemp));
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: SetEnvironmentVariable failed, error = %d"), GetLastError()));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("InitializeProfiles: GetProfilesDirectoryEx failed, error = %d"), GetLastError()));
|
|
}
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("InitializeProfiles: Leaving successfully.")));
|
|
|
|
bRetVal = TRUE;
|
|
|
|
Exit:
|
|
|
|
if ((!bGuiModeSetup) && (g_hProfileSetup)) {
|
|
SetEvent (g_hProfileSetup);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
return bRetVal;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CheckProfile()
|
|
//
|
|
// Purpose: Checks and creates a storage location for either
|
|
// the Default User or All Users profile
|
|
//
|
|
// Parameters: LPTSTR lpProfilesDir - Root of the profiles
|
|
// LPTSTR lpProfileValue - Profile registry value name
|
|
// LPTSTR lpProfileName - Default profile name
|
|
//
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL CheckProfile (LPTSTR lpProfilesDir, LPTSTR lpProfileValue,
|
|
LPTSTR lpProfileName)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
TCHAR szTemp2[MAX_PATH];
|
|
TCHAR szName[MAX_PATH];
|
|
TCHAR szFormat[30];
|
|
DWORD dwSize, dwDisp, dwType;
|
|
LPTSTR lpEnd;
|
|
LONG lResult;
|
|
HKEY hKey;
|
|
INT iStrLen;
|
|
WIN32_FILE_ATTRIBUTE_DATA fad;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Open the ProfileList key
|
|
//
|
|
|
|
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to open profile list key with %d."),
|
|
lResult));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Check the registry to see if this folder is defined already
|
|
//
|
|
|
|
dwSize = sizeof(szTemp);
|
|
if (RegQueryValueEx (hKey, lpProfileValue, NULL, &dwType,
|
|
(LPBYTE) szTemp, &dwSize) == ERROR_SUCCESS) {
|
|
RegCloseKey (hKey);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Generate the default name
|
|
//
|
|
|
|
hr = AppendName(szTemp, ARRAYSIZE(szTemp), lpProfilesDir, lpProfileName, &lpEnd, &cchEnd);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to append lpProfileName to lpProfilesDir.")))
|
|
return FALSE;
|
|
}
|
|
|
|
StringCchCopy (szName, ARRAYSIZE(szName), lpProfileName);
|
|
|
|
|
|
//
|
|
// Check if this directory exists
|
|
//
|
|
|
|
if (FAILED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2))))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to expand env string.")))
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetFileAttributesEx (szTemp2, GetFileExInfoStandard, &fad)) {
|
|
|
|
if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
|
|
//
|
|
// Check if this directory is under the system root.
|
|
// If so, this is ok, we don't need to generate a unique
|
|
// name for this.
|
|
//
|
|
|
|
hr = SafeExpandEnvironmentStrings (TEXT("%SystemRoot%"), szTemp, ARRAYSIZE(szTemp));
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CheckProfile: Failed to %SystemRoot%.")))
|
|
return FALSE;
|
|
}
|
|
|
|
iStrLen = lstrlen (szTemp);
|
|
|
|
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE,
|
|
szTemp, iStrLen, szTemp2, iStrLen) != CSTR_EQUAL) {
|
|
|
|
|
|
//
|
|
// The directory exists already. Use a new name of
|
|
// Profile Name (SystemDirectory)
|
|
//
|
|
// eg: Default User (WINNT)
|
|
//
|
|
|
|
lpEnd = szTemp + lstrlen(szTemp) - 1;
|
|
|
|
while ((lpEnd > szTemp) && ((*lpEnd) != TEXT('\\')))
|
|
lpEnd--;
|
|
|
|
if (*lpEnd == TEXT('\\')) {
|
|
lpEnd++;
|
|
}
|
|
|
|
LoadString (g_hDllInstance, IDS_PROFILE_FORMAT, szFormat,
|
|
ARRAYSIZE(szFormat));
|
|
StringCchPrintf (szName, ARRAYSIZE(szName), szFormat, lpProfileName, lpEnd);
|
|
|
|
//
|
|
// To prevent reusing the directories, delete it first..
|
|
//
|
|
|
|
AppendName(szTemp, ARRAYSIZE(szTemp), lpProfilesDir, szName, NULL, NULL);
|
|
|
|
if (SUCCEEDED(SafeExpandEnvironmentStrings (szTemp, szTemp2, ARRAYSIZE(szTemp2)))) {
|
|
DebugMsg((DM_VERBOSE, TEXT("CheckProfile: Delnoding directory.. %s"), szTemp2));
|
|
Delnode(szTemp2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Save the profile name in the registry
|
|
//
|
|
|
|
RegSetValueEx (hKey, lpProfileValue,
|
|
0, REG_SZ, (LPBYTE) szName,
|
|
((lstrlen(szName) + 1) * sizeof(TCHAR)));
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CheckProfile: The %s profile is mapped to %s"),
|
|
lpProfileName, szName));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateUserProfile()
|
|
//
|
|
// Purpose: Creates a new user profile, but does not load
|
|
// the hive.
|
|
//
|
|
// Parameters: pSid - SID pointer
|
|
// lpUserName - User name
|
|
// lpUserHive - Optional user hive
|
|
// lpProfileDir - Receives the new profile directory
|
|
// dwDirSize - Size of lpProfileDir
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments: If a user hive isn't specified the default user
|
|
// hive will be used.
|
|
//
|
|
// History: Date Author Comment
|
|
// 9/12/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateUserProfile (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
|
|
LPTSTR lpProfileDir, DWORD dwDirSize)
|
|
{
|
|
return CreateUserProfileEx(pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, TRUE);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// CreateUserProfileEx()
|
|
//
|
|
// Purpose: Creates a new user profile, but does not load
|
|
// the hive.
|
|
//
|
|
// Parameters: pSid - SID pointer
|
|
// lpUserName - User name
|
|
// lpUserHive - Optional user hive
|
|
// lpProfileDir - Receives the new profile directory
|
|
// dwDirSize - Size of lpProfileDir
|
|
// bWin9xUpg - Flag to say whether it is win9x upgrade
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs
|
|
//
|
|
// Comments: If a user hive isn't specified the default user
|
|
// hive will be used.
|
|
//
|
|
// History: Date Author Comment
|
|
// 9/12/95 ericflo Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CreateUserProfileEx (PSID pSid, LPCTSTR lpUserName, LPCTSTR lpUserHive,
|
|
LPTSTR lpProfileDir, DWORD dwDirSize, BOOL bWin9xUpg)
|
|
{
|
|
TCHAR szProfileDir[MAX_PATH];
|
|
TCHAR szExpProfileDir[MAX_PATH] = {0};
|
|
TCHAR szDirectory[MAX_PATH];
|
|
TCHAR LocalProfileKey[MAX_PATH];
|
|
UNICODE_STRING UnicodeString;
|
|
LPTSTR lpSidString, lpEnd, lpSave;
|
|
NTSTATUS NtStatus;
|
|
LONG lResult;
|
|
DWORD dwDisp;
|
|
DWORD dwError;
|
|
DWORD dwSize;
|
|
DWORD dwType;
|
|
HKEY hKey;
|
|
UINT cchEnd;
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
//
|
|
// Check parameters
|
|
//
|
|
|
|
if (!lpUserName || !lpUserName[0]) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null username.")));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pSid) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Null SID.")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Verbose output
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with <%s>."), lpUserName));
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Entering with user hive of <%s>."),
|
|
lpUserHive ? lpUserHive : TEXT("NULL")));
|
|
|
|
|
|
//
|
|
// Convert the sid into text format
|
|
//
|
|
|
|
NtStatus = RtlConvertSidToUnicodeString(&UnicodeString, pSid, (BOOLEAN)TRUE);
|
|
|
|
if (!NT_SUCCESS(NtStatus)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: RtlConvertSidToUnicodeString failed, status = 0x%x"),
|
|
NtStatus));
|
|
return FALSE;
|
|
}
|
|
|
|
lpSidString = UnicodeString.Buffer;
|
|
|
|
|
|
//
|
|
// Check if this user's profile exists already
|
|
//
|
|
|
|
GetProfileListKeyName(LocalProfileKey, ARRAYSIZE(LocalProfileKey), lpSidString);
|
|
|
|
szProfileDir[0] = TEXT('\0');
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, LocalProfileKey,
|
|
0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(szProfileDir);
|
|
RegQueryValueEx (hKey, PROFILE_IMAGE_VALUE_NAME, NULL,
|
|
&dwType, (LPBYTE) szProfileDir, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
if (szProfileDir[0] == TEXT('\0')) {
|
|
|
|
//
|
|
// Make the user's directory
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szProfileDir);
|
|
if (!GetProfilesDirectoryEx(szProfileDir, &dwSize, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get profile root directory.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ComputeLocalProfileName (NULL, lpUserName, szProfileDir, ARRAYSIZE(szProfileDir),
|
|
szExpProfileDir, ARRAYSIZE(szExpProfileDir), pSid, bWin9xUpg)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to create directory.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy the default user profile into this directory
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szDirectory);
|
|
if (!GetDefaultUserProfileDirectoryEx(szDirectory, &dwSize, TRUE)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to get default user profile.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (lpUserHive) {
|
|
|
|
//
|
|
// Copy the default user profile without the hive.
|
|
//
|
|
|
|
if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNOREHIVE | CPD_IGNORELONGFILENAMES)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Now copy the hive
|
|
//
|
|
|
|
hr = AppendName(szDirectory, ARRAYSIZE(szDirectory), szExpProfileDir, c_szNTUserDat, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to append ntuser.dat.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lstrcmpi (lpUserHive, szDirectory)) {
|
|
|
|
if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Copy the default user profile and the hive.
|
|
//
|
|
|
|
if (!CopyProfileDirectory (szDirectory, szExpProfileDir, CPD_IGNORECOPYERRORS | CPD_IGNORELONGFILENAMES)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: CopyProfileDirectory failed with error %d."), GetLastError()));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Save the user's profile in the registry.
|
|
//
|
|
|
|
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, LocalProfileKey, 0, 0, 0,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed trying to create the local profile key <%s>, error = %d."), LocalProfileKey, lResult));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Add the profile directory
|
|
//
|
|
|
|
lResult = RegSetValueEx(hKey, PROFILE_IMAGE_VALUE_NAME, 0,
|
|
REG_EXPAND_SZ,
|
|
(LPBYTE)szProfileDir,
|
|
sizeof(TCHAR)*(lstrlen(szProfileDir) + 1));
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: First RegSetValueEx failed, error = %d."), lResult));
|
|
RegCloseKey (hKey);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Add the users's SID
|
|
//
|
|
|
|
lResult = RegSetValueEx(hKey, TEXT("Sid"), 0,
|
|
REG_BINARY, pSid, RtlLengthSid(pSid));
|
|
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Second RegSetValueEx failed, error = %d."), lResult));
|
|
}
|
|
|
|
|
|
//
|
|
// Close the registry key
|
|
//
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
} else {
|
|
|
|
//
|
|
// The user already has a profile, so just copy the hive if
|
|
// appropriate.
|
|
//
|
|
|
|
hr = SafeExpandEnvironmentStrings (szProfileDir, szExpProfileDir,
|
|
ARRAYSIZE(szExpProfileDir));
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to expand env string.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpUserHive) {
|
|
|
|
//
|
|
// Copy the hive
|
|
//
|
|
|
|
hr = AppendName(szDirectory, ARRAYSIZE(szDirectory), szExpProfileDir, c_szNTUserDat, NULL, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: failed to append ntuser.dat.")));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
|
|
SetFileAttributes (szDirectory, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
if (lstrcmpi (lpUserHive, szDirectory)) {
|
|
if (!CopyFile (lpUserHive, szDirectory, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to copy user hive with error %d."), GetLastError()));
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Source: %s."), lpUserHive));
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Destination: %s."), szDirectory));
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Now load the hive temporary so the security can be fixed
|
|
//
|
|
|
|
lpEnd = CheckSlashEx (szExpProfileDir, ARRAYSIZE(szExpProfileDir), &cchEnd);
|
|
lpSave = lpEnd - 1;
|
|
StringCchCopy (lpEnd, cchEnd, c_szNTUserDat);
|
|
|
|
lResult = MyRegLoadKey(HKEY_USERS, lpSidString, szExpProfileDir);
|
|
|
|
*lpSave = TEXT('\0');
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: Failed to load hive, error = %d."), lResult));
|
|
dwError = GetLastError();
|
|
DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
SetLastError(dwError);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!SetupNewHive(NULL, lpSidString, pSid)) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("CreateUserProfile: SetupNewHive failed.")));
|
|
dwError = GetLastError();
|
|
MyRegUnLoadKey(HKEY_USERS, lpSidString);
|
|
DeleteProfileEx (lpSidString, szExpProfileDir, FALSE, HKEY_LOCAL_MACHINE, NULL);
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
SetLastError(dwError);
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Unload the hive
|
|
//
|
|
|
|
MyRegUnLoadKey(HKEY_USERS, lpSidString);
|
|
|
|
|
|
//
|
|
// Free the sid string
|
|
//
|
|
|
|
RtlFreeUnicodeString(&UnicodeString);
|
|
|
|
|
|
//
|
|
// Save the profile path if appropriate
|
|
//
|
|
|
|
if (lpProfileDir) {
|
|
|
|
if ((DWORD)lstrlen(szExpProfileDir) < dwDirSize) {
|
|
StringCchCopy (lpProfileDir, dwDirSize, szExpProfileDir);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Success
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("CreateUserProfile: Leaving successfully.")));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************************
|
|
//
|
|
// SecureUserProfiles()
|
|
//
|
|
// Description : This function secures user profiles during FAT->NTFS conversion.
|
|
// It will also get called during upgrade in order to secure the
|
|
// profile area where the user has converted the file system before
|
|
// the upgrade.
|
|
//
|
|
// Arguments : None.
|
|
//
|
|
// Return Value: None.
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/8/00 santanuc Created
|
|
// 09/25/2002 mingzhu Added SecureCommonProfiles()
|
|
//
|
|
//*************************************************************************
|
|
|
|
void WINAPI SecureUserProfiles(void)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//
|
|
// Put all our work into the exception handler, so we don't corrupt setup
|
|
// and convert.
|
|
//
|
|
__try
|
|
{
|
|
//
|
|
// Secure the per user profile areas
|
|
//
|
|
|
|
hr = SecurePerUserProfiles();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: SecurePerUserProfiles failed, hr =%08X"), hr));
|
|
}
|
|
|
|
//
|
|
// Secure the common profile areas.
|
|
//
|
|
|
|
hr = SecureCommonProfiles();
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: SecureCommonProfile failed, hr =%08X"), hr));
|
|
}
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Exception %d!!!"), GetExceptionCode()));
|
|
}
|
|
}
|
|
|
|
//*************************************************************************
|
|
//
|
|
// SecurePerUserProfiles()
|
|
//
|
|
// Description : This function secure (reacl) the per-user profiles under
|
|
// profiles directory, it will loop for each entry in the
|
|
// profile list entry and reacl every profile with the ACL
|
|
// of Admin(F)System(F)ProfileOwner(F).
|
|
//
|
|
// Arguments : None.
|
|
//
|
|
// Return Value: HRESULT.
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/8/00 santanuc Created
|
|
// 09/25/2002 mingzhu Seperated from SecureUserProfiles()
|
|
//
|
|
//*************************************************************************
|
|
|
|
HRESULT SecurePerUserProfiles()
|
|
{
|
|
SECURITY_DESCRIPTOR DirSd, FileSd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pDirAcl = NULL, pFileAcl = NULL;
|
|
PSID pSidOwner=NULL, pSidAdmin = NULL, pSidSystem = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
HKEY hKeyProfilesList, hKeyProfile = NULL;
|
|
TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
|
|
DWORD dwSIDNameSize, dwSize;
|
|
DWORD dwIndex;
|
|
LONG lResult;
|
|
FILETIME ft;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// Get the system sid
|
|
//
|
|
|
|
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0, &pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: 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_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Open the ProfileList key
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
PROFILE_LIST_PATH,
|
|
0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to open ProfileList key")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Enumerate the profiles
|
|
//
|
|
|
|
dwIndex = 0;
|
|
dwSIDNameSize = ARRAYSIZE(szSIDName);
|
|
lResult = RegEnumKeyEx(hKeyProfilesList,
|
|
dwIndex,
|
|
szSIDName,
|
|
&dwSIDNameSize,
|
|
NULL, NULL, NULL, &ft);
|
|
|
|
|
|
while (lResult == ERROR_SUCCESS) {
|
|
|
|
if (RegOpenKeyEx (hKeyProfilesList,
|
|
szSIDName,
|
|
0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(szProfilePath);
|
|
if (RegQueryValueEx (hKeyProfile,
|
|
PROFILE_IMAGE_VALUE_NAME,
|
|
NULL, NULL,
|
|
(LPBYTE) szProfilePath,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
goto NextProfile;
|
|
}
|
|
|
|
//
|
|
// Expand the profile image filename
|
|
//
|
|
|
|
if (FAILED(SafeExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH)))
|
|
{
|
|
goto IssueError;
|
|
}
|
|
|
|
//
|
|
// Create the acl for the user profile dir
|
|
//
|
|
|
|
//
|
|
// Get the owner sid
|
|
//
|
|
|
|
if (AllocateAndInitSidFromString(szSIDName, &pSidOwner) != STATUS_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to create owner sid."), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the Dir object ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (pSidOwner)) +
|
|
(2 * GetLengthSid (pSidSystem)) +
|
|
(2 * GetLengthSid (pSidAdmin)) +
|
|
sizeof(ACL) +
|
|
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pDirAcl) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for File object ACL
|
|
//
|
|
|
|
cbAcl = (GetLengthSid (pSidOwner)) +
|
|
(GetLengthSid (pSidSystem)) +
|
|
(GetLengthSid (pSidAdmin)) +
|
|
sizeof(ACL) +
|
|
(3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pFileAcl) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to allocate memory for acl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize acl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
|
|
//
|
|
// Add Aces. Non-inheritable ACEs first
|
|
//
|
|
|
|
aceIndex = 0;
|
|
if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidOwner)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
//
|
|
// Now the Inheritable Aces.
|
|
//
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidOwner)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add owner ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to initialize security descriptor. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
|
|
goto IssueError;
|
|
}
|
|
|
|
//
|
|
// Pass the profile path to SecureProfile for securing
|
|
// the profile dir and nested subdirs and files.
|
|
//
|
|
|
|
if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
|
|
goto IssueError;
|
|
}
|
|
|
|
goto NextProfile;
|
|
|
|
IssueError:
|
|
DebugMsg((DM_WARNING, TEXT("SecureUserProfiles: Failed to secure %s Profile directory"), szExpandedProfilePath));
|
|
|
|
}
|
|
|
|
NextProfile:
|
|
|
|
// Free the allocated stuffs
|
|
|
|
if (hKeyProfile) {
|
|
RegCloseKey(hKeyProfile);
|
|
hKeyProfile = NULL;
|
|
}
|
|
|
|
if (pSidOwner) {
|
|
LocalFree(pSidOwner);
|
|
pSidOwner = NULL;
|
|
}
|
|
|
|
if (pDirAcl) {
|
|
GlobalFree (pDirAcl);
|
|
pDirAcl = NULL;
|
|
}
|
|
|
|
if (pFileAcl) {
|
|
GlobalFree (pFileAcl);
|
|
pFileAcl = NULL;
|
|
}
|
|
|
|
//
|
|
// Reset for the next loop
|
|
//
|
|
|
|
dwIndex++;
|
|
dwSIDNameSize = ARRAYSIZE(szSIDName);
|
|
lResult = RegEnumKeyEx(hKeyProfilesList,
|
|
dwIndex,
|
|
szSIDName,
|
|
&dwSIDNameSize,
|
|
NULL, NULL, NULL, &ft);
|
|
}
|
|
|
|
RegCloseKey(hKeyProfilesList);
|
|
|
|
Exit:
|
|
|
|
if (pSidSystem) {
|
|
FreeSid(pSidSystem);
|
|
}
|
|
|
|
if (pSidAdmin) {
|
|
FreeSid(pSidAdmin);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//*************************************************************************
|
|
//
|
|
// HideSpecialProfiles()
|
|
//
|
|
// Routine Description :
|
|
// This function secures special profiles for which PI_HIDEPROFILE
|
|
// flag is specifed, e.g. LocalService, NetworkService etc. except
|
|
// system account profile. This mark the profile dir as super hidden.
|
|
//
|
|
// Arguments :
|
|
// None.
|
|
//
|
|
// Return Value :
|
|
// None.
|
|
//
|
|
// History: Date Author Comment
|
|
// 8/8/00 santanuc Created
|
|
//
|
|
//*************************************************************************
|
|
|
|
void HideSpecialProfiles(void)
|
|
{
|
|
HKEY hKeyProfilesList, hKeyProfile = NULL;
|
|
TCHAR szSIDName[MAX_PATH], szProfilePath[MAX_PATH], szExpandedProfilePath[MAX_PATH];
|
|
DWORD dwSIDNameSize, dwSize;
|
|
DWORD dwIndex, dwFlags;
|
|
LONG lResult;
|
|
FILETIME ft;
|
|
HRESULT hr;
|
|
|
|
|
|
//
|
|
// Open the ProfileList key
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
|
PROFILE_LIST_PATH,
|
|
0, KEY_READ, &hKeyProfilesList) != ERROR_SUCCESS) {
|
|
|
|
DebugMsg((DM_WARNING, TEXT("HideSpecialProfiles: Failed to open ProfileList key")));
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Enumerate the profiles
|
|
//
|
|
|
|
dwIndex = 0;
|
|
dwSIDNameSize = ARRAYSIZE(szSIDName);
|
|
lResult = RegEnumKeyEx(hKeyProfilesList,
|
|
dwIndex,
|
|
szSIDName,
|
|
&dwSIDNameSize,
|
|
NULL, NULL, NULL, &ft);
|
|
|
|
|
|
while (lResult == ERROR_SUCCESS) {
|
|
|
|
if (RegOpenKeyEx (hKeyProfilesList,
|
|
szSIDName,
|
|
0, KEY_READ, &hKeyProfile) == ERROR_SUCCESS) {
|
|
|
|
//
|
|
// Process only if PI_HIDEPROFILE flag is set
|
|
//
|
|
|
|
dwSize = sizeof(DWORD);
|
|
if (RegQueryValueEx (hKeyProfile,
|
|
PROFILE_FLAGS,
|
|
NULL, NULL,
|
|
(LPBYTE) &dwFlags,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
goto NextProfile;
|
|
}
|
|
|
|
if (!(dwFlags & PI_HIDEPROFILE)) {
|
|
goto NextProfile;
|
|
}
|
|
|
|
dwSize = sizeof(szProfilePath);
|
|
if (RegQueryValueEx (hKeyProfile,
|
|
PROFILE_IMAGE_VALUE_NAME,
|
|
NULL, NULL,
|
|
(LPBYTE) szProfilePath,
|
|
&dwSize) != ERROR_SUCCESS) {
|
|
goto NextProfile;
|
|
}
|
|
|
|
// Ignore profile for system account
|
|
|
|
if (lstrcmp(szProfilePath, SYSTEM_PROFILE_LOCATION) == 0) {
|
|
goto NextProfile;
|
|
}
|
|
|
|
//
|
|
// Expand the profile image filename
|
|
//
|
|
|
|
hr = SafeExpandEnvironmentStrings(szProfilePath, szExpandedProfilePath, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
goto NextProfile;
|
|
}
|
|
|
|
// Mark the profile hidden
|
|
SetFileAttributes(szExpandedProfilePath,
|
|
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
|
|
GetFileAttributes(szExpandedProfilePath));
|
|
|
|
}
|
|
|
|
NextProfile:
|
|
|
|
// Free the allocated stuffs
|
|
|
|
if (hKeyProfile) {
|
|
RegCloseKey(hKeyProfile);
|
|
hKeyProfile = NULL;
|
|
}
|
|
|
|
//
|
|
// Reset for the next loop
|
|
//
|
|
|
|
dwIndex++;
|
|
dwSIDNameSize = ARRAYSIZE(szSIDName);
|
|
lResult = RegEnumKeyEx(hKeyProfilesList,
|
|
dwIndex,
|
|
szSIDName,
|
|
&dwSIDNameSize,
|
|
NULL, NULL, NULL, &ft);
|
|
}
|
|
|
|
RegCloseKey(hKeyProfilesList);
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CopySystemProfile()
|
|
//
|
|
// Purpose: Create the system profile information under
|
|
// ProfileList entry.
|
|
// In case of upgrade copy system profile from older
|
|
// location to new location and delete the old system
|
|
// profile
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return: TRUE if successful
|
|
// FALSE if an error occurs. Call GetLastError()
|
|
//
|
|
// Comments: This should only be called by GUI mode setup!
|
|
//
|
|
// History: Date Author Comment
|
|
// 03/13/01 santanuc Created
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL WINAPI CopySystemProfile(BOOL bCleanInstall)
|
|
{
|
|
HANDLE hToken = NULL;
|
|
LPTSTR SidString = NULL, lpEnd;
|
|
TCHAR szLocalProfileKey[MAX_PATH], szBuffer[MAX_PATH];
|
|
TCHAR szSrc[MAX_PATH], szDest[MAX_PATH];
|
|
LONG lResult;
|
|
HKEY hKey = NULL, hKeyShellFolders;
|
|
DWORD dwFlags, dwInternalFlags, dwRefCount;
|
|
DWORD dwDisp, dwSize, dwType, i;
|
|
BOOL bCopySystemProfile = TRUE, bCopyFromDefault = TRUE;
|
|
PSID pSystemSid = NULL;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HRESULT hr;
|
|
UINT cchEnd;
|
|
|
|
//
|
|
// Set the Profile information for system account i.e sid s-1-5-18
|
|
//
|
|
|
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
|
|
TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) {
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to open system token. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the Sid string
|
|
//
|
|
|
|
SidString = GetSidString(hToken);
|
|
if (!SidString) {
|
|
dwErr = ERROR_ACCESS_DENIED;
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid string for system account")));
|
|
goto Exit;
|
|
}
|
|
|
|
pSystemSid = GetUserSid(hToken);
|
|
if (!pSystemSid) {
|
|
dwErr = ERROR_ACCESS_DENIED;
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get sid for system account")));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Open the profile mapping
|
|
//
|
|
|
|
GetProfileListKeyName(szLocalProfileKey, ARRAYSIZE(szLocalProfileKey), SidString);
|
|
|
|
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, szLocalProfileKey, 0, 0, 0,
|
|
KEY_READ | KEY_WRITE, NULL, &hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to open profile mapping key. Error %d"), lResult));
|
|
dwErr = lResult;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Save the flags
|
|
//
|
|
|
|
dwFlags = PI_LITELOAD | PI_HIDEPROFILE;
|
|
lResult = RegSetValueEx (hKey,
|
|
PROFILE_FLAGS,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwFlags,
|
|
sizeof(DWORD));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile flags. Error %d"), lResult));
|
|
}
|
|
|
|
//
|
|
// Save the internal flags
|
|
//
|
|
|
|
dwInternalFlags = 0;
|
|
lResult = RegSetValueEx (hKey,
|
|
PROFILE_STATE,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwInternalFlags,
|
|
sizeof(DWORD));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save internal flags. Error %d"), lResult));
|
|
}
|
|
|
|
//
|
|
// Save the ref count
|
|
//
|
|
|
|
dwRefCount = 1;
|
|
lResult = RegSetValueEx (hKey,
|
|
PROFILE_REF_COUNT,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE) &dwRefCount,
|
|
sizeof(DWORD));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile ref count. Error %d"), lResult));
|
|
}
|
|
|
|
//
|
|
// Save the sid
|
|
//
|
|
|
|
lResult = RegSetValueEx (hKey,
|
|
TEXT("Sid"),
|
|
0,
|
|
REG_BINARY,
|
|
(LPBYTE) pSystemSid,
|
|
RtlLengthSid(pSystemSid));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile system sid. Error %d"), lResult));
|
|
}
|
|
|
|
|
|
//
|
|
// Figure out whether any existing system profile exist or not
|
|
// in upgrade scenario
|
|
//
|
|
|
|
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), SYSTEM_PROFILE_LOCATION);
|
|
hr = SafeExpandEnvironmentStrings(szBuffer, szDest, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
dwErr = HRESULT_CODE(hr);
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to expand env string. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!bCleanInstall) {
|
|
dwSize = ARRAYSIZE(szBuffer) * sizeof(TCHAR);
|
|
lResult = RegQueryValueEx(hKey,
|
|
PROFILE_IMAGE_VALUE_NAME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE) szBuffer,
|
|
&dwSize);
|
|
if (ERROR_SUCCESS == lResult) {
|
|
if (lstrcmp(szBuffer, SYSTEM_PROFILE_LOCATION) == 0) {
|
|
bCopySystemProfile = FALSE;
|
|
}
|
|
else {
|
|
hr = SafeExpandEnvironmentStrings(szBuffer, szSrc, MAX_PATH);
|
|
if (FAILED(hr))
|
|
{
|
|
dwErr = HRESULT_CODE(hr);
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to expand env string. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
bCopyFromDefault = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bCopySystemProfile) {
|
|
|
|
if (!CreateSecureDirectory(NULL, szDest, pSystemSid, FALSE)) {
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Fail to create SystemProfile dir. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (bCopyFromDefault) {
|
|
dwSize = ARRAYSIZE(szSrc);
|
|
if (!GetDefaultUserProfileDirectoryEx(szSrc, &dwSize, TRUE)) {
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to get default user profile. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy the existing or Default user profile in System profile location
|
|
//
|
|
|
|
if (!CopyProfileDirectoryEx(szSrc, szDest, CPD_IGNOREHIVE | CPD_FORCECOPY | CPD_IGNORECOPYERRORS,
|
|
NULL, NULL)) {
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to copy system profile. Error %d"), dwErr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!bCopyFromDefault) {
|
|
Delnode(szSrc);
|
|
}
|
|
}
|
|
|
|
SetAclForSystemProfile(pSystemSid, szDest);
|
|
|
|
//
|
|
// Save local profile path
|
|
//
|
|
|
|
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), SYSTEM_PROFILE_LOCATION);
|
|
lResult = RegSetValueEx (hKey,
|
|
PROFILE_IMAGE_VALUE_NAME,
|
|
0,
|
|
REG_EXPAND_SZ,
|
|
(LPBYTE) szBuffer,
|
|
((lstrlen(szBuffer) + 1) * sizeof(TCHAR)));
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
dwErr = lResult;
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: Failed to save profile image path with error %d"), lResult));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the Shell Folder paths in the registry for system account
|
|
//
|
|
|
|
hr = AppendName(szBuffer, ARRAYSIZE(szBuffer), TEXT(".Default"), SHELL_FOLDERS, NULL, NULL);
|
|
|
|
lpEnd = CheckSlashEx (szDest, ARRAYSIZE(szDest), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
dwErr = ERROR_BAD_PATHNAME;
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: CheckSlashEx failed.")));
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegCreateKeyEx (HKEY_USERS, szBuffer,
|
|
0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ | KEY_WRITE, NULL, &hKeyShellFolders,
|
|
&dwDisp) == ERROR_SUCCESS) {
|
|
|
|
for (i=0; i < g_dwNumShellFolders; i++) {
|
|
|
|
if (c_ShellFolders[i].bAddCSIDL) {
|
|
hr = StringCchCopy(lpEnd, cchEnd, c_ShellFolders[i].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
dwErr = HRESULT_CODE(hr);
|
|
DebugMsg((DM_WARNING, TEXT("CopySystemProfile: failed to copy %s."), c_ShellFolders[i].szFolderLocation));
|
|
goto Exit;
|
|
}
|
|
|
|
RegSetValueEx (hKeyShellFolders, c_ShellFolders[i].lpFolderName,
|
|
0, REG_SZ, (LPBYTE) szDest,
|
|
((lstrlen(szDest) + 1) * sizeof(TCHAR)));
|
|
}
|
|
}
|
|
|
|
RegCloseKey (hKeyShellFolders);
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (hToken) {
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
if (SidString) {
|
|
DeleteSidString(SidString);
|
|
}
|
|
|
|
if (pSystemSid) {
|
|
DeleteUserSid(pSystemSid);
|
|
}
|
|
|
|
if (hKey) {
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
|
|
return(dwErr == ERROR_SUCCESS ? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************************
|
|
//
|
|
// SetAclForSystemProfile()
|
|
//
|
|
// Routine Description :
|
|
// This function secures dir/files of system profile i.e.
|
|
// %windir%\system32\config\systemprofile
|
|
//
|
|
// Arguments :
|
|
// pSidSystem - System sid
|
|
// szExpandedProfilePath - Expanded system profile location
|
|
//
|
|
// Return Value :
|
|
// None.
|
|
//
|
|
// History: Date Author Comment
|
|
// 04/06/01 santanuc Created
|
|
//
|
|
//*************************************************************************
|
|
|
|
void SetAclForSystemProfile(PSID pSidSystem, LPTSTR szExpandedProfilePath)
|
|
{
|
|
SECURITY_DESCRIPTOR DirSd, FileSd;
|
|
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
|
|
PACL pDirAcl = NULL, pFileAcl = NULL;
|
|
PSID pSidAdmin = NULL;
|
|
DWORD cbAcl, aceIndex;
|
|
|
|
|
|
//
|
|
// 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_WARNING, TEXT("SecureUserProfiles: Failed to initialize admin sid. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for the Dir object ACL
|
|
//
|
|
|
|
cbAcl = (2 * GetLengthSid (pSidSystem)) +
|
|
(2 * GetLengthSid (pSidAdmin)) +
|
|
sizeof(ACL) +
|
|
(4 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pDirAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pDirAcl) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!InitializeAcl(pDirAcl, cbAcl, ACL_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate space for File object ACL
|
|
//
|
|
|
|
cbAcl = (GetLengthSid (pSidSystem)) +
|
|
(GetLengthSid (pSidAdmin)) +
|
|
sizeof(ACL) +
|
|
(2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
|
|
|
|
pFileAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
|
|
if (!pFileAcl) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to allocate memory for acl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!InitializeAcl(pFileAcl, cbAcl, ACL_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize acl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Add Aces. Non-inheritable ACEs first
|
|
//
|
|
|
|
aceIndex = 0;
|
|
if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAce(pDirAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
if (!AddAccessAllowedAce(pFileAcl, ACL_REVISION, FILE_ALL_ACCESS, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Now the Inheritable Aces.
|
|
//
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidSystem)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add system ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
aceIndex++;
|
|
if (!AddAccessAllowedAceEx(pDirAcl, ACL_REVISION, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE, GENERIC_ALL, pSidAdmin)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to add builtin admin ace. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Put together the security descriptor
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&DirSd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&DirSd, TRUE, pDirAcl, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!InitializeSecurityDescriptor(&FileSd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to initialize security descriptor. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(&FileSd, TRUE, pFileAcl, FALSE)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Pass the profile path to SecureProfile for securing
|
|
// the profile dir and nested subdirs and files.
|
|
//
|
|
|
|
if (!SecureNestedDir (szExpandedProfilePath, &DirSd, &FileSd)) {
|
|
DebugMsg((DM_WARNING, TEXT("SetAclForSystemProfile: Failed to secure %s Profile directory"), szExpandedProfilePath));
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (pDirAcl) {
|
|
GlobalFree (pDirAcl);
|
|
pDirAcl = NULL;
|
|
}
|
|
|
|
if (pFileAcl) {
|
|
GlobalFree (pFileAcl);
|
|
pFileAcl = NULL;
|
|
}
|
|
|
|
if (pSidAdmin) {
|
|
FreeSid(pSidAdmin);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//*************************************************************************
|
|
//
|
|
// ReaclProfileListEntries()
|
|
//
|
|
// Routine Description :
|
|
//
|
|
// This function reset the entries in ProfileList key's security to
|
|
// their parent, which is not writable for user, and add a new subkey
|
|
// named "Reference" to save user reference. By doing this, we can
|
|
// prevent the user from changing their other profile related values.
|
|
//
|
|
// Arguments :
|
|
//
|
|
// Return Value : S_OK for success, else for failure
|
|
//
|
|
// History: Date Author Comment
|
|
// 04/19/2002 mingzhu Created
|
|
//
|
|
//*************************************************************************
|
|
|
|
HRESULT ReaclProfileListEntries()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
LONG lResult;
|
|
DWORD dwResult;
|
|
|
|
HKEY hkeyProfileList = NULL;
|
|
PSECURITY_DESCRIPTOR psdProfileList = NULL;
|
|
PACL paclProfileList = NULL;
|
|
SECURITY_DESCRIPTOR sdEntry;
|
|
|
|
DWORD dwIndex;
|
|
FILETIME ft;
|
|
TCHAR szEntryName[MAX_PATH];
|
|
HKEY hkeyEntry = NULL;
|
|
DWORD dwUserPreference;
|
|
DWORD dwSize;
|
|
HKEY hkeyPreference = NULL;
|
|
TCHAR szCentralProfile[MAX_PATH];
|
|
DWORD dwProfileState;
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : entering")));
|
|
|
|
//
|
|
// Check clean install, we don't need to do this for clean installed OS
|
|
//
|
|
|
|
if (g_bCleanInstall)
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Open ProfileList key
|
|
//
|
|
|
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
PROFILE_LIST_PATH,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyProfileList);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open ProfileList key, error = %d"), lResult));
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Get the DACL out of it
|
|
//
|
|
|
|
dwResult = GetSecurityInfo(hkeyProfileList,
|
|
SE_REGISTRY_KEY,
|
|
DACL_SECURITY_INFORMATION,
|
|
NULL,
|
|
NULL,
|
|
&paclProfileList,
|
|
NULL,
|
|
&psdProfileList);
|
|
|
|
if (dwResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : GetSecurityInfo failed, error = %d"), dwResult));
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Initialize the SD for sub entries in Profile List, it will have the same DACL as their parent
|
|
//
|
|
|
|
if (!InitializeSecurityDescriptor(&sdEntry, SECURITY_DESCRIPTOR_REVISION))
|
|
{
|
|
dwResult = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : InitializeSecurityDescriptor failed, error = %d"), dwResult));
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Set the Dacl with default to TRUE
|
|
//
|
|
|
|
if (!SetSecurityDescriptorDacl(&sdEntry, TRUE, paclProfileList, TRUE))
|
|
{
|
|
dwResult = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : SetSecurityDescriptorDacl failed, error = %d"), dwResult));
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
//
|
|
// Enumerate each subkey entry, for each entry :
|
|
//
|
|
// 1. Set the DACLs
|
|
// 2. For roaming users, create the "Preference" subkey, set Dacls on that to give user write permission
|
|
// 3. Set the user preference value to the new location if it exists
|
|
//
|
|
|
|
for (dwIndex = 0; ;dwIndex++)
|
|
{
|
|
//
|
|
// Enumerate subkey
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szEntryName);
|
|
|
|
lResult = RegEnumKeyEx(hkeyProfileList,
|
|
dwIndex,
|
|
szEntryName,
|
|
&dwSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ft);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
break;
|
|
|
|
//
|
|
// Open it
|
|
//
|
|
|
|
lResult = RegOpenKeyEx(hkeyProfileList,
|
|
szEntryName,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeyEntry);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open <%s>, error = %d"), szEntryName, lResult));
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// Set the SD to it,
|
|
//
|
|
|
|
lResult = RegSetKeySecurity(hkeyEntry, DACL_SECURITY_INFORMATION, &sdEntry);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : RegSetKeySecurity failed for <%s>, error = %d"), szEntryName, lResult));
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// Read the "CentralProfile" value, if it is empty, this is a local user
|
|
//
|
|
|
|
szCentralProfile[0] = TEXT('\0');
|
|
dwSize = sizeof(szCentralProfile);
|
|
|
|
lResult = RegQueryValueEx(hkeyEntry,
|
|
PROFILE_CENTRAL_PROFILE,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE) szCentralProfile,
|
|
&dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Cannot get central profile for <%s>, user is not roaming."), szEntryName));
|
|
goto Next;
|
|
}
|
|
|
|
szCentralProfile[MAX_PATH - 1] = TEXT('\0');
|
|
|
|
if (lstrlen(szCentralProfile) == 0)
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Central profile is empty for <%s>, user is not roaming."), szEntryName));
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// We got a central profile for the user, check if it belongs to a mandatory/readonly user
|
|
//
|
|
|
|
dwSize = sizeof(dwProfileState);
|
|
|
|
lResult = RegQueryValueEx(hkeyEntry,
|
|
PROFILE_STATE,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE) &dwProfileState,
|
|
&dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Cannot get profile state for <%s>, not setting the Preference key."), szEntryName));
|
|
goto Next;
|
|
}
|
|
|
|
if (dwProfileState & PROFILE_MANDATORY)
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : <%s>'s profile is mandatory or readonly, not setting the Preference key."), szEntryName));
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// We got a roaming user here, create the "Prefrence" key, set the ACL on it.
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : Central profile is <%s>, state is <%08X>, user is roaming."), szCentralProfile, dwProfileState));
|
|
|
|
hr = SetupPreferenceKey(szEntryName);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : SetupPrefrenceKey failed for <%s>, error = %d"), szEntryName, lResult));
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// Try to see if we have user preference value already set in the entry
|
|
//
|
|
|
|
dwSize = sizeof(dwUserPreference);
|
|
|
|
lResult = RegQueryValueEx(hkeyEntry,
|
|
USER_PREFERENCE,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE) &dwUserPreference,
|
|
&dwSize);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
goto Next;
|
|
}
|
|
|
|
//
|
|
// We found an existing user preference value, set it to the new location
|
|
//
|
|
|
|
lResult = RegOpenKeyEx(hkeyEntry,
|
|
PREFERENCE_KEYNAME,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hkeyPreference);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to open <%s> preference key, error = %d"), szEntryName, lResult));
|
|
goto Next;
|
|
}
|
|
|
|
lResult = RegSetValueEx(hkeyPreference,
|
|
USER_PREFERENCE,
|
|
0,
|
|
REG_DWORD,
|
|
(CONST BYTE*) &dwUserPreference,
|
|
sizeof(dwUserPreference));
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("ReaclProfileListEntries : failed to set <%s> preference value, error = %d"), szEntryName, lResult));
|
|
goto Next;
|
|
}
|
|
|
|
Next:
|
|
|
|
if (hkeyPreference)
|
|
{
|
|
RegCloseKey(hkeyPreference);
|
|
hkeyPreference = NULL;
|
|
}
|
|
|
|
if (hkeyEntry)
|
|
{
|
|
RegCloseKey(hkeyEntry);
|
|
hkeyEntry = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (hkeyProfileList)
|
|
RegCloseKey(hkeyProfileList);
|
|
|
|
if (psdProfileList)
|
|
LocalFree(psdProfileList);
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("ReaclProfileListEntries : done!")));
|
|
|
|
return hr;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// CallFaxServiceAPI()
|
|
//
|
|
// Purpose: Call the SecureFaxServiceDirectories() API in fxsocm.dll to set
|
|
// the special DACLs on some folders under
|
|
// "All Users\Application Data" directory
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 08/21/2002 mingzhu Created
|
|
//
|
|
//*****************************************************************************
|
|
|
|
HRESULT CallFaxServiceAPI()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
TCHAR szDir[MAX_PATH];
|
|
HMODULE hFxsocm = NULL;
|
|
DWORD dwErr;
|
|
typedef HRESULT (WINAPI *PFN_FAXAPI)(LPCTSTR);
|
|
PFN_FAXAPI pfnFaxAPI = NULL;
|
|
TCHAR szCommonAppData[MAX_PATH];
|
|
DWORD dwSize;
|
|
LPTSTR lpEnd = NULL;
|
|
DWORD cchEnd;
|
|
TCHAR szTemp[64];
|
|
|
|
//
|
|
// Init the debugging
|
|
//
|
|
|
|
InitDebugSupport(0);
|
|
|
|
//
|
|
// Get the all user profile path
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szCommonAppData);
|
|
if (!GetAllUsersProfileDirectoryEx(szCommonAppData, &dwSize, TRUE))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: GetAllUsersProfileDirectoryEx failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Append the application data to the path
|
|
//
|
|
|
|
lpEnd = CheckSlashEx(szCommonAppData, ARRAYSIZE(szCommonAppData), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : CheckSlashEx failed!")));
|
|
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
|
goto Exit;
|
|
}
|
|
|
|
if (!LoadString (g_hDllInstance, IDS_SH_APPDATA, szTemp, ARRAYSIZE(szTemp)))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : LoadString failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = StringCchCopy (lpEnd, cchEnd, szTemp);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI : StringCchCopy failed, hr = %08X"), hr));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Load the dll and call the API
|
|
//
|
|
|
|
hr = SafeExpandEnvironmentStrings(TEXT("%systemroot%\\system32\\setup\\fxsocm.dll"), szDir, ARRAYSIZE(szDir));
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: SafeExpandEnvironmentStrings failed, hr = %08X"), hr));
|
|
goto Exit;
|
|
}
|
|
|
|
hFxsocm = LoadLibrary(szDir);
|
|
if (!hFxsocm)
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: LoadLibrary failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
pfnFaxAPI = (PFN_FAXAPI) GetProcAddress(hFxsocm, "SecureFaxServiceDirectories");
|
|
if (!pfnFaxAPI)
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("CallFaxServiceAPI: GetProcAddress failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pfnFaxAPI(szCommonAppData);
|
|
|
|
Exit:
|
|
|
|
if (hFxsocm)
|
|
FreeLibrary(hFxsocm);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// SecureCommonProfiles()
|
|
//
|
|
// Purpose: Set the DACLs for the all user's profile and default profile.
|
|
// It will be executed after the FAT->NTFS conversion. We will
|
|
// apply a security template to the all user's profile to ensure
|
|
// a proper DACL for the Windows components, other apps that set
|
|
// specific DACLs under All User's profile will remain everyone(F)
|
|
// since we have no idea what DACL should we set to.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 09/18/2002 mingzhu Created
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//
|
|
// Required typedefs for the API we need to call, SceConfigSystem.
|
|
//
|
|
|
|
#include "secedit.h"
|
|
|
|
typedef SCESTATUS (WINAPI *PFN_SceConfigureSystem)
|
|
(
|
|
IN LPTSTR SystemName OPTIONAL,
|
|
IN PCWSTR InfFileName OPTIONAL,
|
|
IN PCWSTR DatabaseName,
|
|
IN PCWSTR LogFileName OPTIONAL,
|
|
IN DWORD ConfigOptions,
|
|
IN AREA_INFORMATION Area,
|
|
IN PSCE_AREA_CALLBACK_ROUTINE pCallback OPTIONAL,
|
|
IN HANDLE hCallbackWnd OPTIONAL,
|
|
OUT PDWORD pdWarning OPTIONAL
|
|
);
|
|
|
|
|
|
HRESULT SecureCommonProfiles()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HMODULE hSceCli = NULL;
|
|
DWORD dwErr;
|
|
SCESTATUS status;
|
|
TCHAR szWindows[64];
|
|
TCHAR szInfFile[MAX_PATH]; //TEXT("%SystemRoot%\\Inf\\ProfSec.Inf");
|
|
TCHAR szDatabase[MAX_PATH]; //TEXT("%SystemRoot%\\Security\\Database\\ProfSec.sdb");
|
|
TCHAR szLogFile[MAX_PATH]; //TEXT("%SystemRoot%\\Security\\Log\\ProfSec.log");
|
|
DWORD dwWarning;
|
|
DWORD dwOptions;
|
|
PFN_SceConfigureSystem pfn_SceConfigureSystem = NULL;
|
|
|
|
InitDebugSupport(0);
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("SecureCommonProfile: Entering...")));
|
|
|
|
//
|
|
// 1. First set a series environment variables that used in the inf file
|
|
//
|
|
|
|
PrepareEnvironmentVariables();
|
|
|
|
//
|
|
// 2. Load the security library and get the function
|
|
//
|
|
|
|
hSceCli = LoadLibrary(TEXT("SceCli.dll"));
|
|
if (!hSceCli)
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: LoadLibrary failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
pfn_SceConfigureSystem = (PFN_SceConfigureSystem) GetProcAddress (hSceCli, "SceConfigureSystem");
|
|
if (!pfn_SceConfigureSystem)
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: GetProcAddress failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// 3. Get the windows directory
|
|
//
|
|
|
|
if (!GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows)))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: GetWindowsDirectory failed, error = %d"), dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// 4. Get the path for our INF file
|
|
//
|
|
|
|
hr = StringCchPrintf(szInfFile, ARRAYSIZE(szInfFile), TEXT("%s\\Inf\\ProfSec.Inf"), szWindows);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// 5. Get the path for the data base
|
|
//
|
|
|
|
hr = StringCchPrintf(szDatabase, ARRAYSIZE(szDatabase), TEXT("%s\\Security\\Database\\ProfSec.sdb"), szWindows);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// 6. Get the path for the log file
|
|
//
|
|
|
|
hr = StringCchPrintf(szLogFile, ARRAYSIZE(szLogFile), TEXT("%s\\Security\\Logs\\ProfSec.log"), szWindows);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: StringCchPrintf failed, hr = %08X"), hr));
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// 7. Call the API
|
|
//
|
|
|
|
dwOptions = SCE_OVERWRITE_DB | SCE_VERBOSE_LOG;
|
|
|
|
status = pfn_SceConfigureSystem(NULL, // System Name
|
|
szInfFile, // InfFileName
|
|
szDatabase, // DatabaseName
|
|
szLogFile, // LogFileName
|
|
dwOptions, // Options
|
|
AREA_FILE_SECURITY, // Area information
|
|
NULL, // Area call back
|
|
NULL, // Call back window
|
|
&dwWarning); // Warning
|
|
|
|
if (status != SCESTATUS_SUCCESS)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SecureCommonProfile: SceConfigureSystem failed, status = %d, warning = %d"), status, dwWarning));
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("SecureCommonProfile: Success!")));
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
|
|
if (hSceCli)
|
|
FreeLibrary(hSceCli);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// SetEnvFromResource()
|
|
//
|
|
// Purpose: Get the localized strings for subfolders of all user's profile
|
|
// and set it to the environment variable
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 09/18/2002 mingzhu Created
|
|
//
|
|
//*****************************************************************************
|
|
|
|
HRESULT SetEnvFromResource(DWORD dwResID, LPCTSTR szEnvVar, LPTSTR lpEnd, size_t cchEnd, LPTSTR szBuffer)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DWORD dwErr;
|
|
DWORD dwIndex;
|
|
|
|
for (dwIndex = 0; dwIndex < g_dwNumCommonShellFolders; dwIndex++)
|
|
{
|
|
if (c_CommonShellFolders[dwIndex].iFolderID == dwResID)
|
|
{
|
|
hr = StringCchCopy (lpEnd, cchEnd, c_CommonShellFolders[dwIndex].szFolderLocation);
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("SetEnvFromResource : StringCchCopy for %s failed, hr = %08X"), szEnvVar, hr));
|
|
goto Exit;
|
|
}
|
|
|
|
if (!SetEnvironmentVariable(szEnvVar, szBuffer))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("SetEnvFromResource: SetEnvironmentVariable for %s failed, error = %d"), szEnvVar, dwErr));
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
goto Exit;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("SetEnvFromResource: set %s = %s"), szEnvVar, szBuffer));
|
|
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("SetEnvFromResource: can't find folder name for %s"), szEnvVar));
|
|
hr = S_FALSE;
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// PrepareEnvironmentVariables()
|
|
//
|
|
// Purpose: Prepare environment variables used by the profile security
|
|
// template file.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: HRESULT
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: Date Author Comment
|
|
// 09/18/2002 mingzhu Created
|
|
//
|
|
//*****************************************************************************
|
|
|
|
HRESULT PrepareEnvironmentVariables()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
DWORD dwSize;
|
|
DWORD dwErr;
|
|
LPTSTR lpEnd;
|
|
UINT cchEnd;
|
|
TCHAR szTemp[MAX_PATH];
|
|
|
|
//
|
|
// Set the default user profile path
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szBuffer);
|
|
if (!GetDefaultUserProfileDirectoryEx(szBuffer, &dwSize, TRUE))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: GetDefaultUserProfileDirectoryEx failed, error = %d"), dwErr));
|
|
}
|
|
else
|
|
{
|
|
if (!SetEnvironmentVariable(TEXT("DEFAULTUSERPROFILE"), szBuffer))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: SetEnvironmentVariable for default user failed, error = %d"), dwErr));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the all users profile path
|
|
//
|
|
|
|
dwSize = ARRAYSIZE(szBuffer);
|
|
if (!GetAllUsersProfileDirectoryEx(szBuffer, &dwSize, TRUE))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: GetAllUsersProfileDirectoryEx failed, error = %d"), dwErr));
|
|
}
|
|
else
|
|
{
|
|
if (!SetEnvironmentVariable(TEXT("ALLUSERSPROFILE"), szBuffer))
|
|
{
|
|
dwErr = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables: SetEnvironmentVariable failed, error = %d"), dwErr));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set all the subfolders under all user's profile
|
|
//
|
|
lpEnd = CheckSlashEx(szBuffer, ARRAYSIZE(szBuffer), &cchEnd);
|
|
if (!lpEnd)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("PrepareEnvironmentVariables : CheckSlashEx failed!")));
|
|
}
|
|
else
|
|
{
|
|
SetEnvFromResource(IDS_SH_APPDATA, TEXT("COMMON_APPDATA"), lpEnd, cchEnd, szBuffer);
|
|
SetEnvFromResource(IDS_SH_DESKTOP, TEXT("COMMON_DESKTOP"), lpEnd, cchEnd, szBuffer);
|
|
SetEnvFromResource(IDS_SH_FAVORITES, TEXT("COMMON_FAVORITES"), lpEnd, cchEnd, szBuffer);
|
|
SetEnvFromResource(IDS_SH_STARTMENU, TEXT("COMMON_STARTMENU"), lpEnd, cchEnd, szBuffer);
|
|
SetEnvFromResource(IDS_SH_TEMPLATES, TEXT("COMMON_TEMPLATES"), lpEnd, cchEnd, szBuffer);
|
|
SetEnvFromResource(IDS_SH_SHAREDDOCS, TEXT("COMMON_DOCS"), lpEnd, cchEnd, szBuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
hr = S_OK;
|
|
|
|
return hr;
|
|
}
|
|
|