Win32 API: Introduction - 2020
Bookmark and Share
ms_icon.png

WinMain entry point

Here is the prototype of WinMain().

int CALLBACK WinMain(
  _In_  HINSTANCE hInstance,
  _In_  HINSTANCE hPrevInstance,
  _In_  LPSTR lpCmdLine,
  _In_  int nCmdShow
);
Familiar?
WinMain() is the conventional name used for a graphical Windows-based application entry point.

The parameter definition from msdn:

  • hInstance [in]
    Type: HINSTANCE A handle to the current instance of the application.
  • hPrevInstance [in]
    Type: HINSTANCE A handle to the previous instance of the application. This parameter is always NULL. If you need to detect whether another instance already exists, create a uniquely named mutex using the CreateMutex function. CreateMutex will succeed even if the mutex already exists, but the function will return ERROR_ALREADY_EXISTS. This indicates that another instance of your application exists, because it created the mutex first. However, a malicious user can create this mutex before you do and prevent your application from starting. To prevent this situation, create a randomly named mutex and store the name so that it can only be obtained by an authorized user. Alternatively, you can use a file for this purpose. To limit your application to one instance per user, create a locked file in the user's profile directory.
  • lpCmdLine [in]
    Type: LPSTR The command line for the application, excluding the program name. To retrieve the entire command line, use the GetCommandLine function.
  • nCmdShow [in]
    Type: int Controls how the window is to be shown.


Windows Data Type

The data types supported by Windows are used to define function return values, function and message parameters, and structure members. They define the size and meaning of these elements.

The following table contains the following types: character, integer, Boolean, pointer, and handle. The character, integer, and Boolean types are common to most C compilers. Most of the pointer-type names begin with a prefix of P or LP. Handles refer to a resource that has been loaded into memory.

More complete data types are MSDN - Windows Data Types.


Data Type Description
BYTE A byte (8 bits).
This type is declared in WinDef.h as follows:
typedef unsigned char BYTE;
DWORD A 32-bit unsigned integer. The range is 0 through 4294967295 decimal.
This type is declared in IntSafe.h as follows:
typedef unsigned long DWORD;
HINSTANCE A handle to an instance. This is the base address of the module in memory.
HMODULE and HINSTANCE are the same.
This type is declared in WinDef.h as follows:
typedef HANDLE HINSTANCE;
LPSTR A pointer to a constant null-terminated string of 8-bit Windows (ANSI) characters.
This type is declared in WinNT.h as follows:
typedef __nullterminated CONST CHAR *LPCSTR;
LPVOID A pointer to any type.
This type is declared in WinDef.h as follows:
typedef void *LPVOID;
TCAHR A WCHAR if UNICODE is defined, a CHAR otherwise.
This type is declared in WinNT.h as follows:
#ifdef UNICODE
typedef WCHAR TCHAR;
#else
typedef char TCHAR;
#endif
WCHAR A 16-bit Unicode character.
This type is declared in WinNT.h as follows:
typedef wchar_t WCHAR;
WINAPI The calling convention for system functions.
This type is declared in WinDef.h as follows:
#define WINAPI __stdcall
CALLBACK, WINAPI, and APIENTRY are all used to define functions with the __stdcall calling convention. Most functions in the Windows API are declared using WINAPI. We may wish to use CALLBACK for the callback functions that we implement to help identify the function as a callback function.
WORD A 16-bit unsigned integer. The range is 0 through 65535 decimal.
This type is declared in WinDef.h as follows:
typedef unsigned short WORD;


C / Win32 API

Developing software on Windows involved using the C in conjunction with the Windows API. While there have been numerous successful applications using the raw API has been really painful. First of all, the C language is not object oriented but structural. Also, programmers need to be very careful for manual memory management, and they have to face the tricky pointer arithmetic.

When we combine the numerous global functions and data types defined by the Win32 API to an already formidable language, it's not a surprise that there are many applications still struggling with so many bugs.




Title Description
MFC Desktop Applications Microsoft Foundation Classes provide a thin object-oriented wrapper over Win32 to enable rapid development of GUI applications in C++.
ATL COM Desktop Components ATL provides class templates and other use constructs to simplify creation of COM objects in C++.
ATL/MFC Shared Classes References for CStringT Class and other classes that are shared by MFC and ATL.
Visual C++ Parent topic for all C++ content in the MSDN library.



C++/Win32 MFC

Using C++ itself is a huge improvement over raw C/API programming. In essence, C++ is a C with a class. C++ can be considered as an object-oriented layer on top of C. However, several C features that bother programmers are still there.

MFC (Microsoft Foundation Class) provides the developer with a set of C++ classes that facilitates the creation of Win32 applications. Actually, MFC provides a thin object-oriented wrapper over the raw Win32 API to enable rapid development of GUI applications in C++. It provides a set of classes, magic macros, and numerous code-generation tools.

But we should admit that even with the help from the MFC framework, still programming in C++ remains difficult and error-prone due to the legacy from C.



COM (Component Object Model)

The COM was Microsoft's previous application framework. COM's idea was: "If we build our classes in accordance with the rules of COM, we end up with a block of reusable binary code."

The essence of a binary COM server is that it can be accessed in a language-independent manner so that C++ programmer can build COM classes that can be used by VB6. But it turns out, the language independence is limited. For example, there is no way to derive a COM class using an existing COM class since COM does not support inheritance. So, we should take cumbersome route to reuse COM class types.

Another benefit of COM is that it is location-transparent. In other words, using constructs such as application identifiers (AppID), stubs, proxies, and the COM runtime environment, programmers can avoid the need to work with raw sockets, RPC calls, and other low-level details.

To some people, even though COM may be considered as a very successful object model, it is really complex under the hood. The ATL (Active Template Library) came out to help simplify creation of COM objects by providing another set of C++ classes, templates, and macros.

However, language support alone is not enough to hide the complexity of COM. For example, even when we choose a relatively simple COM-aware language such as VB6, we're still forced to contend with fragile registration entries and numerous deployment-related issues regarding dlls.