-
Notifications
You must be signed in to change notification settings - Fork 35
/
NtUtils.Environment.User.pas
117 lines (89 loc) · 2.93 KB
/
NtUtils.Environment.User.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
unit NtUtils.Environment.User;
{
The functions for constructing user environment using a token.
}
interface
uses
Ntapi.WinNt, Ntapi.ntseapi, NtUtils;
const
TOKEN_CREATE_ENVIRONMEMT = TOKEN_QUERY or TOKEN_DUPLICATE or TOKEN_IMPERSONATE;
// Prepare an environment for a user. If the token is not specified, the
// function returns only system environmental variables. Supports AppContainers.
function UnvxCreateUserEnvironment(
out Environment: IEnvironment;
[opt, Access(TOKEN_CREATE_ENVIRONMEMT)] hxToken: IHandle = nil;
InheritCurrent: Boolean = False;
FixAppContainers: Boolean = True
): TNtxStatus;
// Update an environment to point to correct folders in case of AppContainer
function UnvxUpdateAppContainerEnvironment(
var Environment: IEnvironment;
const AppContainerSid: ISid
): TNtxStatus;
implementation
uses
Ntapi.UserEnv, NtUtils.Profiles, NtUtils.Ldr, NtUtils.Tokens,
NtUtils.Tokens.Info, NtUtils.Security.Sid, NtUtils.Objects, Ntapi.Versions,
NtUtils.Environment;
{$BOOLEVAL OFF}
{$IFOPT R+}{$DEFINE R+}{$ENDIF}
{$IFOPT Q+}{$DEFINE Q+}{$ENDIF}
function UnvxCreateUserEnvironment;
var
hToken: THandle;
EnvBlock: PEnvironment;
Package: ISid;
begin
Result := LdrxCheckDelayedImport(delayed_CreateEnvironmentBlock);
if not Result.IsSuccess then
Exit;
if Assigned(hxToken) then
begin
// Add support for pseudo-handles
Result := NtxExpandToken(hxToken, TOKEN_CREATE_ENVIRONMEMT);
if not Result.IsSuccess then
Exit;
hToken := hxToken.Handle;
end
else
hToken := 0; // System environment only
Result.Location := 'CreateEnvironmentBlock';
if hToken <> 0 then
Result.LastCall.Expects<TTokenAccessMask>(TOKEN_CREATE_ENVIRONMEMT);
Result.Win32Result := CreateEnvironmentBlock(EnvBlock, hToken,
InheritCurrent);
// Capture the environment block
if Result.IsSuccess then
Environment := RtlxCaptureEnvironment(EnvBlock)
else
Exit;
// On Win8+ we might need to fix AppContainer profile path
if FixAppContainers and Assigned(hxToken) and RtlOsVersionAtLeast(OsWin8) then
begin
// Get the package SID
Result := NtxQuerySidToken(hxToken, TokenAppContainerSid, Package);
if not Result.IsSuccess then
Exit;
// Fix AppContainer paths
if Result.IsSuccess and Assigned(Package) then
Result := UnvxUpdateAppContainerEnvironment(Environment, Package);
end;
end;
function UnvxUpdateAppContainerEnvironment;
var
ProfilePath, TempPath: String;
begin
// Obtain the profile path
Result := UnvxQueryFolderAppContainer(AppContainerSid, ProfilePath);
if not Result.IsSuccess then
Exit;
// Fix AppData
Result := RtlxSetVariableEnvironment(Environment, 'LOCALAPPDATA', ProfilePath);
// Fix Temp
TempPath := ProfilePath + '\Temp';
if Result.IsSuccess then
Result := RtlxSetVariableEnvironment(Environment, 'TEMP', TempPath);
if Result.IsSuccess then
Result := RtlxSetVariableEnvironment(Environment, 'TMP', TempPath);
end;
end.