programmatically check for subsystem - c++

I have a .exe created with a windows subsystem. I copy that .exe to another .exe, and I run:
editbin.exe /SUBSYSTEM:CONSOLE my.exe
So my intention is to have a .exe that runs with a GUI, and another .exe that is meant for command line operations (no GUI).
How do I check what subsystem is currently active in my C++ code?

Subsystem type (GUI, console, etc.) is stored in the PE header, which you can access via the ImageHlp functions. You can get it with the following code:
// Retrieve the header for the exe. GetModuleHandle(NULL) returns base address
// of exe.
PIMAGE_NT_HEADERS header = ImageNtHeader((PVOID)GetModuleHandle(NULL));
if (header->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
{
// Console application.
}
Relevent MSDN entries:
ImageNtHeader
IMAGE_NT_HEADERS
IMAGE_OPTIONAL_HEADER

Look at the ImageLoad function in the Imagehlp library. This returns a LOADED_IMAGE structure which has a IMAGE_NT_HEADERS structure in its FileHeader field. The OptionalHeader field in this structure is an IMAGE_OPTIONAL_HEADER which has a Subsytem filed containg the information that you want.

Far easier than spelunking in your own headers: check if you've got console handles.
For a GUI subsystem app, GetStdHandle() will return NULL handles.

Related

Open Public Documents folder in Windows Explorer

I have the following file I need to open in a windows explorer window
C:\Users\Public\Documents\folder1\test.txt
So far opening this file using the above path is fine and I can read it as usual.
However when trying to open this this folder through Windows Explorer using wxExecute((wxChar **)cmd, wxEXEC_ASYNC, NULL); where cmd is the above path(minus the file), It opens to my user documents.
I've tried various Windows API functions to get the path, some including where Public Documents has it's own ID and these still generate the path I already have. Are there any CLI options I can give to Windows Explorer so that it can actually open Public Documents without reverting to my User Documents folder?
First of all, why do you cast your string to wxChar**? This just can't be right.
Second, you should be using wxLaunchDefaultApplication() instead of "raw" wxExecute() in the first place (FWIW wxLaunchDefaultApplication() is a straightforward wrapper for ShellExecute() under MSW, while wxExecute() is much more complicated).
It's undocumented, but has worked across multiple windows Versions since at least XP with the following command line:
explorer.exe /select,"path-to-open"
Note the comma, and make sure the path is quoted. The path may include a file name, in which case that file gets selected.
(With Windows 10, it's actually a good idea to use a file name, since otherwise the parent folder is opened with the specified sub folder selected)
Should be the same with CreateProcess, ShellExecute, or system(), or whatever comfort wxWidgets offer.
Actually turned out to be an issue with wxExec from wxWidgets. Converting the command to a ShellExecute opened it up just fine. Potentially Widgets 2.9.5 can't handle Windows 10's pseudo folders and weirdness?.

Using Loadlibrary("cmd.exe") but not work

as we all know when we start a CMD.exe it will appear a console window and start with lines like:
Microsoft Windows [版本 6.1.7601]
版权所有 (c) 2009 Microsoft Corporation。保留所有权利。
C:\Users\hey>
but when i crate a windows console project in VS and my code like this:
int _tmain(int argc, _TCHAR* argv[])
{
auto h = LoadLibrary(__TEXT("cmd.exe"));
Sleep(99999);
}
just turns out a black window.no lines out!
as i expect,i can load this PE(windows executable format) file in my process so i do not have to start a new cmd.exe and redirect its stdIO to the process which start cmd.exe.(i know Loadlibrary with an exe file could start a exe in calling process without creating a new process)
and why is Loadlibrary not working?(it did not appear any words in the console window)
(i know Loadlibrary with an exe file could start a exe in calling process without creating a new process)
No, it can't.
You can pass the name of an EXE file to LoadLibraryEx if you use the LOAD_LIBRARY_AS_DATAFILE flag, in order to access its resources, but LoadLibrary neither runs the code in an EXE nor prepares the code for being run.
The entry point for an EXE is designed for having its own process. (I'm talking about the real entry point, which is usually provided by a language support library. It may have a name such as wmainCRT and its address, not the address of user-provided main(), appears in the PE header). Typically it exits by calling ExitProcess(), which will have catastrophic effects on your host EXE even if you do manage to map it into your memory space and call it.
The requirements for the entry point of a dynamically loadable library and an executable file are very, very different.
You can't run an executable via LoadLibrary. Use CreateProcess (or one of its siblings) instead.
From the LoadLibrary function docs (highlight in bold is mine):
LoadLibrary can also be used to load other executable modules. For example, the function can specify an .exe file to get a handle that can be used in FindResource or LoadResource. However, do not use LoadLibrary to run an .exe file. Instead, use the CreateProcess function.

dll loading error using LoadLibraryA

We are trying to load a dll-library from inside a 64-bit dll using LoadLibraryA function. It returns 126 error - mod not found. The dll file path given to the function is correct, we are sure.
We have tried a dummy dll to test and it worked, it is loaded.
We also tried adding the dll (which is a dependcy of the first dll that we want to load) to the dummy dll. It also worked. So the problem seems not about the dependency dlls, but the original dll that we want to load in the first place.
We also tried converting the dl to 64-bit, and tried that, still no good.
We also checked the dependencies with Dependency Walker. Everything is OK.
The operating system that we are using is Windows 8, 64bit. If it makes any difference..
Does anyone have any idea about this poblem?
EDIT:
We also tried this code:
hModule = LoadLibraryW(L"C:\\temp\\dllToLoad.dll");
and received this error code:
"First-chance exception at 0x00000000 in C_Test_TSMPPKCS11.exe: 0xC0000005: Access violation at location 0x0000000000000000."
EDIT 2:
The code that we used in the first place is:
hModule = LoadLibraryA((char*)aDLLFile);
EDIT 3:
We are using complete path to load the dll. In order to test this we tried this code:
FILE *fp;
int size = 0;
fp=fopen("C:\\temp\\dllToLoad.dll", "r");
size = fgetc(fp);
printf("size:%d\n",size);
fclose(fp);
There was no problem, we received the file size which is 77.
We also tried converting the dl to 64-bit, and tried that, still no good.
There's no way you can load a 32-bit dll as executable code into a 64-bit process (and since you're using LoadLibraryA() that's all you can be trying to do).
Assuming the dll that you are trying to load and the process that you're loading it into are the same type then are you passing a complete path to LoadLibraryA() or a relative path or just a dll name? If you're not using a complete path then consider using LoadLibraryEx() if possible as this gives you much more control over the search path used. If you are using a complete path try opening the file using normal file operations if you fail to load the dll, does this work? If that works then try LoadLibraryEX() with LOAD_LIBRARY_AS_DATAFILE and see if that will load the dll as a simple data file (which proves that it's finding the file).
Run up Sysinternal's ProcMon and watch the code open the DLL, that may show you dependent DLL load failures.

CreateProcess STATUS_DLL_NOT_FOUND - which dll?

I have a process which calls CreateProcess. It appears that CreateProcess returns nonzero indicating success. However, the HANDLE to the process then gets immediately set, indicating the process has exited. When I call GetExitCodeProcess, STATUS_DLL_NOT_FOUND is then returned.
I understand that a DLL is missing. I even know exactly which one. However, what I don't understand is how to figure that out programmatically.
I noticed that Windows will present a dialog saying that the process failed to start because it couldn't find the specified DLL (screenshot: http://www.mediafire.com/view/?kd9ddq0e2dlvlb9 ). In the dialog, Windows specifies which DLL is missing. However, I find no way to get that information myself programmatically.
If a process fails to start and would return STATUS_DLL_NOT_FOUND, how do I programmatically retrieve the library name to which the target process was linked which couldn't be found? That way I can automatically record in an error report what DLL appears to be missing or corrupt in a given installation.
CreateProcess returns 0 indicating success.
CreateProcess() returns a BOOL, where 0 is FALSE, aka failure not success.
If a process fails to start and would return STATUS_DLL_NOT_FOUND, how do I programmatically retrieve the library name to which the target process was linked which couldn't be found?
Unfortunately, there is no API for that. Your only option would be to manually access and enumerate the executable's IMPORTS table to find out what DLLs it uses, and then recursively access and enumerate their IMPORTS tables, manually checking every DLL reference you find to see whether that DLL file exists on the OS's search path or not.
If the dll is statically linked you can walk the iat and see if the dll exists. If the dll is dynamically loaded then starting the process suspended and hooking LoadLibrary (or instead of hooking emulate a debugger) is the only way I see.
The best way is to use loader snaps. Basically you use gflags.exe (which is included with windbg) to enable loader snaps; then, run the process with the debugger attached. Loader snaps will enable the loader to print out dbg messages of the process and it will print the failures.
gflags.exe -i yourcode.exe +sls
windbg yourcode.exe
I know this is not a "programmatic" way to find out the problem, but what the loader does is complicated, and you don't really want to be redoing its logic to find the failure. That is why loader snaps were invented.
The very hard way would be: Parsing the .EXE and .DLL files and create the dependency tree of .DLL files.
I don't think there is a way to get a list of DLL files that are missing: When Windows finds one missing DLL file it stops loading so if one DLL file is missing you won't find out if more DLL files are missing.
Another problem you could have is that old DLL versions could have missing "exports" (functions). This is even harder to detect than the dependency tree.
Just since this is somehow the top stackoverflow result on Google for "STATUS_DLL_NOT_FOUND". How to trace and solve any random occurence:
Download SysInternals procmon64.exe (or just the entire set). After startup immediately hit the looking glass 'Stop capture' button (Ctrl+E). And 'Clear' (Ctrl+X).
Set filters for:
'Process name' is to whatever the mentioned process name was (for me it was 'build-script-build.exe') [Add]
'Result' is not 'SUCCESS' [Add]
'Path' ends with '.dll' [Add] [OK]
Start capture again (Ctrl+E).
Run the thing that had a problem again (for me: build cargo). Google for the last listed DLL file.
For me that was VCRUNTIME140.dll, so I installed the VC++ 2015 to 2019 redistributable.
ProcMon is kind of like unix strace.

Trying to load a DLL with LoadLibrary and get R6034 "An application has made an attempt to load the C runtime library incorrectly"

I'm writing a wrapper program that loads Winamp input plugins. I've got it working well so far with quite a few plugins, but for some others, I get an error message at runtime when I attempt to call LoadLibrary on the plugin's DLL. (It seems to happen mostly with plugins that were included with Winamp.) A dialog appears and gives me the error code and message above. This happens, for example, with the in_flac.dll and in_mp3.dll plugins (which come with Winamp). Any ideas on how I can remedy this situation?
EDIT:
This basically iterates through the plugins in a directory and attempts to load and then free each one. Some plugins produce the error I mentioned above, while others do not.
wstring path = GetSearchPath();
FileEnumerator e(path + L"in_*.dll");
while(e.MoveNext()) {
wstring pluginPath = path + e.GetCurrent().cFileName;
MessageBoxW(NULL, pluginPath.c_str(), L"Message", MB_OK);
HINSTANCE dll = LoadLibraryW(pluginPath.c_str());
if(!dll) {
pluginPath = wstring(L"There was an error loading \"") + wstring(e.GetCurrent().cFileName) + L"\":\n" + LastErrorToString();
MessageBoxW(NULL, pluginPath.c_str(), L"Error", MB_OK);
continue;
}
FreeLibrary(dll);
}
Starting from Visual Studio 2005, the C/C++ runtime MUST be put in the Windows side-by-side cache (C:\windows\WinSxS), so putting the CRT DLL's next to your exe doesn't work anymore (with one exception, see later).
You MUST also refer to the CRT DLL's via a manifest file. This manifest file is generated by the linker and will have a name like myexe.exe.manifest or mydll.dll.manifest. Distribiute this manifest with your application/DLL or link it in the exe/dll using the mt command.
The side-by-side cache and the manifest file system were introduced in Windows XP and are mainly intended to solve the DLL hell and to increase security.
Not referring to the CRT using a manifest or not putting the CRT in the side-by-side cache will generate error 6034.
If you still want to put the CRT DLL's next to your application, you could also use private assemblies, which means creating a kind of mini-side-by-side cache in the folder of your application. You can find additional information on MSDN.
there can be many reason... put your code here for clarification... one of the many solution might be is
Rebuild your application with a manifest. Building an application with Visual Studio automatically puts the manifest into the resulting EXE or DLL file. If you are building at the command line, use the mt.exe tool to add the manifest as a resource. Use resource ID 1 if building an EXE, 2 if building a DLL.
Also, you may try adding this into the code:
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'\"")