function FindWinlogon(ASessionId: DWord): DWord;
var
PID, SessionId: DWord;
hSnap: THANDLE;
procEntry: TProcessEntry32;
begin
Result := 0;
hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap <> INVALID_HANDLE_VALUE) then
begin
procEntry.dwSize := Sizeof(PROCESSENTRY32);
PID := 0;
SessionId := 0;
if Process32First(hSnap, procEntry) then
begin
while Process32Next(hSnap, procEntry) do
begin
if Pos('winlogon.exe', LowerCase(procEntry.szExeFile)) > 0 then
begin
if ProcessIdToSessionId(procEntry.th32ProcessID, SessionId) then
begin
if SessionId = ASessionId then
begin
PID := procEntry.th32ProcessID;
Break;
end;
end
end;
end;
Result := PID;
end;
end;
end;
function RunProcessAsUser(APath: WideString): DWord;
var
pi: PROCESS_INFORMATION;
si: STARTUPINFOW;
dwSessionId, PID, DesiredAccess, dwCreationFlags: DWord;
hUserTokenDup, hPToken, hProcess: THANDLE;
begin
Result := 0;
RevertToSelf;
dwSessionId := WtsGetActiveConsoleSessionID;
PID := FindWinLogon(dwSessionId);
if PID <> 0 then
begin
hPToken := 0;
hProcess := OpenProcess(MAXIMUM_ALLOWED, False, PID);
DesiredAccess := TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY or TOKEN_DUPLICATE or
TOKEN_ASSIGN_PRIMARY or TOKEN_ADJUST_SESSIONID or TOKEN_READ or TOKEN_WRITE;
if OpenProcessToken(hProcess, DesiredAccess, hPToken) then
begin
hUserTokenDup := 0;
if DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, nil, SecurityIdentification, TokenPrimary, hUserTokenDup) then
begin
ZeroMemory(@si, SizeOf(si));
ZeroMemory(@pi, SizeOf(pi));
dwCreationFlags := NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT;
if CreateProcessAsUserW(hUserTokenDup, PWideChar(APath), nil, nil, nil, False, dwCreationFlags, nil, nil, si, pi) then
Result := pi.dwProcessId
end
end
end;
end;