|
33 | 33 | #include "nsString.h"
|
34 | 34 | #include "nsLiteralString.h"
|
35 | 35 | #include "nsReadableUtils.h"
|
| 36 | +#include "mozilla/UniquePtrExtensions.h" |
36 | 37 | #else
|
37 | 38 | #ifdef XP_MACOSX
|
38 | 39 | #include <crt_externs.h>
|
@@ -72,6 +73,7 @@ nsProcess::nsProcess()
|
72 | 73 | , mShutdown(false)
|
73 | 74 | , mBlocking(false)
|
74 | 75 | , mStartHidden(false)
|
| 76 | + , mNoShell(false) |
75 | 77 | , mPid(-1)
|
76 | 78 | , mObserver(nullptr)
|
77 | 79 | , mWeakObserver(nullptr)
|
@@ -466,46 +468,78 @@ nsProcess::RunProcess(bool aBlocking, char** aMyArgv, nsIObserver* aObserver,
|
466 | 468 |
|
467 | 469 | #if defined(PROCESSMODEL_WINAPI)
|
468 | 470 | BOOL retVal;
|
469 |
| - wchar_t* cmdLine = nullptr; |
| 471 | + UniqueFreePtr<wchar_t> cmdLine; |
470 | 472 |
|
471 | 473 | // |aMyArgv| is null-terminated and always starts with the program path. If
|
472 | 474 | // the second slot is non-null then arguments are being passed.
|
473 |
| - if (aMyArgv[1] && assembleCmdLine(aMyArgv + 1, &cmdLine, |
474 |
| - aArgsUTF8 ? CP_UTF8 : CP_ACP) == -1) { |
475 |
| - return NS_ERROR_FILE_EXECUTION_FAILED; |
| 475 | + if (aMyArgv[1] || mNoShell) { |
| 476 | + // Pass the executable path as argv[0] to the launched program when calling |
| 477 | + // CreateProcess(). |
| 478 | + char** argv = mNoShell ? aMyArgv : aMyArgv + 1; |
| 479 | + |
| 480 | + wchar_t* assembledCmdLine = nullptr; |
| 481 | + if (assembleCmdLine(argv, &assembledCmdLine, |
| 482 | + aArgsUTF8 ? CP_UTF8 : CP_ACP) == -1) { |
| 483 | + return NS_ERROR_FILE_EXECUTION_FAILED; |
| 484 | + } |
| 485 | + cmdLine.reset(assembledCmdLine); |
476 | 486 | }
|
477 | 487 |
|
478 |
| - /* The SEE_MASK_NO_CONSOLE flag is important to prevent console windows |
479 |
| - * from appearing. This makes behavior the same on all platforms. The flag |
480 |
| - * will not have any effect on non-console applications. |
481 |
| - */ |
482 |
| - |
483 | 488 | // The program name in aMyArgv[0] is always UTF-8
|
484 | 489 | NS_ConvertUTF8toUTF16 wideFile(aMyArgv[0]);
|
485 | 490 |
|
486 |
| - SHELLEXECUTEINFOW sinfo; |
487 |
| - memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW)); |
488 |
| - sinfo.cbSize = sizeof(SHELLEXECUTEINFOW); |
489 |
| - sinfo.hwnd = nullptr; |
490 |
| - sinfo.lpFile = wideFile.get(); |
491 |
| - sinfo.nShow = mStartHidden ? SW_HIDE : SW_SHOWNORMAL; |
492 |
| - sinfo.fMask = SEE_MASK_FLAG_DDEWAIT | |
493 |
| - SEE_MASK_NO_CONSOLE | |
494 |
| - SEE_MASK_NOCLOSEPROCESS; |
| 491 | + if (mNoShell) { |
| 492 | + STARTUPINFO startupInfo; |
| 493 | + ZeroMemory(&startupInfo, sizeof(startupInfo)); |
| 494 | + startupInfo.cb = sizeof(startupInfo); |
| 495 | + startupInfo.dwFlags = STARTF_USESHOWWINDOW; |
| 496 | + startupInfo.wShowWindow = mStartHidden ? SW_HIDE : SW_SHOWNORMAL; |
| 497 | + |
| 498 | + PROCESS_INFORMATION processInfo; |
| 499 | + retVal = CreateProcess(/* lpApplicationName = */ wideFile.get(), |
| 500 | + /* lpCommandLine */ cmdLine.get(), |
| 501 | + /* lpProcessAttributes = */ NULL, |
| 502 | + /* lpThreadAttributes = */ NULL, |
| 503 | + /* bInheritHandles = */ FALSE, |
| 504 | + /* dwCreationFlags = */ 0, |
| 505 | + /* lpEnvironment = */ NULL, |
| 506 | + /* lpCurrentDirectory = */ NULL, |
| 507 | + /* lpStartupInfo = */ &startupInfo, |
| 508 | + /* lpProcessInformation */ &processInfo); |
| 509 | + |
| 510 | + if (!retVal) { |
| 511 | + return NS_ERROR_FILE_EXECUTION_FAILED; |
| 512 | + } |
| 513 | + |
| 514 | + CloseHandle(processInfo.hThread); |
495 | 515 |
|
496 |
| - if (cmdLine) { |
497 |
| - sinfo.lpParameters = cmdLine; |
498 |
| - } |
| 516 | + mProcess = processInfo.hProcess; |
| 517 | + } else { |
| 518 | + SHELLEXECUTEINFOW sinfo; |
| 519 | + memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW)); |
| 520 | + sinfo.cbSize = sizeof(SHELLEXECUTEINFOW); |
| 521 | + sinfo.hwnd = nullptr; |
| 522 | + sinfo.lpFile = wideFile.get(); |
| 523 | + sinfo.nShow = mStartHidden ? SW_HIDE : SW_SHOWNORMAL; |
| 524 | + |
| 525 | + /* The SEE_MASK_NO_CONSOLE flag is important to prevent console windows |
| 526 | + * from appearing. This makes behavior the same on all platforms. The flag |
| 527 | + * will not have any effect on non-console applications. |
| 528 | + */ |
| 529 | + sinfo.fMask = SEE_MASK_FLAG_DDEWAIT | |
| 530 | + SEE_MASK_NO_CONSOLE | |
| 531 | + SEE_MASK_NOCLOSEPROCESS; |
499 | 532 |
|
500 |
| - retVal = ShellExecuteExW(&sinfo); |
501 |
| - if (!retVal) { |
502 |
| - return NS_ERROR_FILE_EXECUTION_FAILED; |
503 |
| - } |
| 533 | + if (cmdLine) { |
| 534 | + sinfo.lpParameters = cmdLine.get(); |
| 535 | + } |
504 | 536 |
|
505 |
| - mProcess = sinfo.hProcess; |
| 537 | + retVal = ShellExecuteExW(&sinfo); |
| 538 | + if (!retVal) { |
| 539 | + return NS_ERROR_FILE_EXECUTION_FAILED; |
| 540 | + } |
506 | 541 |
|
507 |
| - if (cmdLine) { |
508 |
| - free(cmdLine); |
| 542 | + mProcess = sinfo.hProcess; |
509 | 543 | }
|
510 | 544 |
|
511 | 545 | mPid = GetProcessId(mProcess);
|
@@ -603,6 +637,20 @@ nsProcess::SetStartHidden(bool aStartHidden)
|
603 | 637 | return NS_OK;
|
604 | 638 | }
|
605 | 639 |
|
| 640 | +NS_IMETHODIMP |
| 641 | +nsProcess::GetNoShell(bool* aNoShell) |
| 642 | +{ |
| 643 | + *aNoShell = mNoShell; |
| 644 | + return NS_OK; |
| 645 | +} |
| 646 | + |
| 647 | +NS_IMETHODIMP |
| 648 | +nsProcess::SetNoShell(bool aNoShell) |
| 649 | +{ |
| 650 | + mNoShell = aNoShell; |
| 651 | + return NS_OK; |
| 652 | +} |
| 653 | + |
606 | 654 | NS_IMETHODIMP
|
607 | 655 | nsProcess::GetPid(uint32_t* aPid)
|
608 | 656 | {
|
|
0 commit comments