Windows Programming/Windows System Architecture
Windows was originally a 16-bit graphical layer for MS-DOS that was written by Microsoft. As it grew, it gained the ability to handle 32-bit programs and eventually became totally 32-bit when Windows NT and 2000 came out. After Windows 95, Microsoft began to remove dependencies on DOS and finally fully implemented the separation in Windows 2000. Windows has many advanced features as well as many platform specific problems. It possesses an Application Programming Interface that consists of thousands of mostly undocumented GUI functions as well as having varying degrees of MS-DOS compatibility. Additionally, with the advent of NT (New Technology), Windows relies completely on the NT kernel instead of its MS-DOS subsystem, the NT kernel is capable of emulating the necessary DOS functionality. In addition to the NT kernel, Microsoft has also introduced many API wrappers, such as the MFCs (Microsoft Foundation Classes), COM (Component Object Model), and .NET technologies.
Windows 1.0, 2.0, and 3.11 are considered to be an older generation of Windows systems that were built to be a simple graphical layer over the MS-DOS operating system. Windows 95, Windows 98, and Windows ME were designed to bypass MS-DOS (although DOS was still present), and were all based on the same code structure known as the "9x Kernel". Windows NT 4.0, Windows 2000, Windows XP, Windows Vista, Windows 7, and Windows Server are all based on a collection of code known as the "NT Kernel".
Today we’re starting a new series of posts focused on understanding the Windows System Architecture itself. In our first post, we’re going to quickly review some basic Windows concepts and terms including a brief overview of the Windows API, Services and the difference between a Process and a Thread. Think of this as laying the groundwork for our future posts which will cover topics such as the Registry, Session Space and Desktop Heap. So, without further ado – let’s start with an introduction to the Windows API.
The Windows NT Kernel is divided into several sections, here we will briefly discuss how the Windows operating system is put together. At the most basic level is the file NTOSKRNL.EXE, the kernel of the Windows operating system, and the most important file on your computer. If you are interested in seeing this for yourself, you can find it in the C:\Windows\System32 folder (this can also be found using the following path %systemroot%\system32 ) on your own Windows NT machines.
NTOSKRNL.EXE provides some of the basic functionality of Windows, but one file alone cannot make the whole system work. NTOSKRNL relies heavily on a Dynamic Link Library (DLL) known as HAL.DLL. HAL stands for "Hardware Abstraction Layer", and is the portion of code that allows low-level mechanisms such as interrupts and BIOS communication to be handled independently.
If we consider Windows architecture as a layered architecture, with NTOSKRNL.EXE and HAL.DLL on the bottom layer, the next layer up contains two important files, NTDLL.DLL, and WIN32K.SYS. NTDLL contains a number of user-mode functions such as system call stubs and the run-time library (RTL) code, collectively known as the (largely undocumented) "Native API". Much of the run-time library code is shared between NTOSKRNL and NTDLL. WIN32K.SYS is a kernel-mode driver that implements windowing and graphics, allowing for user interfaces to be created.
The next layer up contains a number of libraries that will be of primary interest to us. This layer comprises what is called the Win32 API, and it contains (almost) all the functions that a user will need in order to program in Windows. The Win32 API is divided into 4 component parts, each one a .DLL:
- This contains most of the system-related Win32 API functions. Most of these functions are just wrappers around the lower-level NTDLL functions, but some functionality such as National Language Support (NLS) and console handling are not available in NTDLL.
- This contains other system-related functions such as registry and service handling.
- This contains a number of basic functions for drawing. These functions are all relatively simple, and allow the user to draw shapes (circles, rectangles, etc.) on the screen, to display and manipulate bitmaps, etc.
- This contains a number of functions that implement the familiar user-interface of Windows. Programs, message boxes, prompts, etc are all implemented using the User32 functions. User32 performs its tasks by calling system calls implemented by WIN32K.SYS.
In addition to the 4 primary libraries in the Win32 API, there are a number of other important libraries that a Windows programmer should become familiar with:
- MSVCRT.DLL is the dynamic link library that contains the implementations of the C standard library (stdlib) functions that C programmers should be familiar with. These are the functions defined in the common header files stdio.h, string.h, stdlib.h, etc.
- This is the Winsock2 library, that contains the standard Berkeley socket API for communicating on the internet. We will talk about winsock programming later in this book.
Windows Does It
The Windows system, it might be surprising for some people to learn, is a very hands-on system. This is not a familiar concept for people who are just beginning C programming using the standard library. In a normal software project, there is typically a main function, and the main function in turn calls other functions that are defined in your project. In a Windows function, typically the programmer provides function pointers to the system, and Windows will make calls into your program. Also, in a Windows program, your code will sit idle when there is nothing to be done. Using the message loop architecture, Windows will send messages to your program when an event needs to be handled, and the program responds to the messages. If the program doesn't respond, the message is ignored.
For each program, Windows sets up a message queue structure to handle the message transmission process. Windows will maintain a listing of all the objects and system resources in use by a program, and will assign each one a handle. These handles are useless by themselves, but they can be passed to the system to reference particular objects and resources.