WindowsXP-SP1/termsrv/tsappcmp/inipath.c
2020-09-30 16:53:49 +02:00

1068 lines
31 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*************************************************************************
*
* inipath.c
*
* Routines to manage per user mapping of Ini file paths
*
* copyright notice: Copyright 1998, Microsoft Corporation
*
*
*
*************************************************************************/
#include "precomp.h"
#pragma hdrstop
//*** Instance data
ULONG ulWinDirFlags = 0; // State of user's Windows directory
#define WINDIR_FLAGS_VALID 0x01 // The flags are initialized
#define WINDIR_USER_WINDIR_OK 0x02 // User's Windows dir exists
#define WINDOWS_DIR L"WINDOWS"
UNICODE_STRING WindowsDir = { sizeof(WINDOWS_DIR) - sizeof(UNICODE_NULL) , sizeof(WINDOWS_DIR) + sizeof(UNICODE_NULL), WINDOWS_DIR };
WCHAR gpwszDefaultUserName[MAX_PATH+1];
/******************************************************************************
*
* TermsrvPerUserWinDirMapping
*
*
/******************************************************************************/
BOOLEAN TermsrvPerUserWinDirMapping() {
#ifdef PERUSERBYREQUEST
PRTL_USER_PROCESS_PARAMETERS pUserParam;
PWCHAR pwch, pwchext;
WCHAR pwcAppName[MAX_PATH+1];
ULONG ulCompat=0, ulAppType=0;
// Get the path of the executable name
pUserParam = NtCurrentPeb()->ProcessParameters;
// Get the executable name, if there's no \ just use the name as it is
pwch = wcsrchr(pUserParam->ImagePathName.Buffer, L'\\');
if (pwch) {
pwch++;
} else {
pwch = pUserParam->ImagePathName.Buffer;
}
wcscpy(pwcAppName, pwch);
pwch = pwcAppName;
if (_wcsicmp(pwch, L"ntvdm.exe")) {
// If not a 16 bit app
// Check if we should return the per user windows dir for this app
GetCtxAppCompatFlags(&ulCompat, &ulAppType);
if (!(ulCompat & TERMSRV_COMPAT_PERUSERWINDIR) ||
!(ulCompat & ulAppType)) {
//
// Let the standard GetWindowsDirectory call return the actual path
//
return FALSE;
}
}
return TRUE;
#else
ULONG ulCompat=0, ulAppType = 0;
// Check if we should return the system windows dir for this app
GetCtxAppCompatFlags(&ulCompat, &ulAppType);
if ((ulCompat & CITRIX_COMPAT_SYSWINDIR) &&
(ulCompat & ulAppType)) {
return FALSE;
} else {
return TRUE;
}
#endif
}
/******************************************************************************
*
* TermsrvBuildIniFileName
*
* Build the INI file name based on the INIPATH or HOMEPATH (if no INIPATH)
*
* ENTRY:
* pFQName (output)
* Buffer to place fully qualified INI file name
* pBaseFileName (input)
* pointer to buffer containing base INI file name
*
* EXIT:
* NTSTATUS
*
*****************************************************************************/
NTSTATUS
TermsrvBuildIniFileName(
OUT PUNICODE_STRING pFQName,
IN PUNICODE_STRING pBaseFileName
)
{
NTSTATUS Status;
USHORT indexLastWChar;
ULONG ulCompat, ulAppType=0;
//Added By SalimC
/*
* If in install mode, use the base windows directory
* like a stock NT.
*/
if( IsSystemLUID() || TermsrvAppInstallMode() ) {
return( STATUS_UNSUCCESSFUL );
}
//END SalimC
if (!TermsrvPerUserWinDirMapping()) {
return( STATUS_UNSUCCESSFUL );
}
#if 0
GetCtxAppCompatFlags(&ulCompat, &ulAppType);
if (((ulCompat & TERMSRV_COMPAT_SYSWINDIR) && (ulCompat & ulAppType))) {
return STATUS_UNSUCCESSFUL;
}
#endif
Status = GetPerUserWindowsDirectory( pFQName );
if ( NT_SUCCESS( Status ) ) {
/*
* Add a '\' if one's not already there
*/
if ( indexLastWChar = pFQName->Length / sizeof( WCHAR ) ) {
if ( pFQName->Buffer[--indexLastWChar] != L'\\' ) {
Status = RtlAppendUnicodeToString( pFQName, L"\\" );
}
}
/*
* Append the base file name to the fully qualified directory name
*/
if ( NT_SUCCESS( Status ) ) {
Status = RtlAppendUnicodeStringToString( pFQName, pBaseFileName );
}
}
return( Status );
}
/******************************************************************************
*
* GetPerUserWindowsDirectory
*
* Get the user's INI file directory
*
* ENTRY:
* pFQName (output)
* Buffer to place fully qualified INI file name
*
* EXIT:
* NTSTATUS
*
*****************************************************************************/
NTSTATUS
GetPerUserWindowsDirectory(
OUT PUNICODE_STRING pFQName
)
{
NTSTATUS Status;
int indexLastWChar;
USHORT Length;
#if 0 //Bug fix #340691: Inherit the security
PSECURITY_ATTRIBUTES psa = NULL;
#endif //Bug fix #340691: Inherit the security
UNICODE_STRING UserProfilePath;
WCHAR* pwszFQProfileName;
#if DBG
char pszFile[MAX_PATH+1];
#endif
UNICODE_STRING BaseHomePathVariableName, BaseHomeDriveVariableName;
/*
* If in install mode, use the base windows directory
* like a stock NT.
*/
if( IsSystemLUID() || TermsrvAppInstallMode() ) {
//Status = GetEnvPath( pFQName, NULL, &BaseWindowsDirectory );
return( STATUS_UNSUCCESSFUL );
}
/*
* Check for HOMEDRIVE and HOMEPATH
*/
RtlInitUnicodeString(&BaseHomeDriveVariableName,L"HOMEDRIVE");
RtlInitUnicodeString(&BaseHomePathVariableName,L"HOMEPATH");
if (!NT_SUCCESS(Status = GetEnvPath( pFQName, &BaseHomeDriveVariableName,
&BaseHomePathVariableName ))){
if (Status == STATUS_BUFFER_TOO_SMALL) {
// Need 2 bytes for the "\" character to cat FQN and WindowsDir
Length = pFQName->Length + sizeof(WCHAR) + WindowsDir.Length;
#if DBG
DbgPrint("pFQName->Length = %u WindowsDir.Length = %u Length = %u\n",
pFQName->Length, WindowsDir.Length, Length);
#endif
pFQName->Length = Length;
#if DBG
DbgPrint("\nGetEnvPath return STATUS_BUFFER_TOO_SMALL\n");
#endif
} else {
#if DBG
DbgPrint("GetEnvPath failed with Status %lx\n",Status);
#endif
}
return Status;
}
/*
* If the user profile is Default User then use the
* base windows directory.
*/
if (pwszFQProfileName = wcsrchr( pFQName->Buffer, L'\\' )) {
if (_wcsnicmp(pwszFQProfileName+1, gpwszDefaultUserName, MAX_PATH+1) == 0) {
return STATUS_UNSUCCESSFUL;
}
}
/*
* Check buffer length
*/
Length = pFQName->Length + sizeof(WCHAR) + WindowsDir.Length;
// take into account the NULL terminator character
if (pFQName->MaximumLength < Length + 1) {
// Need 2 bytes for the NULL terminator
Length += sizeof(WCHAR);
pFQName->Length = Length;
Status = STATUS_BUFFER_TOO_SMALL;
goto done;
}
/*
* Add a trailing backslash if one's not already there
*/
if ( indexLastWChar = pFQName->Length / sizeof( WCHAR ) ) {
if ( pFQName->Buffer[--indexLastWChar] != L'\\' ) {
if (NT_SUCCESS(RtlAppendUnicodeToString( pFQName, L"\\" ))) {
/*
* Append "WINDOWS" to home dir
*/
Status = RtlAppendUnicodeStringToString( pFQName, &WindowsDir );
}
} else {
Status = RtlAppendUnicodeStringToString( pFQName, &WindowsDir );
}
}
if (NT_SUCCESS(Status)) {
// Check if we've already tried to create the user's windows path
if (ulWinDirFlags & WINDIR_FLAGS_VALID) {
if (ulWinDirFlags & WINDIR_USER_WINDIR_OK) {
goto done;
} else {
Status = STATUS_OBJECT_PATH_INVALID;
}
}
}
if ( NT_SUCCESS(Status) ) {
WCHAR Buffer[MAX_PATH+1];
SECURITY_ATTRIBUTES sa;
BOOL fDirCreated = FALSE;
// Mark this process's windows directory flags as valid
ulWinDirFlags |= WINDIR_FLAGS_VALID;
#if 0 //Bug fix #340691: Inherit the security
/*
* Since creating a security descriptor calls LookupAccountName,
* which is very time consuming, we only do that if we have to
* create the directory (which should rarely happen anyway).
*/
if ( CreateDirectoryW( (LPCWSTR)pFQName->Buffer, NULL ) &&
RemoveDirectoryW( (LPCWSTR)pFQName->Buffer ) &&
CtxCreateSecurityDescriptor( &sa ) ) {
psa = &sa;
}
/*
* Create windows directory if it doesn't exist
*/
if ( !CreateDirectoryW( (LPCWSTR)pFQName->Buffer, psa ) ) {
#endif //Bug fix #340691: Inherit the security
if ( !CreateDirectoryW( (LPCWSTR)pFQName->Buffer, NULL ) ) {
if ( (Status = GetLastError()) == ERROR_ALREADY_EXISTS ) {
Status = STATUS_SUCCESS;
}
#if DBG
else {
wcstombs( pszFile, pFQName->Buffer, sizeof(pszFile) );
DbgPrint( "KERNEL32: Error (%d) creating dir '%s'\n",
Status, pszFile );
}
#endif
} else {
fDirCreated = TRUE;
}
if (NT_SUCCESS(Status)) {
/*
* Create system directory if it doesn't exist
* (ignore return code)
*/
wcscpy( Buffer, pFQName->Buffer );
wcscat( Buffer, L"\\system" );
/*
* If the user's WINDOWS directory already existed but the
* WINDOWS\SYSTEM directory didn't, we need to create the
* security descriptor (this scenario is even rarer).
*/
#if 0 //Bug fix #340691: Inherit the security
if ( !psa && !fDirCreated &&
CreateDirectoryW( (LPCWSTR)Buffer, NULL ) &&
RemoveDirectoryW( (LPCWSTR)Buffer ) &&
CtxCreateSecurityDescriptor( &sa ) ) {
psa = &sa;
}
if ( !CreateDirectoryW( (LPCWSTR)Buffer, psa ) ) {
#endif
if ( !CreateDirectoryW( (LPCWSTR)Buffer, NULL ) ) {
#if DBG
if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
wcstombs( pszFile, Buffer, sizeof(pszFile) );
DbgPrint( "KERNEL32: Error (%d) creating dir '%s'\n",
GetLastError(), pszFile );
}
#endif
}
ulWinDirFlags |= WINDIR_USER_WINDIR_OK;
}
}
done:
#if 0 //Bug fix #340691: Inherit the security
if ( psa ) {
CtxFreeSecurityDescriptor( psa );
}
#endif //Bug fix #340691: Inherit the security
#if DDBG
wcstombs( pszFile, pFQName->Buffer, sizeof(pszFile) );
DbgPrint( "KERNEL32: ctxwindir='%s'\n", Status ? "Error" : pszFile );
#endif
return( Status );
}
/******************************************************************************
*
* GetEnvPath
*
* Retrieve a fully qualified path derived from a drive and dir env variable
*
* ENTRY:
* pFQPath (output)
* Buffer to place fully qualified path name
* pDriveVariableName (input)
* pointer to buffer containing env variable name for drive
* if NULL, pPathVariableName is a FQPath and no env vars are used
* pPathVariableName (input)
* pointer to buffer containing env variable name for dir
*
* EXIT:
* NTSTATUS
*
* If NTSTATUS is STATUS_BUFFER_TOO_SMALL, pFQPath->Length will be set
* to the buffer size needed.
*
*****************************************************************************/
NTSTATUS
GetEnvPath(
OUT PUNICODE_STRING pFQPath,
IN PUNICODE_STRING pDriveVariableName,
IN PUNICODE_STRING pPathVariableName
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING Path;
USHORT Length;
if ( pDriveVariableName ) {
/*
* First let's figure out how big the buffer needs to be
* We need to do this in case the buffer is too small and we
* need to return the required size
*/
RtlInitUnicodeString( &Path, NULL );
/*
* See if an env variable is defined for the drive
*/
Status = RtlQueryEnvironmentVariable_U( NULL, pDriveVariableName,
&Path);
switch ( Status ) {
case STATUS_BUFFER_TOO_SMALL:
Length = Path.Length; // Count how big this the drive spec is
break;
case STATUS_SUCCESS:
Status = STATUS_OBJECT_NAME_NOT_FOUND; // Something's wrong!
default:
goto done;
break;
}
/*
* See if an env variable is defined for the directory
*/
Path.Length = 0;
Status = RtlQueryEnvironmentVariable_U( NULL, pPathVariableName,
&Path);
switch ( Status ) {
case STATUS_BUFFER_TOO_SMALL:
Length += Path.Length; // Count how big this the dir spec is
break;
case STATUS_SUCCESS:
Status = STATUS_OBJECT_NAME_NOT_FOUND; // Something's wrong!
default:
goto done;
break;
}
/*
* If the buffer is too small, return the max size needed
*/
if ( Length + sizeof(WCHAR) > pFQPath->MaximumLength ) {
Status = STATUS_BUFFER_TOO_SMALL;
pFQPath->Length = Length + sizeof(WCHAR); // return size
goto done;
}
/*
* Get the env variable for the drive - should work if we got this far
*/
if ( Status = RtlQueryEnvironmentVariable_U( NULL, pDriveVariableName,
pFQPath) ) {
goto done;
}
/*
* Setup a receive buffer that points to the proper spot in pFQPath
*/
Length = pFQPath->Length; // Save the drive length
Path.Length = 0;
Path.MaximumLength = pFQPath->MaximumLength - Length;
(ULONG_PTR)Path.Buffer = (ULONG_PTR)pFQPath->Buffer + (ULONG)Length;
/*
* Get the env variable for the directory - should work if we got this far
* Then append it to the end of the drive spec
*/
if ( Status = RtlQueryEnvironmentVariable_U( NULL, pPathVariableName,
&Path) ) {
goto done;
}
/*
* Fix up the structure and we're done
*/
pFQPath->Length = Path.Length + Length;
} else {
/*
* pPathVariableName is really the FQ directory name
*/
if ( (pPathVariableName->Length + sizeof(WCHAR)) > pFQPath->MaximumLength ) {
Status = STATUS_BUFFER_TOO_SMALL;
pFQPath->Length = pPathVariableName->Length + sizeof(WCHAR); // return size
} else {
RtlCopyUnicodeString( pFQPath, pPathVariableName );
}
}
done:
return( Status );
}
/******************************************************************************
*
* TermsrvConvertSysRootToUserDir
*
* People who use INI files should never have to fully qualify them, but some
* people do anyway. What's more, some people do it wrong. For example,
* Microsoft PowerPoint 4.0 will call GetSystemDir (not GetWindowsDir) and
* will strip off "\system" to build a fully qualified path.
*
* ENTRY:
* pFQPath (input/output)
* Buffer containing fully qualified path name
*
* EXIT:
* NTSTATUS
*
* If NTSTATUS is not STATUS_SUCCESS, the directory was not converted
*
*****************************************************************************/
NTSTATUS
TermsrvConvertSysRootToUserDir(
OUT PUNICODE_STRING pFQPath,
IN PUNICODE_STRING BaseWindowsDirectory
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PWSTR p;
INT_PTR c;
WCHAR buffer[MAX_PATH+1];
UNICODE_STRING BaseFileName;
#if DDBG
char pszFile[MAX_PATH+1];
#endif
ULONG ulCompat, ulAppType=0;
/*
* If in install mode, use the base windows directory
* like a stock NT.
*/
if( IsSystemLUID() || TermsrvAppInstallMode() ) {
goto done;
}
#if 0
GetCtxAppCompatFlags(&ulCompat, &ulAppType);
if (((ulCompat & TERMSRV_COMPAT_SYSWINDIR) && (ulCompat & ulAppType))) {
goto done;
}
#endif
if (!TermsrvPerUserWinDirMapping()) {
goto done;
}
/*
* Check for NULL pointers
*/
if ( !pFQPath || !pFQPath->Buffer ) {
#if DBG
DbgPrint( "KERNEL32: Bogus ini path\n" );
#endif
goto done;
}
/*
* Validate and isolate the path
*/
if ( !(p = wcsrchr( pFQPath->Buffer, L'\\' ) ) ) {
#if DBG
DbgPrint( "KERNEL32: No backslash in ini path\n" );
#endif
goto done;
}
c = (INT_PTR)((ULONG_PTR)p - (ULONG_PTR)pFQPath->Buffer);
#if DDBG
wcstombs( pszFile, BaseWindowsDirectory->Buffer, sizeof(pszFile) );
DbgPrint( "KERNEL32: c(%d) c2(%d) BaseWinDir: '%s'\n",
c, (int)BaseWindowsDirectory->Length, pszFile );
wcstombs( pszFile, p, sizeof(pszFile) );
DbgPrint( "KERNEL32: BaseFileName: '%s'\n", pszFile );
#endif
if ( c != (INT_PTR)BaseWindowsDirectory->Length ) {
#if DDBG
DbgPrint( "KERNEL32: Path length diff from BaseWinDir length\n" );
#endif
goto done;
}
/*
* See if the path is the same as the base windows directory
*/
c /= sizeof(WCHAR);
if ( _wcsnicmp( BaseWindowsDirectory->Buffer, pFQPath->Buffer, (size_t)c ) ) {
#if DDBG
DbgPrint( "KERNEL32: Path diff from BaseWinDir\n" );
#endif
goto done;
}
/*
* Use the user's directory instead
*/
wcscpy( buffer, ++p );
RtlInitUnicodeString( &BaseFileName, buffer );
Status = TermsrvBuildIniFileName( pFQPath, &BaseFileName );
done:
#if DDBG
wcstombs( pszFile, pFQPath->Buffer, sizeof(pszFile) );
DbgPrint( "KERNEL32: Exit(%x) ConvertSystemRootToUserDir: '%s'\n",
Status, pszFile );
#endif
return( Status );
}
/******************************************************************************
*
* CtxCreateSecurityDescriptor
*
* This routine will create a security descriptor based on the specified
* generic flags. If this function succeeds, the caller needs to call
* CtxFreeSecurityDescriptor() when it is done using the descriptor.
*
* ENTRY:
* psa (output)
* Pointer to uninitialized security attributes structure
*
* EXIT:
* TRUE if successful, FALSE if error occurred
*
* (GetLastError() can be called to retrieve error code)
*
*****************************************************************************/
#if 0 //Bug fix #340691: Inherit the security
BOOL CtxCreateSecurityDescriptor( PSECURITY_ATTRIBUTES psa )
{
BOOL fSuccess = FALSE;
NTSTATUS Status;
PSID psidAdmin, psidUser;
UINT cb = sizeof( SECURITY_DESCRIPTOR ) + 2 * sizeof(PSID);
UINT cbAcl = sizeof(ACL);
PACL pAcl;
PSID *ppsidAdmin, *ppsidUser;
SID_IDENTIFIER_AUTHORITY gSystemSidAuthority = SECURITY_NT_AUTHORITY;
HANDLE hUserToken;
PTOKEN_USER pTokenUser = NULL;
DWORD cbNeeded;
/*
* Initialize pointers to dynamic memory blocks
*/
psa->lpSecurityDescriptor = NULL;
psidAdmin = NULL;
psidUser = NULL;
/*
* Get the SID of the bult-in Administrators group
*/
Status = RtlAllocateAndInitializeSid(
&gSystemSidAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,0,0,0,0,0,
&psidAdmin);
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("KERNEL32: Couldn't allocate Administrators SID (0x%x)\n", Status );
#endif
goto done;
}
/*
* Get the SID for the current user from their process token
*/
Status = NtOpenThreadToken(
NtCurrentThread(),
TOKEN_QUERY,
TRUE,
&hUserToken);
if (Status == STATUS_NO_TOKEN) {
Status = NtOpenProcessToken(
NtCurrentProcess(),
TOKEN_QUERY,
&hUserToken);
}
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("KERNEL32: Couldn't access process' token (0x%x)\n", Status );
#endif
RtlFreeHeap( RtlProcessHeap(), 0, psidAdmin );
goto done;
}
Status = NtQueryInformationToken(
hUserToken,
TokenUser,
NULL,
0,
&cbNeeded );
if (Status == STATUS_BUFFER_TOO_SMALL) {
pTokenUser = (PTOKEN_USER)RtlAllocateHeap( RtlProcessHeap(), 0, cbNeeded );
if (pTokenUser != NULL) {
Status = NtQueryInformationToken(
hUserToken,
TokenUser,
(LPVOID)pTokenUser,
cbNeeded,
&cbNeeded );
if (NT_SUCCESS(Status)) {
/*
* Make a copy of the user's SID
*/
psidUser = RtlAllocateHeap( RtlProcessHeap(), 0, RtlLengthSid(pTokenUser->User.Sid) );
if (psidUser != NULL) {
Status = RtlCopySid( RtlLengthSid(pTokenUser->User.Sid), psidUser, pTokenUser->User.Sid );
} else {
Status = STATUS_NO_MEMORY;
}
}
} else {
Status = STATUS_NO_MEMORY;
}
}
if (pTokenUser != NULL) {
RtlFreeHeap( RtlProcessHeap(), 0, pTokenUser );
}
NtClose(hUserToken);
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("KERNEL32: Couldn't query user's token (0x%x)\n", Status );
#endif
RtlFreeHeap( RtlProcessHeap(), 0, psidAdmin );
if (psidUser != NULL) {
RtlFreeHeap( RtlProcessHeap(), 0, psidUser );
}
goto done;
}
/*
* Figure out how much memory we need to allocate for the SD
*/
cbAcl += sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid( psidUser ) - sizeof(DWORD);
cbAcl += sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid( psidAdmin ) - sizeof(DWORD);
/*
* Allocate all the memory we need for the security descriptor
*/
if ( !(psa->lpSecurityDescriptor =
(PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, cb + cbAcl ) ) ) {
#if DBG
DbgPrint("KERNEL32: No memory to create security descriptor (%d)\n",
cb + cbAcl);
#endif
goto done;
}
/*
* Divvy up our memory block to include SIDs and ACLs
*/
ppsidAdmin = (PSID*)((ULONG_PTR)psa->lpSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR));
ppsidUser = (PSID*)((ULONG_PTR)ppsidAdmin + sizeof(PSID));
pAcl = (PACL)((ULONG_PTR)ppsidUser + sizeof(PSID));
/*
* Save the SIDs - the SIDs must not be freed until we're done
* using the security descriptor
*/
*ppsidAdmin = psidAdmin;
*ppsidUser = psidUser;
/*
* Initialize the rest of the security attributes structure
*/
psa->nLength = sizeof( SECURITY_ATTRIBUTES );
psa->bInheritHandle = FALSE;
/*
* Initialize the security descriptor
*/
if ( Status = RtlCreateSecurityDescriptor(
psa->lpSecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) initializing security descriptor\n",
Status );
#endif
goto done;
}
/*
* Set the owner
*/
if ( Status = RtlSetOwnerSecurityDescriptor( psa->lpSecurityDescriptor,
NULL, FALSE ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) setting security descriptor owner\n",
Status );
#endif
goto done;
}
/*
* Set the group
*/
if ( Status = RtlSetGroupSecurityDescriptor( psa->lpSecurityDescriptor,
psidAdmin, FALSE ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) setting security descriptor owner\n",
Status );
#endif
goto done;
}
/*
* Initialize the ACL
*/
if ( Status = RtlCreateAcl( pAcl, cbAcl, ACL_REVISION ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) initializing ACL\n",
Status );
#endif
goto done;
}
/*
* Add user ACE
*/
if ( Status = CtxAddAccessAllowedAce( pAcl, ACL_REVISION, GENERIC_ALL, psidUser, 0 ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) adding user ACE\n", Status );
#endif
goto done;
}
/*
* Add Administrators ACE
*/
if ( Status = CtxAddAccessAllowedAce( pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin, 1 ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) adding admin ACE\n", Status );
#endif
goto done;
}
/*
* Set the discretionary ACL
*/
if ( Status = RtlSetDaclSecurityDescriptor( psa->lpSecurityDescriptor,
TRUE, pAcl, FALSE ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%08X) setting security descriptor owner\n",
Status );
#endif
goto done;
}
fSuccess = TRUE;
done:
if ( !fSuccess && psa->lpSecurityDescriptor ) {
CtxFreeSecurityDescriptor( psa );
}
return( fSuccess );
}
/******************************************************************************
*
* CtxFreeSecurityDescriptor
*
* This routine will free resources allocated in a corresponding
* CtxCreateSecurityDescriptor() call.
*
* ENTRY:
* psa (input)
* Pointer to security attributes
*
* EXIT:
* TRUE if successful, FALSE if error occurred
*
* (GetLastError() can be called to retrieve error code)
*
*****************************************************************************/
BOOL CtxFreeSecurityDescriptor( PSECURITY_ATTRIBUTES psa )
{
BOOL fSuccess = TRUE;
PSID *ppsidAdmin, *ppsidUser;
if ( psa->lpSecurityDescriptor ) {
ppsidAdmin = (PSID*)((ULONG_PTR)psa->lpSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR));
ppsidUser = (PSID*)((ULONG_PTR)ppsidAdmin + sizeof(PSID));
if ( *ppsidUser ) {
CtxFreeSID( *ppsidUser );
}
if ( *ppsidAdmin ) {
CtxFreeSID( *ppsidAdmin );
}
fSuccess = !LocalFree( psa->lpSecurityDescriptor );
#if DDBG
DbgPrint( "KERNEL32: fSuccess(%d) freeing security descriptor (%08X)\n",
fSuccess, psa->lpSecurityDescriptor );
#endif
}
return( fSuccess );
}
NTSTATUS
CtxAddAccessAllowedAce (
IN OUT PACL Acl,
IN ULONG AceRevision,
IN ACCESS_MASK AccessMask,
IN PSID Sid,
IN DWORD index
)
{
NTSTATUS Status;
ACE_HEADER *pHeader;
/*
* First add the ACL
*/
if ( !(Status = RtlAddAccessAllowedAce( Acl, AceRevision,
AccessMask, Sid ) ) ) {
/*
* Get the ACE
*/
if ( Status = RtlGetAce( Acl, index, &pHeader ) ) {
#if DBG
DbgPrint( "KERNEL32: Error (%X) from RtlGetAce\n", Status );
#endif
goto done;
}
/*
* Now set the inheritence bits
*/
pHeader->AceFlags |= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
}
done:
return( Status );
}
#endif //Bug fix #340691: Inherit the security
// from \nt\private\windows\gina\userenv\globals.h
#define PROFILE_LIST_PATH L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"
#define DEFAULT_USER_PROFILE L"DefaultUserProfile"
#define DEFAULT_USER L"Default User"
BOOL GetDefaultUserProfileName(
LPWSTR lpProfileDir,
LPDWORD lpcchSize
)
{
WCHAR* pwszProfileName;
BYTE pKeyValueInfo[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+(MAX_PATH+1)*sizeof(WCHAR)];
ULONG ulSize;
DWORD dwLength;
BOOL bRetVal = FALSE;
HKEY hKey;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING UnicodeString;
//
// Query for the Default User profile name
//
RtlInitUnicodeString(&UnicodeString, PROFILE_LIST_PATH);
InitializeObjectAttributes(&ObjectAttributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey( &hKey,
KEY_READ,
&ObjectAttributes );
//lResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, PROFILE_LIST_PATH,
// 0, KEY_READ, &hKey);
if (!NT_SUCCESS(Status)) {
#if DBG
DbgPrint("TSAppCmp:GetDefaultUserProfileName: Failed to open profile list key with 0x%x.",Status);
#endif
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
//lResult = RegQueryValueExW(hKey, DEFAULT_USER_PROFILE, NULL, &dwType,
// (LPBYTE) wszProfileName, &dwSize);
RtlInitUnicodeString(&UnicodeString, DEFAULT_USER_PROFILE);
Status = NtQueryValueKey( hKey,
&UnicodeString,
KeyValuePartialInformation,
pKeyValueInfo,
sizeof(pKeyValueInfo),
&ulSize);
pwszProfileName = (WCHAR*)(((PKEY_VALUE_PARTIAL_INFORMATION)pKeyValueInfo)->Data);
if (!NT_SUCCESS(Status)) {
lstrcpy (pwszProfileName, DEFAULT_USER);
}
NtClose(hKey);
//
// Save the result if possible
dwLength = lstrlen(pwszProfileName) + 1;
if (lpProfileDir) {
if (*lpcchSize >= dwLength) {
lstrcpy (lpProfileDir, pwszProfileName);
bRetVal = TRUE;
} else {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
} else {
SetLastError(ERROR_INVALID_PARAMETER);
}
*lpcchSize = dwLength;
return bRetVal;
}