Page 1 of 1

shellExecuteEx

Posted: Sat Jun 01, 2013 3:36 am
by ghosttie
Has anyone used shellExecuteEx with JADE?

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;
Part of what makes it difficult is the strings. I think I'm supposed to allocate them separately and just put the address in the SHELLEXECUTEINFO structure. allocateString is:

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;
shellExecuteEx is defined as:

Code: Select all

shellExecuteEx(sei : Binary[64] io) : Boolean is ShellExecuteEx in shell32 presentationClientExecution;
and copyMemoryFromBinary is:

Code: Select all

copyMemoryFromBinary(pI_Dest : Integer; pBin_Source : Binary; pI_Length : Integer) is RtlMoveMemory in kernel32;