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
|
procedure CreateProcAsUserEx(const UserDomain, UserName, Password, CommandLine: string;
const Environment: PChar);
const
// default values for window stations and desktops
CreateProcDEFWINSTATION = 'WinSta0';
CreateProcDEFDESKTOP = 'Default';
CreateProcDOMUSERSEP = '\';
var
ConsoleTitle: string;
Help: string;
WinStaName: string;
DesktopName: string;
hUserToken: THandle;
hWindowStation: HWINSTA;
hDesktop: HDESK;
StartUpInfo: TStartUpInfo;
ProcInfo: TProcessInformation;
begin
// Step 1: check for the correct OS version
CheckOSVersion;
// Step 2: logon as the specified user
if not LogonUser(PChar(UserName), PChar(UserDomain), PChar(Password),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hUserToken) then
begin
case GetLastError of
ERROR_PRIVILEGE_NOT_HELD:
raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcPrivilegeMissing,
[GetPrivilegeDisplayName(SE_TCB_NAME), SE_TCB_NAME]);
ERROR_LOGON_FAILURE:
raise EJclCreateProcessError.CreateResRec(@RsCreateProcLogonUserError);
ERROR_ACCESS_DENIED:
raise EJclCreateProcessError.CreateResRec(@RsCreateProcAccessDenied);
else
raise EJclCreateProcessError.CreateResRec(@RsCreateProcLogonFailed);
end;
end;
// Step 3: give the new user access to the current WindowStation and Desktop
hWindowStation:= GetProcessWindowStation;
WinStaName := GetUserObjectName(hWindowStation);
if WinStaName = '' then
WinStaName := CreateProcDEFWINSTATION;
if not SetUserObjectFullAccess(hWindowStation) then
begin
CloseHandle(hUserToken);
raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcSetStationSecurityError, [WinStaName]);
end;
hDesktop := GetThreadDesktop(GetCurrentThreadId);
DesktopName := GetUserObjectName(hDesktop);
if DesktopName = '' then
DesktopName := CreateProcDEFDESKTOP;
if not SetUserObjectFullAccess(hDesktop) then
begin
CloseHandle(hUserToken);
raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcSetDesktopSecurityError, [DesktopName]);
end;
// Step 4: set the startup info for the new process
ConsoleTitle := UserDomain + UserName;
FillChar(StartUpInfo, SizeOf(StartUpInfo), #0);
with StartUpInfo do
begin
cb:= SizeOf(StartUpInfo);
lpTitle:= PChar(ConsoleTitle);
Help := WinStaName + '\' + DeskTopName;
lpDesktop:= PChar(Help);
end;
// Step 5: create the child process
if not CreateProcessAsUser(hUserToken, nil, PChar(CommandLine),
nil, nil, False, CREATE_NEW_CONSOLE or CREATE_NEW_PROCESS_GROUP,
Environment, nil, StartUpInfo, ProcInfo) then
begin
case GetLastError of
ERROR_PRIVILEGE_NOT_HELD:
raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcPrivilegesMissing,
[GetPrivilegeDisplayName(SE_ASSIGNPRIMARYTOKEN_NAME), SE_ASSIGNPRIMARYTOKEN_NAME,
GetPrivilegeDisplayName(SE_INCREASE_QUOTA_NAME), SE_INCREASE_QUOTA_NAME]);
ERROR_FILE_NOT_FOUND:
raise EJclCreateProcessError.CreateResRecFmt(@RsCreateProcCommandNotFound, [CommandLine]);
else
raise EJclCreateProcessError.CreateResRec(@RsCreateProcFailed);
end;
end;
// clean up
CloseWindowStation(hWindowStation);
CloseDesktop(hDesktop);
CloseHandle(hUserToken);
// if this code should be called although there has
// been an exception during invocation of CreateProcessAsUser,
// it will quite surely fail. you should make sure this doesn't happen.
// (it shouldn't happen due to the use of exceptions in the above lines)
CloseHandle(ProcInfo.hThread);
CloseHandle(ProcInfo.hProcess);
end; |
Partager