Skip to content

Commit 11240ae

Browse files
authored
Merge pull request #11703 from Ext3h/fix_portable_system_on_windows
Replace ShellExecuteExW with simple CreateProcessW #11699
2 parents 71b6d24 + be192aa commit 11240ae

File tree

1 file changed

+31
-47
lines changed

1 file changed

+31
-47
lines changed

src/portable.cpp

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -200,59 +200,43 @@ int Portable::system(const QCString &command,const QCString &args,bool commandHa
200200
}
201201
else
202202
{
203-
// Because ShellExecuteEx can delegate execution to Shell extensions
204-
// (data sources, context menu handlers, verb implementations) that
205-
// are activated using Component Object Model (COM), COM should be
206-
// initialized before ShellExecuteEx is called. Some Shell extensions
207-
// require the COM single-threaded apartment (STA) type.
208-
// For that case COM is initialized as follows
209-
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
210-
211-
uint16_t *commandw = nullptr;
212-
recodeUtf8StringToW( commandCorrectedPath, &commandw );
213-
uint16_t *argsw = nullptr;
214-
recodeUtf8StringToW( args, &argsw );
215-
216-
// gswin32 is a GUI api which will pop up a window and run
217-
// asynchronously. To prevent both, we use ShellExecuteEx and
218-
// WaitForSingleObject (thanks to Robert Golias for the code)
219-
220-
SHELLEXECUTEINFOW sInfo = {
221-
sizeof(SHELLEXECUTEINFOW), /* structure size */
222-
SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI, /* tell us the process
223-
* handle so we can wait till it's done |
224-
* do not display msg box if error
225-
*/
226-
nullptr, /* window handle */
227-
nullptr, /* action to perform: open */
228-
(LPCWSTR)commandw, /* file to execute */
229-
(LPCWSTR)argsw, /* argument list */
230-
nullptr, /* use current working dir */
231-
SW_HIDE, /* minimize on start-up */
232-
nullptr, /* application instance handle */
233-
nullptr, /* ignored: id list */
234-
nullptr, /* ignored: class name */
235-
nullptr, /* ignored: key class */
236-
0, /* ignored: hot key */
237-
nullptr, /* ignored: icon */
238-
nullptr /* resulting application handle */
239-
};
240-
241-
if (!ShellExecuteExW(&sInfo))
203+
uint16_t* fullCmdW = nullptr;
204+
recodeUtf8StringToW(fullCmd, &fullCmdW);
205+
206+
STARTUPINFOW sStartupInfo;
207+
std::memset(&sStartupInfo, 0, sizeof(sStartupInfo));
208+
sStartupInfo.cb = sizeof(sStartupInfo);
209+
sStartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
210+
sStartupInfo.wShowWindow = SW_HIDE;
211+
212+
PROCESS_INFORMATION sProcessInfo;
213+
std::memset(&sProcessInfo, 0, sizeof(sProcessInfo));
214+
215+
if (!CreateProcessW(
216+
nullptr, // No module name (use command line)
217+
reinterpret_cast<wchar_t*>(fullCmdW), // Command line, can be mutated by CreateProcessW
218+
nullptr, // Process handle not inheritable
219+
nullptr, // Thread handle not inheritable
220+
FALSE, // Set handle inheritance to FALSE
221+
CREATE_NO_WINDOW,
222+
nullptr, // Use parent's environment block
223+
nullptr, // Use parent's starting directory
224+
&sStartupInfo,
225+
&sProcessInfo
226+
))
242227
{
243-
delete[] commandw;
244-
delete[] argsw;
228+
delete[] fullCmdW;
245229
return -1;
246230
}
247-
else if (sInfo.hProcess) /* executable was launched, wait for it to finish */
231+
else if (sProcessInfo.hProcess) /* executable was launched, wait for it to finish */
248232
{
249-
WaitForSingleObject(sInfo.hProcess,INFINITE);
233+
WaitForSingleObject(sProcessInfo.hProcess,INFINITE);
250234
/* get process exit code */
251235
DWORD exitCode;
252-
bool retval = GetExitCodeProcess(sInfo.hProcess,&exitCode);
253-
CloseHandle(sInfo.hProcess);
254-
delete[] commandw;
255-
delete[] argsw;
236+
bool retval = GetExitCodeProcess(sProcessInfo.hProcess,&exitCode);
237+
CloseHandle(sProcessInfo.hProcess);
238+
CloseHandle(sProcessInfo.hThread);
239+
delete[] fullCmdW;
256240
if (!retval) return -1;
257241
return exitCode;
258242
}

0 commit comments

Comments
 (0)