wxExecute can't execute file that needs admin permissions UAC - c++

From wxWidgets application I try to run installer, made with NSIS, in silent mode (/S flag). Got this error:
Execution of command: "C:\somecommand.exe" failed (error 0: Операция
завершена успешно / Successful).
When I run installer silently from command line, I got UAC popup, but when I execute it from wxWidget application I got only this error. And what this error means? Like "Fatal Error: All is fine".
In NSIS script I have RequestExecutionLevel admin, because I really need it to have ability to install program in directories like Program Files.

To start a Windows application that requires elevation you must use ShellExecute and not CreateProcess, CreateProcess will just fail with a elevation required error.
I would imagine that wxLaunchDefaultApplication uses ShellExecute internally but it seems a bit risky to rely on that so you might as well use a ifdef:
#ifdef __WINDOWS__ // __WXMSW__
ShellExecute(0, 0, pathtoexe, parameters, 0, SW_SHOW);
#else
wxExecute(something);
#endif

Related

How to enable System Error message when running executable from command line

According to Microsoft, "If [the system] cannot locate the DLL, the system terminates the process and displays a dialog box that reports the error. " This is the result I get when I run my application outside of the command line, but I do not get the same system error when I run the application from a shell environment such as command prompt or powershell.
Is there a way to show the same error message when the application is run from a command line interface?
https://msdn.microsoft.com/en-us/library/aa271571(v=vs.60).aspx
SetErrorMode(GetErrorMode() & ~SEM_FAILCRITICALERRORS);
but I don't think you want to do this, as you do not know in which environment the user will run your application.
It is usually now a good idea to popup a dialogbox in e.g. a service environment.
What is the problem with examining the error code of whatever is failing e.g. LoadLibrary() and reacting to this error?

UNC-Paths aren't supported

I am trying to color my console outputs, but while doing so ran into the following warning message:
CMD.EXE was started with the Path given above as the current Directory.
UNC-Paths aren't supported.
The Windows - Directory will be set as current Directory.
That warning comes from this line:
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
Does anyone has an idea how I would get rid of that message?
GetStdHandle is probably returning a handle which is incompatible with the debug console you have running. Calling the function once at program start-up and keeping hold of the handle might work better.

Is it possible to suppress MessageBox when running a specific command?

I'm using Tortoise SVN, and TortoisePlink for remote ssh connections.
From time to time TortoisePlink is displaying errors like:
---------------------------
TortoisePlink Fatal Error
---------------------------
Network error: Software caused connection abort
---------------------------
OK
---------------------------
And they appears as messagebox and needs to be clicked by end-user.
I have tried to suppress messagebox by using -batch from command line, but problem still can be reproduced. For me it's sufficient if I'll disable messagebox prompting and print for example in command line same information - since my batch will retry later on again automatically.
Does there exists such software which can override default windows behavior and print in console window whatever is displayed in message box.
I guess in simplest terms such command line tool can be easily created, using for example
http://www.codeproject.com/Articles/44326/MinHook-The-Minimalistic-x-x-API-Hooking-Libra
and override MessageBoxA / MessageBoxW - but have anyone done this kind of thing ?
I think you're going about this the wrong way. Instead of trying to suppress the dialog boxes that TortoisePlink is showing, use the original Plink. TortoisePlink is a fork of Plink to explicitly show message boxes and not print anything on a command line, because it's designed for an UI app and not for console apps.
And if you really only want to use svn from a batch file, don't use TortoiseSVN but the original svn command line client (can be installed with the TSVN installer as well) and use the 'svn' command from the command line.
TortoisePLink.exe is targetted for end-user - so it's intended to display message boxes, however - there also exists a command line version of PLink.exe, and it can be downloaded from here:
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
Please notice that "TortoiseSVN" > "Settings" > "Network" > "SSH Client" should use TortoisePLink.exe - errors will be displayed to end-user.
For following file however -
%appdata%\Subversion\
file ‘config’:
In section [tunnels]
Add line like this:
ssh = Plink.exe -l <your login> -pw <password>
You should use command line version of PLink.exe (that is also displaying command prompt when launched).
It's easier to save PLink.exe next with TortoisePLink.exe, that is into
C:\Program Files\TortoiseSVN\bin.
I have tried to make a command line tool for supressing messageboxes, but it's useless for TortoisePLink.exe (Haven't debugged what is the problem), but in case if you're interested (Have other means to use it):
https://sourceforge.net/p/diagnostic/svn/HEAD/tree/Tools/msgboxSupress/
msSupress.cpp is compiled into .dll and it uses minimalistic hook for windows to disable MessageBoxA and MessageBoxW - actually they will be printed to console or redirected to file.
msSupressExe.cpp is compiled into .exe and it starts process in suspended mode, replaces .exe's entry point with EB FE (jump short into itself), waits until that address is reached, injects .dll and .dll will hook new process.
I have tested only on 64-bit platform - I suspect that command being executed must match same platform as as msSupress.exe.
So typically TortoisePlink.exe will display messagebox - but when executed like this:
mbSupress.exe "C:\Program Files\TortoiseSVN\bin\TortoisePlink.exe"
Same stuff as shown over message box will be displayed in console.
I think this solution is good prototype for further virus or trojan construction - using technique like this will allow to intercept even keyboard presses on any application - but I now made a command line utility, not a virus.

I want to open Msconfig from a button on my GUI

In my line of work I use msconfig a lot and I'm wanting to create a tool with various buttons on it so I can easily access my most commonly used programs. I'm using the Win32API to create the GUI and buttons, however I am having trouble getting msconfig to run. In my program I have
void callMsconfig()
{
ShellExecute(NULL,(LPCWSTR)L"open", (LPCWSTR)L"C:\\Windows\\System32\\msconfig.exe", NULL, NULL, SW_SHOWDEFAULT);
}
and an action statement so when the button is pressed the function is called. I've tried replacing ShellExecute() with system() and CreateProcess(). I've also replaced "open" with "runas" and the most I've gotten is the error saying C:\Windows\System32\msconfig.exe cannot be found when I know it is there because I've checked. What am I doing wrong? I'm using Windows 10 Home if that helps any.
If you have created a 32bit app that is running inside of the WOW64 emulator on 64bit systems, the C:\Windows\System32\ folder is silently redirected by WOW64 to the C:\Windows\SysWOW64\ folder, which does not have an msconfig.exe file. You need to account for that. Either create a 64bit executable, or use the Sysnative alias in 32bit code that runs inside of WOW64. Sysnative is documented on MSDN:
File System Redirector:
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. This mechanism is flexible and easy to use, therefore, it is the recommended mechanism to bypass file system redirection. Note that 64-bit applications cannot use the Sysnative alias as it is a virtual directory not a real one.
Try something more like this:
#include <shlwapi.h>
void callMsconfig()
{
BOOL IsWow64 = FALSE;
WCHAR szCmdLine[MAX_PATH] = {0};
IsWow64Process(GetCurrentProcess(), &IsWow64);
if (IsWow64)
{
GetWindowsDirectoryW(szCmdLine, MAX_PATH);
PathAppendW(szCmdLine, L"Sysnative");
}
else
{
GetSystemDirectoryW(szCmdLine, MAX_PATH);
}
PathAppendW(szCmdLine, L"msconfig.exe");
ShellExecuteW(NULL, NULL, szCmdLine, NULL, NULL, SW_SHOWDEFAULT);
}
However, do note that if UAC is enabled and you try to launch msconfig.exe from a 32bit process running inside of WOW64, the 32bit process MUST be running elevated or else ShellExecute() (and CreateProcess()) will fail to find the file correctly. I don't know why, but that is how it works. UAC Elevation is not required when launching msconfig.exe from a 64bit process.
If you don't want to elevate your entire program, you will have to make it launch a separate elevated process that can then launch msconfig.exe. You could just have the program launch a second copy of itself with a command-line parameter so it knows to just launch msconfig.exe and then exit itself. To launch an elevated process, you can use ShellExecute() specifying the runas verb.

How to call system() in an opened administrator program and gives it the same privileges?

I am writing a c++ application in Windows that runs as administrator. However, while calling the system() command, it seems that the command doesn't have admin privileges (can't create file in the C:\Program Files (x86)\ directory).
How can I avoid using CreateProcess ?
If you use system you can use:
system("runas /user:<admin-user> \"program.exe\"");
Or ShellExecute:
ShellExecute(hwnd, "runas", "program.exe", 0, 0, SW_SHOWNORMAL);
This Stackoverflow Question
details the CreateProcess method pretty well.