I need to run an elevated program synchronously. We usually use createProcess with waitForSingleObject to run programs synchronously, but apparently createProcess doesn't work with elevated programs and the proper thing to use is shellExecuteEx with a verb of "runas".
Unfortunately it's not working and getLastError is returning 0 so it makes it difficult to figure out what the problem is.
Code: Select all
createElevatedProcessSync(pS_FileName, pS_Parameters : String) : Integer;
constants
SEE_MASK_NOCLOSEPROCESS : Integer = #00000040;
SW_HIDE : Integer = 0;
VERB : String = "runas";
WAIT_INTERVAL : Integer = 1000;
WAIT_TIMEOUT : Integer = #00000102;
vars
binStartupInfo : Binary[64];
iResult : Integer;
iProcessHandle : Integer;
iHandleVerb, iHandleFile, iHandleParameters : Integer;
begin
iHandleVerb := allocateString(VERB);
iHandleFile := allocateString(pS_FileName);
if pS_Parameters <> null then
iHandleParameters := allocateString(pS_Parameters);
endif;
binStartupInfo := 64.Integer.asBinary(LittleEndian, 4) //DWORD cbSize;
& SEE_MASK_NOCLOSEPROCESS.asBinary(LittleEndian, 4) //ULONG fMask;
& 0.asBinary(LittleEndian, 4) //HWND hwnd;
& iHandleVerb.asBinary(LittleEndian, 4) //LPCTSTR lpVerb;
& iHandleFile.asBinary(LittleEndian, 4) //LPCTSTR lpFile;
& iHandleParameters.asBinary(LittleEndian, 4) //LPCTSTR lpParameters;
& 0.asBinary(LittleEndian, 4) //LPCTSTR lpDirectory;
& SW_HIDE.asBinary(LittleEndian, 4) //int nShow;
& 0.asBinary(LittleEndian, 4) //HINSTANCE hInstApp;
& 0.asBinary(LittleEndian, 4) //LPVOID lpIDList;
& 0.asBinary(LittleEndian, 4) //LPCTSTR lpClass;
& 0.asBinary(LittleEndian, 4) //HKEY hkeyClass;
& 0.asBinary(LittleEndian, 4) //DWORD dwHotKey;
& 0.asBinary(LittleEndian, 4) //union {HANDLE hIcon;
& 0.asBinary(LittleEndian, 4) //HANDLE hMonitor;} DUMMYUNIONNAME;
& 0.asBinary(LittleEndian, 4); //HANDLE hProcess;
if not call shellExecuteEx(binStartupInfo).Boolean then
return call getLastError;
endif;
iProcessHandle := binStartupInfo[61 : 4].Integer;
iResult := call waitForSingleObject(iProcessHandle, WAIT_INTERVAL);
while iResult = WAIT_TIMEOUT do
iResult := call waitForSingleObject(iProcessHandle, WAIT_INTERVAL);
endwhile;
epilog
call closeHandle(iProcessHandle);
if iHandleVerb <> 0 then
call _globalFree(iHandleVerb);
endif;
if iHandleFile <> 0 then
call _globalFree(iHandleFile);
endif;
if iHandleParameters <> 0 then
call _globalFree(iHandleParameters);
endif;
end;
Code: Select all
allocateString(pS : String) : Integer;
constants
GMEM_MOVEABLE : Integer = 2;
vars
iPtr, iHandle : Integer;
begin
iHandle := call _globalAlloc(GMEM_MOVEABLE, pS.length);
if iHandle = 0 then
return 0;
endif;
iPtr := call _globalLock(iHandle);
if iPtr = 0 then
call _globalFree(iHandle);
return 0;
endif;
call copyMemoryFromBinary(iPtr, pS.Binary, pS.length);
call _globalUnlock(iHandle);
return iHandle;
end;
Code: Select all
shellExecuteEx(sei : Binary[64] io) : Boolean is ShellExecuteEx in shell32 presentationClientExecution;
Code: Select all
copyMemoryFromBinary(pI_Dest : Integer; pBin_Source : Binary; pI_Length : Integer) is RtlMoveMemory in kernel32;