There were quite a few missing imports/definitions in Delphi, so I had to define them myself. But here is the finished implementation in Delphi of the C++ code from the link provided by Remy:
FUNCTION GetShellWindow : HWND; EXTERNAL 'USER32.DLL';
FUNCTION InitializeProcThreadAttributeList(lpAttributeList : PProcThreadAttributeList ; dwAttributeCount,dwFlags : DWORD ; VAR lpSize : NativeUInt) : ByteBool; stdcall; EXTERNAL 'KERNEL32.DLL';
FUNCTION UpdateProcThreadAttribute(lpAttributeList : PProcThreadAttributeList ; dwFlags : DWORD ; Attribute : NativeUInt ; lpValue : Pointer ; cbSize : NativeUInt ; lpPreviousValue : POINTER = NIL ; lpReturnSize : PSIZE_T = NIL) : ByteBool; OVERLOAD; stdcall; EXTERNAL 'KERNEL32.DLL';
FUNCTION UpdateProcThreadAttribute(lpAttributeList : PProcThreadAttributeList ; dwFlags : DWORD ; Attribute : NativeUInt ; VAR Process : THandle ; lpPreviousValue : Pointer = NIL ; lpReturnSize : PSIZE_T = NIL) : ByteBool; OVERLOAD;
BEGIN
Result:=UpdateProcThreadAttribute(lpAttributeList,dwFlags,Attribute,@Process,SizeOf(THandle),lpPreviousValue,lpReturnSize)
END;
PROCEDURE DeleteProcThreadAttributeList(lpAttributeList : PProcThreadAttributeList); stdcall; EXTERNAL 'KERNEL32.DLL';
CONST PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = $0002000
CONST EXTENDED_STARTUPINFO_PRESENT = $00080000;
TYPE
STARTUPINFOEXW = PACKED RECORD
StartupInfo : STARTUPINFOW;
lpAttributeList : PProcThreadAttributeList
END;
STARTUPINFOEX = STARTUPINFOEXW;
FUNCTION TryRunUnelevated(CONST Prog : TFileName ; CONST Tail : STRING ; CONST StartupDir : STRING = '') : BOOLEAN;
VAR
H : HWND;
PID : DWORD;
Process : THandle;
Size : SIZE_T;
P : PProcThreadAttributeList;
SIEX : STARTUPINFOEX;
PI : PROCESS_INFORMATION;
BEGIN
Result:=FALSE; H:=GetShellWindow;
IF H=0 THEN EXIT;
IF GetWindowThreadProcessID(H,PID)=0 THEN EXIT;
Process:=OpenProcess(PROCESS_CREATE_PROCESS,FALSE,PID);
IF Process=0 THEN EXIT;
TRY
InitializeProcThreadAttributeList(NIL,1,0,Size);
GetMem(P,Size);
TRY
IF NOT InitializeProcThreadAttributeList(P,1,0,Size) THEN EXIT;
TRY
IF NOT UpdateProcThreadAttribute(P,0,PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,Process) THEN EXIT;
FillChar(SIEX,SizeOf(STARTUPINFOEX),0);
SIEX.lpAttributeList:=P;
SIEX.StartupInfo.cb:=SizeOf(STARTUPINFOEX);
IF NOT CreateProcess(PChar(Prog),PChar(Tail),NIL,NIL,FALSE,CREATE_NEW_CONSOLE OR EXTENDED_STARTUPINFO_PRESENT,NIL,POINTER(StartupDir),SIEX.StartupInfo,PI) THEN EXIT
FINALLY
DeleteProcThreadAttributeList(P)
END;
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread)
FINALLY
FreeMem(P)
END
FINALLY
CloseHandle(Process)
END;
Result:=TRUE
END;
PROCEDURE RunUnelevated(CONST Prog : TFileName ; CONST Tail : STRING ; CONST StartupDir : STRING = '');
BEGIN
IF NOT TryRunUnelevated(Prog,Tail,StartupDir) THEN RaiseLastOSError
END;
There are two routines - one that simply returns TRUE/FALSE to signify success or failure, and one that raises an exception if it can't do it.
Edit: The re-declaration of DeleteProcThreadAttributeList is because the declaration of this routine in the standard Delphi sources is wrong - it uses TProcThreadAttributeList instead of PProcThreadAttributeList.