I have an executable written in C that has some functions in it that I would like to use from a c# application. I have written plenty of dlls before and was able to use functions in them by prepending __declspec(dllexport) to the function declaration. Can I do this from an executable? will the executable actually export the function?
Yes you can! Yes the executable will export the functions. This is not done very often, but it works pretty good. According the Specification (http://msdn.microsoft.com/en-us/gg463119.aspx) of the Executable, there is no difference between DLL and Executable as far as the Exports is concerned. EXE like DLL can have an Export Table directory that documents the functions that will be exported by the image. As an Example of a "normal" Executable exporting functions, have a look at Chrome.exe. See the I made using PEStudio showing Chrome exporting some functions. Some Windows built-in Executable also export functions (e.g. the Local Security Authority Subsystem - lsass.exe). The Windows Kernel (ntoskrnl.exe) image also exports more than 2000 functions (on a Windows7 system).
Related
I've got a Windows application with a GUI written in Rust and winapi. Despite its GUI, it behaves like a console application. When the exe file is started, a Command Prompt window pops up, and the application is run from it. This is not what I want; a main window should open instead, as in all real desktop apps. How can I achieve this goal in Rust with winapi?
I've investigated some options. You can develop Windows desktop applications using Tauri or gtk-rs, but both of these techniques have drawbacks when used for Windows apps. More options may be found here. I've also tried the windows-rs samples available on the internet, but they're all console apps with a graphical user interface, which isn't what I'm looking for.
I also note that C++ desktop applications use the function int APIENTRY wWinMain(...) as the entry point while console applications use int main(...), and wWinMain doesn't seem available in rust winapi.
Whether the system allocates a console for a newly created process is controlled by the Subsystem field in the Windows-specific optional PE header. The field is populated through the linker's /SUBSYSTEM command line option. The only relevant arguments for desktop applications are CONSOLE and WINDOWS. The former instructs the system to allocate a console on launch, whereas the latter won't.
You can instruct the linker to target the WINDOWS subsystem from Rust code by placing the per-module
#![windows_subsystem = "windows"]
attribute (see windows-subsystem) inside the main module of your application.
You'll find an example of this in the core_app sample of the windows crate.
This is the most convenient way to target the WINDOWS subsystem. You can also explicitly pass the linker flag along, e.g. by placing the following override into .cargo/config.toml:
[build]
rustflags = [
"-C", "link-arg=/SUBSYSTEM:WINDOWS",
]
This may or may not work, depending on the linker you happen to be using. Since the linker isn't part of the Rust toolchain, making sure that this works and has the intended effect is on you.
A note on the entry point's function name: It is irrelevant as far as the OS loader is concerned. It never even makes it into the final executable image anyway. The PE image only stores the (image-base-relative) AddressOfEntryPoint, and that symbol could have been named anything.
The concrete name is only relevant to the build tools involved in generating the respective linker input.
More info here: WinMain is just the conventional name for the Win32 process entry point. The underlying principles apply to Rust just the same, particularly the aspect that the user-defined entry point (fn main()) isn't actually the executable's entry point.
On Windows 10 with linux subsystem you can compile project with debug information that contains paths like this "/mnt/c/" using mingw compiler.
And software like gdbgui tries to open such file using function like
https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew
and of course it fails
What is the proper way to write such software in cross platform way?
Edit: Possible workarounds
edit compiled binary and change paths
create small utility and hook winapi FileOpen function
I have a python script for a word game that uses a dictionary which is a unformatted text file.
I want to create an executable file and pass it on to my friends. They use Windows, Mac or Linux and none of them have Python installed. How can I generate an executable from my script so all my friends can run it and test the game?
You can embedding the specific python binaries for each distribution in folders like python_win, python_mac, python_linux and create three distinct scripts launchers for each one passing on your application as parameter, this will work.
Is there a way of dynamically running a DLL at a remote Windows box?
Say a user wants to send a his own DLL file to a remote server and run a function in that DLL at the remote site. The user may be able to provide function entry points as well as required parameters, but no more. (e.g. no header file)
I am thinking of setting up an agent executable at the remote site that can (1) dynamically load and bind a unknown DLL and (2) run a function with parameters. Is this a good a approach, or is such an executable possible?
You can use a technique of Dynamically loading your DLL's.
Normally you use a DLL by statically linking a .LIB into your project and compiling it. To load a DLL dynamically at runtime you use the following WIN32 API functions and a few other tricks.
LoadLibaray();
LoadLibarayEx();
GetProcAddress();
FreeLibrary();
There are some other tricks involved
You need to declare the dll functions as export'ed.
In c++ you need to use extern "C" to prevent name mangling of your functions.
FARPROC ... with GetProcAddress
It is all explained in the following wiki article - http://en.wikipedia.org/wiki/Dynamic-link_library
Your idea of installing an executable on the remote machine is a good one. So long as you agree on the function names and parameters with the user. If the dll complies with this then the dll can be changed at any time without requiring you EXE to be changed. Once set up and working it is simple to add extra functions.
Yes you could write small program that runs the DLL function using this information and call it remotely using the something like PSEXEC from sysinternals.
PsExec is a light-weight
telnet-replacement that lets you
execute processes on other systems,
complete with full interactivity for
console applications, without having
to manually install client softwareto manually install client software
Andrew Cash's reply is sound for unmanaged code. The technique he describes around GetProcAddress is essentially what RunDll32.exe does. RunDll32.exe is part of Windows and specializes at loading arbitrary DLLs and executing their code. You can run it like this:
RUNDLL32.EXE [dllfile],[entrypoint] [optional arguments]
When you do this, RunDll32 will call LoadLibrary on the DLL and then GetProcAddress on the entrypoint name you give it. If all that goes well then it calls the entry point function.
For this to actually work the entrypoint function needs to be exported. It must also be declared like this:
void CALLBACK MyEntryPoint(
HWND hwnd,
HINSTANCE hinst,
LPSTR lpszCmdLine,
int nCmdShow);
I remember a few years ago(2002) there was a multipartite virus that could be run natively on linux and windows. I don't know if a compiler could be specially craft an executable so that it could be read as both ELF and PE, so that the os would start executing at different entry points. Or a program that could merge two programs, one compiled using mingw, one compiled in native linux, to one program.
I don't know if such a program exists, or could it exist, and I'm know this could be implemented in Java or some scripting language, but that's not a native program.
Imagine the possibilities, I could deploy a program with linux and window (and perhaps os/x)libraries, and one main executable that could be run on any os. The cross-platform support would compensate the bigger size.
Windows programs have a DOS stub in the beginning, and I just ran an ELF executable through debug.com, which said that the first instruction of this exe was JG 0x147. Just maybe something could be done with this...
No.
Windows and Linux use vastly different binary file formats. See Portable Executable (Windows) and Executable and Linkable Format (Linux).
Something like WINE will run Windows executables on Linux but that's not the same thing.
This is actually a really terrible idea for multiple reasons.
Cross-compiling across operating system boundaries is extremely difficult to do properly.
If you go for the second route (building separate PE binaries on Windows and ELF on Linux, and then somehow merging them) you have to maintain two machines, each running a different OS and the full build stack, and you'd have to make sure that you tested both versions separately before gluing them together.
Dynamic linking is already a pain to properly manage, on Windows and on Linux; static linking can generate binaries that are much more inconvenient to deal with than whatever imaginary benefits you get from providing one single file type to your end-user.
If you want to run the same binary executable file on multiple OSes, your options are Java, Mono, and potentially NativeClient, the browser plug-in Google's developing to work around the "webapps are too slow" problem.