484 lines
11 KiB
C
484 lines
11 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1997.
|
||
|
//
|
||
|
// File: util.c
|
||
|
//
|
||
|
// Contents:
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 5-21-97 RichardW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <ntlsa.h>
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <userenv.h>
|
||
|
#include <userenvp.h>
|
||
|
|
||
|
#include <lm.h>
|
||
|
#include "moveme.h"
|
||
|
|
||
|
|
||
|
#define USER_SHELL_FOLDER TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders")
|
||
|
#define PROFILE_LIST_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList")
|
||
|
#define PROFILE_FLAGS TEXT("Flags")
|
||
|
#define PROFILE_STATE TEXT("State")
|
||
|
#define PROFILE_IMAGE_VALUE_NAME TEXT("ProfileImagePath")
|
||
|
#define PROFILE_CENTRAL_PROFILE TEXT("CentralProfile")
|
||
|
#define CONFIG_FILE_PATH TEXT("%SystemRoot%\\Profiles\\")
|
||
|
#define USER_PREFERENCE TEXT("UserPreference")
|
||
|
#define PROFILE_BUILD_NUMBER TEXT("BuildNumber")
|
||
|
#define TEMP_PROFILE_NAME_BASE TEXT("TEMP")
|
||
|
#define DELETE_ROAMING_CACHE TEXT("DeleteRoamingCache")
|
||
|
#define USER_PROFILE_MUTEX TEXT("userenv: User Profile Mutex")
|
||
|
|
||
|
LPTSTR
|
||
|
SidToString(
|
||
|
PSID Sid
|
||
|
)
|
||
|
{
|
||
|
UNICODE_STRING String ;
|
||
|
NTSTATUS Status ;
|
||
|
|
||
|
Status = RtlConvertSidToUnicodeString( &String, Sid, TRUE );
|
||
|
|
||
|
if ( NT_SUCCESS( Status ) )
|
||
|
{
|
||
|
return String.Buffer ;
|
||
|
}
|
||
|
return NULL ;
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FreeSidString(
|
||
|
LPTSTR SidString
|
||
|
)
|
||
|
{
|
||
|
UNICODE_STRING String ;
|
||
|
|
||
|
RtlInitUnicodeString( &String, SidString );
|
||
|
|
||
|
RtlFreeUnicodeString( &String );
|
||
|
}
|
||
|
|
||
|
//*************************************************************
|
||
|
//
|
||
|
// GetUserProfileDirectory()
|
||
|
//
|
||
|
// Purpose: Returns the root of the user's profile directory.
|
||
|
//
|
||
|
// Parameters: hToken - User's token
|
||
|
// lpProfileDir - Output buffer
|
||
|
// lpcchSize - Size of output buffer
|
||
|
//
|
||
|
// Return: TRUE if successful
|
||
|
// FALSE if an error occurs
|
||
|
//
|
||
|
// Comments: If false is returned, lpcchSize holds the number of
|
||
|
// characters needed.
|
||
|
//
|
||
|
// History: Date Author Comment
|
||
|
// 9/18/95 ericflo Created
|
||
|
//
|
||
|
//*************************************************************
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
GetUserProfileDirectoryFromSid(
|
||
|
PSID Sid,
|
||
|
LPTSTR lpProfileDir,
|
||
|
LPDWORD lpcchSize
|
||
|
)
|
||
|
{
|
||
|
DWORD dwLength = MAX_PATH * sizeof(TCHAR);
|
||
|
DWORD dwType;
|
||
|
BOOL bRetVal = FALSE;
|
||
|
LPTSTR lpSidString;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
TCHAR szDirectory[MAX_PATH];
|
||
|
HKEY hKey;
|
||
|
LONG lResult;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Retrieve the user's sid string
|
||
|
//
|
||
|
|
||
|
lpSidString = SidToString( Sid );
|
||
|
|
||
|
if (!lpSidString) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check the registry
|
||
|
//
|
||
|
|
||
|
lstrcpy(szBuffer, PROFILE_LIST_PATH);
|
||
|
lstrcat(szBuffer, TEXT("\\"));
|
||
|
lstrcat(szBuffer, lpSidString);
|
||
|
|
||
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ,
|
||
|
&hKey);
|
||
|
|
||
|
if (lResult != ERROR_SUCCESS) {
|
||
|
FreeSidString(lpSidString);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
lResult = RegQueryValueEx(hKey,
|
||
|
PROFILE_IMAGE_VALUE_NAME,
|
||
|
NULL,
|
||
|
&dwType,
|
||
|
(LPBYTE) szBuffer,
|
||
|
&dwLength);
|
||
|
|
||
|
if (lResult != ERROR_SUCCESS) {
|
||
|
RegCloseKey (hKey);
|
||
|
FreeSidString(lpSidString);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Clean up
|
||
|
//
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
FreeSidString(lpSidString);
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Expand and get the length of string
|
||
|
//
|
||
|
|
||
|
ExpandEnvironmentStrings(szBuffer, szDirectory, MAX_PATH);
|
||
|
|
||
|
dwLength = lstrlen(szDirectory) + 1;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Save the string if appropriate
|
||
|
//
|
||
|
|
||
|
if (lpProfileDir) {
|
||
|
|
||
|
if (*lpcchSize >= dwLength) {
|
||
|
lstrcpy (lpProfileDir, szDirectory);
|
||
|
bRetVal = TRUE;
|
||
|
|
||
|
} else {
|
||
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
*lpcchSize = dwLength;
|
||
|
|
||
|
return bRetVal;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SetUserProfileDirectory(
|
||
|
PSID Base,
|
||
|
PSID Copy
|
||
|
)
|
||
|
{
|
||
|
LPTSTR lpSidString;
|
||
|
TCHAR szBuffer[MAX_PATH];
|
||
|
HKEY hKey;
|
||
|
HKEY hNewKey ;
|
||
|
LONG lResult;
|
||
|
DWORD Disp ;
|
||
|
WCHAR CopyBuffer[ MAX_PATH ] ;
|
||
|
DWORD CopySize ;
|
||
|
DWORD ValueCount ;
|
||
|
DWORD ValueNameLen ;
|
||
|
DWORD ValueDataLen ;
|
||
|
PUCHAR Value ;
|
||
|
DWORD Type ;
|
||
|
DWORD Index ;
|
||
|
DWORD NameSize ;
|
||
|
//
|
||
|
// Retrieve the user's sid string
|
||
|
//
|
||
|
|
||
|
lpSidString = SidToString( Base );
|
||
|
|
||
|
if (!lpSidString) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check the registry
|
||
|
//
|
||
|
|
||
|
lstrcpy(szBuffer, PROFILE_LIST_PATH);
|
||
|
lstrcat(szBuffer, TEXT("\\"));
|
||
|
lstrcat(szBuffer, lpSidString);
|
||
|
|
||
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ,
|
||
|
&hKey);
|
||
|
|
||
|
FreeSidString( lpSidString );
|
||
|
|
||
|
if ( lResult != 0 )
|
||
|
{
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Retrieve the user's sid string
|
||
|
//
|
||
|
|
||
|
lpSidString = SidToString( Copy );
|
||
|
|
||
|
if (!lpSidString) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check the registry
|
||
|
//
|
||
|
|
||
|
lstrcpy(szBuffer, PROFILE_LIST_PATH);
|
||
|
lstrcat(szBuffer, TEXT("\\"));
|
||
|
lstrcat(szBuffer, lpSidString);
|
||
|
|
||
|
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
||
|
szBuffer,
|
||
|
0,
|
||
|
TEXT(""),
|
||
|
REG_OPTION_NON_VOLATILE,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
NULL,
|
||
|
&hNewKey,
|
||
|
&Disp );
|
||
|
|
||
|
|
||
|
FreeSidString( lpSidString );
|
||
|
|
||
|
if ( lResult != 0 )
|
||
|
{
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy Key:
|
||
|
//
|
||
|
|
||
|
lResult = RegQueryInfoKey( hKey,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&ValueCount,
|
||
|
&ValueNameLen,
|
||
|
&ValueDataLen,
|
||
|
NULL,
|
||
|
NULL );
|
||
|
|
||
|
if ( lResult != 0 )
|
||
|
{
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
Value = LocalAlloc( LMEM_FIXED, ValueDataLen );
|
||
|
|
||
|
if ( Value )
|
||
|
{
|
||
|
Index = 0 ;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
CopySize = ValueDataLen ;
|
||
|
NameSize = MAX_PATH ;
|
||
|
|
||
|
lResult = RegEnumValue( hKey,
|
||
|
Index,
|
||
|
CopyBuffer,
|
||
|
&NameSize,
|
||
|
NULL,
|
||
|
&Type,
|
||
|
Value,
|
||
|
&CopySize );
|
||
|
|
||
|
if ( lResult == 0 )
|
||
|
{
|
||
|
lResult = RegSetValueEx( hNewKey,
|
||
|
CopyBuffer,
|
||
|
0,
|
||
|
Type,
|
||
|
Value,
|
||
|
CopySize );
|
||
|
}
|
||
|
|
||
|
ValueCount-- ;
|
||
|
Index ++ ;
|
||
|
|
||
|
} while ( ValueCount );
|
||
|
|
||
|
LocalFree( Value );
|
||
|
|
||
|
}
|
||
|
|
||
|
lResult = RegSetValueEx( hNewKey,
|
||
|
TEXT("Sid"),
|
||
|
0,
|
||
|
REG_BINARY,
|
||
|
Copy,
|
||
|
RtlLengthSid( Copy )
|
||
|
);
|
||
|
|
||
|
if (lResult == 0) {
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
MyRegSaveKey(
|
||
|
HKEY Key,
|
||
|
LPTSTR File,
|
||
|
LPSECURITY_ATTRIBUTES lpsa
|
||
|
)
|
||
|
{
|
||
|
BOOL bResult = TRUE;
|
||
|
LONG error;
|
||
|
NTSTATUS Status;
|
||
|
BOOLEAN WasEnabled;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Enable the restore privilege
|
||
|
//
|
||
|
|
||
|
Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &WasEnabled);
|
||
|
|
||
|
if (NT_SUCCESS(Status))
|
||
|
{
|
||
|
error = RegSaveKey( Key, File, lpsa );
|
||
|
|
||
|
Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
error = RtlNtStatusToDosError( Status );
|
||
|
}
|
||
|
|
||
|
return error ;
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
GetPrimaryDomain(
|
||
|
PWSTR Domain
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status, IgnoreStatus;
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
LSA_HANDLE LsaHandle;
|
||
|
SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
|
||
|
PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo;
|
||
|
BOOL PrimaryDomainPresent = FALSE;
|
||
|
|
||
|
//
|
||
|
// Set up the Security Quality Of Service
|
||
|
//
|
||
|
|
||
|
SecurityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
||
|
SecurityQualityOfService.ImpersonationLevel = SecurityImpersonation;
|
||
|
SecurityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
||
|
SecurityQualityOfService.EffectiveOnly = FALSE;
|
||
|
|
||
|
//
|
||
|
// Set up the object attributes to open the Lsa policy object
|
||
|
//
|
||
|
|
||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||
|
NULL,
|
||
|
0L,
|
||
|
(HANDLE)NULL,
|
||
|
NULL);
|
||
|
ObjectAttributes.SecurityQualityOfService = &SecurityQualityOfService;
|
||
|
|
||
|
//
|
||
|
// Open the local LSA policy object
|
||
|
//
|
||
|
|
||
|
Status = LsaOpenPolicy( NULL,
|
||
|
&ObjectAttributes,
|
||
|
POLICY_VIEW_LOCAL_INFORMATION,
|
||
|
&LsaHandle
|
||
|
);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DebugLog((DEB_ERROR, "Failed to open local LsaPolicyObject, Status = 0x%lx\n", Status));
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the primary domain info
|
||
|
//
|
||
|
Status = LsaQueryInformationPolicy(LsaHandle,
|
||
|
PolicyPrimaryDomainInformation,
|
||
|
(PVOID *)&PrimaryDomainInfo);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
DebugLog((DEB_ERROR, "Failed to query primary domain from Lsa, Status = 0x%lx\n", Status));
|
||
|
|
||
|
IgnoreStatus = LsaClose(LsaHandle);
|
||
|
ASSERT(NT_SUCCESS(IgnoreStatus));
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the primary domain name into the return string
|
||
|
//
|
||
|
|
||
|
if (PrimaryDomainInfo->Sid != NULL) {
|
||
|
|
||
|
PrimaryDomainPresent = TRUE;
|
||
|
|
||
|
if ( Domain )
|
||
|
{
|
||
|
CopyMemory( Domain, PrimaryDomainInfo->Name.Buffer,
|
||
|
PrimaryDomainInfo->Name.Length + 2 );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We're finished with the Lsa
|
||
|
//
|
||
|
|
||
|
IgnoreStatus = LsaFreeMemory(PrimaryDomainInfo);
|
||
|
ASSERT(NT_SUCCESS(IgnoreStatus));
|
||
|
|
||
|
IgnoreStatus = LsaClose(LsaHandle);
|
||
|
ASSERT(NT_SUCCESS(IgnoreStatus));
|
||
|
|
||
|
|
||
|
return(PrimaryDomainPresent);
|
||
|
}
|