Windows System and its Programming Model
Let's begin our Windows journey by referencing some of its parts to Linux. It's totally fine if you are not familiar with Linux Systems. I will try to explain all the core concepts you need to understand.
Prerequisite: If you are new in programming then make sure to READ_THIS_BLOG before continuing further. It will give you the idea of a basic general model of a program.
* The Great Difference
When talking about the differences between Windows and Linux, the first thing that comes up to me is the system-call concept.
On Linux, a programmer can choose to talk directly to its kernel (or simply the operating system), for example: by using the open() or write() system calls.
System Calls?
A System call is a programmatic way a program request a service from the Kernel.
But on Windows, you can't talk directly to its kernel, unlike Linux.
WHY?
On Windows, talking directly to its kernel would be quite inconvenient since each new release of Windows version and its service packs changes its kernel interface.
Wait! Why do we need to talk to kernel in the first place? (This question can turn quite silly)
After all, your C program functions are actually just a wrapper to those kernel system calls.
I think everything starts to make sense as anything done on our computer is performed and organized by our operating system (kernel is just a part of the Operating System). And System calls are a way to communicate to our operating system.
OK, back to Windows...
Since its kernel interface changes frequently, Windows NT introduces the WIN32API.
WIN32API gives programmer a stable API to work with (like those system calls in Linux).
An advantage to mention is that this gives Windows Kernel Team a way to change their internal Kernel's functionality or add totally new functionality while still providing a stable API for programmers to work with.
* SHARED LIBRARY
On Linux, a shared library is a file containing object code that is shared among several executable files. The code in the shared library can be used by several executables simultaneously.
You can think of this concept as just sharing your C program's function with other programs without actually rewriting those function but rather linking the function file to the program.
This concept of shared library also applies to Windows in the form of DLL (Dynamic-link library).
And our WIN32API from the previous section is just an orderly set of DLLs, so any process using the WIN32API uses Dynamic-link library.
Shared Library files in Linux would be .so files which is an ELF file format.
But a DLL is in PE-COFF file format (or simply PE or portable executable).
Portable Executable?
"The Portable Executable format is a file format for executables,
object code, DLLs and others used in 32-bit and 64-bit versions of
Windows operating systems. The PE format is a data structure that
encapsulates the information necessary for the Windows OS loader to
manage the wrapped executable code." -- WIKIPEDIA
* HEAP
In Linux, usually a single default heap space is created for a process.
While on windows, the heap is created every time a DLL gets loaded using HeapCreate() and stores a global variable as a pointer to that heap so that any allocation operations in the future can use it instead of the default heap.
Usually, many DLLs are loaded so there are many heaps. The example below will clear your confusion regarding the above heap statement.
Example Scenario:
When we call malloc() in Windows (WIN32) we are actually using HeapAllocate() function exported by msvcrt.dll . And we are also using the msvcrt's private heap.
Each process also has its default heap (like on Linux). The default heap can be found with GetDefaultHeap() function.
Short break:
Grab me a coffee. I need coffee to THINK!!!. Think of more amazing posts for you.
* THREADING
Windows has no fork() (used to spawn a new process in Linux).
In Windows, CreateProcess() will spawn a new process with its own memory space.
A process has its own virtual address space (means it has its own code section and other data sections) and it's not accessible by other processes.
And each process can have several threads doing different tasks. A thread has its independent stack and its set of registers. It also means that they share code section, global variables etc.
* TOKEN
Another important concept for Windows programming would be the concept of Tokens.
So, What's a Token?
As the name suggests they represent access rights. Technically they are just 32-bit integer much like a file descriptor. The Windows kernel maintains a system of token per process and that token represents the access rights of the process.
For Example: When a process wants to access a file, the process' token is checked to see if it has the permission to do so.
Simply, a low privileged user's process cannot access higher privileged system files.
Now things will get a little more complicated when we go deeper as there are several types of tokens and only two tokens can affect each operation: the primary token and current thread token.
The primary token is assigned when a process starts up carrying the access rights of the user who started the process (normally).
The current thread token can be thought of as borrowing access rights. We can set/assign any current thread token to a thread.
How do we get this token?
The Current thread token can be obtained from another process or from LogonUser() function. Username and Password is fed to LogonUser() function and it returns a new token if successful. And to attach any token to your thread use the SetThreadToken(token_to_attach) and remove it with RevertToSelf(), which will revert to the primary token.
That's it for token.
Well, there is a lot more to cover but let's continue later.
Hope you learn something today :)
Please let me know if there is any mistake.
What topic do you want to see next?