How can I write a Windows application without using WinMain? - c

Windows GUI applications written in C/C++ have 'WinMain' as an entry point (rather than 'main'). My understanding of this is that the compiler generates a 'main' function to be called by the C Runtime. This 'main' function sets up the necessary environment for the GUI and calls into 'WinMain' (specifying the instance handles etc.).
In short, I believe console and GUI application startup to differ in the following way:
Console application:
C Runtime --> 'main' function (hand-coded)
GUI application:
C Runtime --> 'main' function (compiler-generated) --> 'WinMain' function (hand-coded)
I would like to both validate this understanding and find out how I can hand-code a Windows GUI with just a 'main' function (i.e. without having to write 'WinMain').

You have an incorrect understanding. The difference between main and WinMain, apart from some differet initialization code, is the parameters passed to it.
main looks like this:
int main(int argc, char* argv[]);
While WinMain looks like this:
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
);
Something has to setup those parameters and make the call, and that's the startup code. When you compile and link a program, one of the linker parameters is the entry point, and that will be, depending on a console or GUI app, a different bit of startup code.
You can certainly write your own startup code, just go into your visual c++ source directory and you can find the startup code, it's called crt0.c and it's in the VC\crt\src directory.

With Just main, you can not code Winmain. For justifications, Following statements were taken from
http://blogs.msdn.com/oldnewthing/archive/2007/12/03/6644060.aspx
[In Windows Programming,] Why wasn't the application entry point called
main? Well, for one thing, the name main was already taken, and
Windows didn't have the authority to reserve an alternate definition.
There was no C language standardization committee back then; C was
what Dennis said it was, and it was hardly guaranteed that Dennis
would take any special steps to preserve Windows source code
compatibility in any future version of the C language. Since K&R
didn't specify that implementations could extend the acceptable forms
of the main function, it was entirely possible that there was a legal
C compiler that rejected programs that declared main incorrectly. The
current C language standard explicitly permits implementation-specific
alternate definitions for main, but requiring all compilers to support
this new Windows-specific version in order to compile Windows programs
would gratuitously restrict the set of compilers you could use for
writing Windows programs.
If you managed to overcome that obstacle, you'd have the problem that
the Windows version of main would have to be something like this:
int main(int argc, char *argv[], HINSTANCE hinst,
HINSTANCE hinstPrev, int nCmdShow);
Due to the way C linkage was performed, all variations of a function had to agree on the
parameters they had in common. This means that the Windows version
would have to add its parameters onto the end of the longest existing
version of main, and then you'd have to cross your fingers and hope
that the C language never added another alternate version of main. If
you went this route, your crossed fingers failed you, because it turns
out that a third parameter was added to main some time later, and it
conflicted with your Windows-friendly version.
Suppose you managed to convince Dennis not to allow that
three-parameter version of main. You still have to come up with those
first two parameters, which means that every program's startup code
needs to contain a command line parser. Back in the 16-bit days,
people scrimped to save every byte. Telling them, "Oh, and all your
programs are going to be 2KB bigger" probably wouldn't make you a lot
of friends. I mean, that's four sectors of I/O off a floppy disk!
But probably the reason why the Windows entry point was given a
different name is to emphasize that it's a different execution
environment. If it were called main, people would take C programs
designed for a console environment, throw them into their Windows
compiler, and then run them, with disastrous results.
Hope this clears your doubts.

It works the other way. There's a statically linked object file which comes with the compiler that holds the actual entry point. That entry point does initialization and then calls your entry point (i.e. WinMain).
What that static part expects to call may be tweakable. For example, in Visual Studio there's a field for the entry point name in the linker settings.

Related

Win32, WinMain vs custom Entry Point (huge size difference), why?

As topic says.
I noticed that if i use WinMain or any other default Entry Point, a C application can be like 70kb.
But if i just specify a custom Entry Point, say "RawMain", int RawMain().
Then the file will be like 6kb.
So i am wondering, why is this, what does it add/reference to the file?
I could understand there being some small difference in size, but the difference is huge for an empty application.
Thanks!
When building for windows in most environments, the actual program entry point will be provided by a function in a small runtime library. That will do some environment preparation and then call a function you provide, such as main, wmain, WinMain, etc.
The code that runs before your user-provided main function includes running global C++ constructors, enabling TLS variables, initializing global mutexes so that standard-library calls work properly in a multithreaded environment, setting up the standard locale, and other stuff.
One thing that setting the entry point does is starts the linker with an undefined symbol with the name you give the entry point, so for example, if you're using mingw32, the linker will start assuming that it needs to link libmingw32.a and with the undefined symbol __tmainCRTStartup.
The linker will find (hopefully) __tmainCRTStartup in libmingw32.a, and include the object file crtexe.o which contains it, along with anything else needed to satisfy undefined symbols emanating from crtexe.o, which is where the extra size comes from.
When you set your own entry point, you override this, and just set the linker to look for whatever function you specify. You get a smaller executable, but you have to be careful that features you're using don't rely on any of the global initialization that would be done by the runtime's startup function.

hidden routines linked in c program

Hullo,
When one disasembly some win32 exe prog compiled by c compiler it
shows that some compilers links some 'hidden' routines in it -
i think even if c program is an empty one and has a 5 bytes or so.
I understand that such 5 bytes is enveloped in PE .exe format but
why to put some routines - it seem not necessary for me and even
somewhat annoys me. What is that? Can it be omitted? As i understand
c program (not speaking about c++ right now which i know has some
initial routines) should not need such complementary hidden functions..
Much tnx for answer, maybe even some extended info link, cause this
topic interests me much
//edit
ok here it is some disasembly Ive done way back then
(digital mars and old borland commandline (i have tested also)
both make much more code, (and Im specialli interested in bcc32)
but they do not include readable names/symbols in such dissassembly
so i will not post them here
thesse are somewhat readable - but i am not experienced in understending
what it is ;-)
https://dl.dropbox.com/u/42887985/prog_devcpp.htm
https://dl.dropbox.com/u/42887985/prog_lcc.htm
https://dl.dropbox.com/u/42887985/prog_mingw.htm
https://dl.dropbox.com/u/42887985/prog_pelles.htm
some explanatory comments whats that heere?
(I am afraid maybe there is some c++ sh*t here, I am
interested in pure c addons not c++ though,
but too tired now to assure that it was compiled in c
mode, extension of compiled empty-main prog was c
so I was thinking it will be output in c not c++)
tnx for longer explanations what it is
Since your win32 exe file is a dynamically linked object file, it will contain the necessary data needed by the dynamic linker to do its job, such as names of libraries to link to, and symbols that need resolving.
Even a program with an empty main() will link with the c-runtime and kernel32.dll libraries (and probably others? - a while since I last did Win32 dev).
You should also be aware that main() is only the entry point of your program - quite a bit has already gone on before this point such as retrieving and tokening the command-line, setting up the locale, creating stderr, stdin, and stdout and setting up the other mechanism required by the c-runtime library such a at_exit(). Similarly, when your main() returns, the runtime does some clean-up - and at the very least needs to call the kernel to tell it that you're done.
As to whether it's necessary? Yes, unless you fancy writing your own program prologue and epilogue each time. There are probably are ways of writing minimal, statically linked applications if you're sufficiently masochistic.
As for storage overhead, why are you getting so worked up? It's not enough to worry about.
There are several initialization functions that load whenever you run a program on Windows. These functions, among other things, call the main() function that you write - which is why you need either a main() or WinMain() function for your program to run. I'm not aware of other included functions though. Do you have some disassembly to show?
You don't have much detail to go on but I think most of what you're seeing is probably the routines of the specific C runtime library that your compiler works with.
For instance there will be code enabling it to run from the entry point 'main' which portable executable format understands to call the main(char ** args) that you wrote in your C program.

Few WinMain questions

I have few very simple question. I searched a web for them, but I found different answers so I just want to know which to follow.
So, first, I believe WinMain is NOT C or C++ standart, but is only added by Microsoft to determine when to load different CRT startup code, am I right?
And second, is WinMain called by OS, in a way of lets say similiar to dynamic linking, or is it just program startup point like main?
Why I ask? I mainly used C for programming MCUs. I am more HW oriented than SW, so I like MCUs, I find them and programming for them more "clear".
But when I started to get interested about C language itself and its standart, I found that its very hard. I mean, for example, on MCU, you need no int return type of main, as well as in win32 app you need different startup code than pure main has.
So, I like C but I find its standart to be somehow old. Thanks.
I believe WinMain is NOT C or C++ standart, but is only added by Microsoft to determine when to load different CRT startup code, am I right?
Yes. All C and C++ standards define main() (and only main()) as the program entry point (although its exact signature may vary between languages and standard versions).
And second, is WinMain called by OS, in a way of lets say similiar to dynamic linking, or is it just program startup point like main?
It is actually called from main(). There is a main() in Windows programs too, just hidden deep within WinAPI code.
Although it's all the same, consider C as being 3 languages:
Standard free standing
Standard hosted implementation
Extended hosted implementation
What you describe (WinMain) belongs to type 3.
Type 3 programs work on computers which describe the specific extensions they use
Type 2 has a lot of rules, but offers a guarantee that programs written in that type will work the same on every computer system with a standard C compiler (virtually every computer with a keyboard attached (including PDA, wrist watch, ..., ...)).
Type 1 is the same as type 2 minus a few of the rules and the standard library -- and it should work for every processor on Earth.
The text of the Standard is from 1999 2001 2004 2007. You can find a PDF at the ISO site ( http://www.open-std.org/jtc1/sc22/wg14/www/standards )

Call C (exposed) function from COBOL program

Some time ago, I had created a DLL to be used in another C program. Basically I exposed specific functions by using the following within my dll:
void __declspec(dllexport) MyFunc(myFirstArg, mySecondArg);
Then I added an external file (MyExposedDll.h) with all exposed functions and structures to the new C program and included it:
#include MyExposedDll.h
Now how can I use this dll (or mainly a dll) to a Cobol function? I need to expose a function that has two char* arguments and returns a boolean.
Thanks,
Sun
This should not be difficult in an IBM Z/OS environment with LE support.
Capture the boolean result using the
COBOL CALL RETURNING
form of the CALL statement. The string arguments are passed just as any other arguments in a COBOL CALL statement.
The only thing to be wary of is that C uses Null terminated strings whereas COBOL generally does not. You should review
how to handle null terminated strings in
COBOL.
Have a look at: Using COBOL DLLs with C/C++ programs this gives a really simple example showing a call to a C++ function returning a function pointer.
EDIT
I may have missed part of your question... When your COBOL program is linked-edited, you need to provide the your DLL IMPORT file so it can be bound. See linking DLL's.
EDIT 2
Based on your comments, I take it you are running your application on a Z/OS box. Visual Studio is a PC based product so I am guessing that you develop your code there but deploy it under Z/OS? In order to get the COBOL program to recognize your DLL you need to create a "side file" from your C program when it is compiled. This "side file" contains the DLL structures needed by the linker when the COBOL program is linked. You should be able to get the process worked out from the links provided above.

Some general C questions

I am trying to fully understand the process pro writing code in some language to execution by OS. In my case, the language would be C and the OS would be Windows. So far, I read many different articles, but I am not sure, whether I understand the process right, and I would like to ask you if you know some good articles on some subjects I couldnĀ“t find.
So, what I think I know about C (and basically other languages):
C compiler itself handles only data types, basic math operations, pointers operations, and work with functions. By work with functions I mean how to pass argument to it, and how to get output from function. During compilation, function call is replaced by passing arguments to stack, and than if function is not inline, its call is replaced by some symbol for linker. Linker than find the function definition, and replace the symbol to jump adress to that function (and of course than jump back to program).
If the above is generally true and I get it right, where to final .exe file actually linker saves the functions? After the main() function? And what creates the .exe header? Compiler or Linker?
Now, additional capabilities of C, today known as C standart library is set of functions and the declarations of them, that other programmers wrote to extend and simplify use of C language. But these functions like printf() were (or could be?) written in different language, or assembler. And there comes my next question, can be, for example printf() function be written in pure C without use of assembler?
I know this is quite big question, but I just mostly want to know, wheather I am right or not. And trust me, I read a lots of articles on the web, and I would not ask you, If I could find these infromation together on one place, in one article. Insted I must piece by piece gather informations, so I am not sure if I am right. Thanks.
I think that you're exposed to some information that is less relevant as a beginning C programmer and that might be confusing you - part of the goal of using a higher level language like this is to not have to initially think about how this process works. Over time, however, it is important to understand the process. I think you generally have the right understanding of it.
The C compiler merely takes C code and generates object files that contain machine language. Most of the object file is taken by the content of the functions. A simple function call in C, for example, would be represented in the compiled form as low level operators to push things into the stack, change the instruction pointer, etc.
The C library and any other libraries you would use are already available in this compiled form.
The linker is the thing that combines all the relevant object files, resolves all the dependencies (e.g., one object file calling a function in the standard library), and then creates the executable.
As for the language libraries are written in: Think of every function as a black box. As long as the black box has a standard interface (the C calling convention; that is, it takes arguments in a certain way, returns values in a certain way, etc.), how it is written internally doesn't matter. Most typically, the functions would be written in C or directly in assembly. By the time they make it into an object file (or as a compiled library), it doesn't really matter how they were initially created, what matters is that they are now in the compiled machine form.
The format of an executable depends on the operating system, but much of the body of the executable in windows is very similar to that of the object files. Imagine as if someone merged together all the object files and then added some glue. The glue does loading related stuff and then invokes the main(). When I was a kid, for example, people got a kick out of "changing the glue" to add another function before the main() that would display a splash screen with their name.
One thing to note, though is that regardless of the language you use, eventually you have to make use of operating system services. For example, to display stuff on the screen, to manage processes, etc. Most operating systems have an API that is also callable in a similar way, but its contents are not included in your EXE. For example, when you run your browser, it is an executable, but at some point there is a call to the Windows API to create a window or to load a font. If this was part of your EXE, your EXE would be huge. So even in your executable, there are "missing references". Usually, these are addressed at load time or run time, depending on the operating system.
I am a new user and this system does not allow me to post more than one link. To get around that restriction, I have posted some idea at my blog http://zhinkaas.blogspot.com/2010/04/how-does-c-program-work.html. It took me some time to get all links, but in totality, those should get you started.
The compiler is responsible for translating all your functions written in C into assembly, which it saves in the object file (DLL or EXE, for example). So, if you write a .c file that has a main function and a few other function, the compiler will translate all of those into assembly and save them together in the EXE file. Then, when you run the file, the loader (which is part of the OS) knows to start running the main function first. Otherwise, the main function is just like any other function for the compiler.
The linker is responsible for resolving any references between functions and variables in one object file with the references in other files. For example, if you call printf(), since you do not define the function printf() yourself, the linker is responsible for making sure that the call to printf() goes to the right system library where printf() is defined. This is done at compile-time.
printf() is indeed be written in pure C. What it does is call a system call in the OS which knows how to actually send characters to the standard output (like a window terminal). When you call printf() in your program, at compile time, the linker is responsible for linking your call to the printf() function in the standard C libraries. When the function is passed at run-time, printf() formats the arguments properly and then calls the appropriate OS system call to actually display the characters.

Resources