/************************************************************************* * * 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; }