The Big Picture: Following a Parcel
Think of a parcel being sent from your door to a faraway warehouse. It goes through a local post office, a sorting centre, a lorry, a depot and finally the warehouse. Then a receipt travels back. You see only two things: you hand it over, and the receipt arrives.
A single Windows call works the same way. This section follows one real call all the way down and back, step by step. Sections 1 to 4 gave you each stage. Now you see them join up.
Our example: a program wants to create a file called notes.txt.
5.1 Step 1: The Application Calls a Win32 Function
What it is: The program (or its language runtime) calls CreateFileW.
HANDLE h = CreateFileW(L"notes.txt", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);In plain English: "Open notes.txt for writing. If it exists, replace it. If it does not, make it."
How the program finds CreateFileW: when it started, the Windows loader (Chapter 22) read the program's import list, loaded kernel32.dll, and wrote the address of CreateFileW into the program's import table. The call is therefore a normal function call, still inside the program's own process, in user mode.
Note. If the program is written in Python, C#, Java or another language, its runtime calls
CreateFileWon its behalf (see Section 1.3).
5.2 Step 2: Win32 Calls the Matching Native API Function
What it is: kernel32.dll forwards the call to kernelbase.dll, which does the Win32 tidy-up. If the program named an API set (Section 2.5), Windows has already swapped it for the real DLL. Then kernelbase.dll:
| Task | Example |
|---|---|
| Checks and fixes inputs | Is the file name too long? Is it empty? |
| Expands the path | notes.txt becomes C:\Users\You\notes.txt, based on the program's current folder |
| Changes it to the kernel's style | \??\C:\Users\You\notes.txt |
| Builds Native structures | A UNICODE_STRING and an OBJECT_ATTRIBUTES (Section 3.2) |
| Chooses the Native function | NtCreateFile |
Then it calls ntdll!NtCreateFile. (The ! is how people write "function X inside DLL Y": dll!function.)
5.3 Step 3: The Native API Runs the System Call
What it is: NtCreateFile is a tiny stub in ntdll.dll. It loads its service number into a register and runs the syscall instruction (Section 4.3). The CPU switches from ring 3 to ring 0. We have now crossed the border.
5.4 Step 4: The Kernel Handles the Request
What it is: The kernel entry point looks up the service number in the dispatch table (SSDT, Section 4.2) and runs the kernel's NtCreateFile. This code, inside ntoskrnl.exe, belongs to the I/O Manager and the Object Manager. It:
- Checks that the pointers the program gave are really in the program's memory.
- Looks up the path in the Object Manager's namespace (the kernel's own tree of names).
\??\C:points to the disk volume for drive C. - Asks the Security Reference Monitor: "Is this user allowed to create a file here?" (This is where
ERROR_ACCESS_DENIEDcan start.) - Creates a file object and a handle for it (Chapter 9).
- Builds an I/O request, a package that says "create this file", and sends it down to the right driver.
5.5 Step 5: The Kernel Calls Into a Driver if Hardware Is Involved
What it is: The I/O Manager passes its request package to a stack of drivers, each doing one job. The first is the file system driver (for most PCs, NTFS, the file system you will meet in the later chapters on file systems and storage). It:
- Works out where on the disk the file's information goes.
- Updates its records (the file name, size, time stamps, the journal that protects it against crashes).
- Hands a smaller request to the volume and disk drivers below it.
File system driver (NTFS) "create 'notes.txt' in this folder"
│
▼
Volume / partition driver "translate to a place on the disk"
│
▼
Disk / storage driver "send this command to the SSD"
A recently written file is often kept in RAM first, in the cache, and written to the disk a little later. So a call to create a file may be answered quickly even before the SSD has finished. Windows lets programs ask for stronger guarantees when they need them.
5.6 Step 6: The Driver Communicates With the Hardware
What it is: The lowest driver in the stack, for an SSD usually the NVMe driver (Chapter 4 explained NVMe and PCIe), writes a command into a queue in RAM and rings a "doorbell" on the device. The SSD then reads the command using DMA (Chapter 4, Section 4), does the work and sends back an interrupt (Chapter 4, Section 3) to say "done". The driver's interrupt handler marks the request as finished.
5.7 Step 7: The Result Returns Back Up the Chain
What it is: The answer takes the same road in reverse:
| Step | Who | What they do |
|---|---|---|
| 1 | Driver | Marks the request complete |
| 2 | I/O Manager | Fills in a status block (success, plus how many bytes) |
| 3 | Kernel | Returns an NTSTATUS and the new handle to the syscall return path |
| 4 | CPU | Executes sysret: back to ring 3 |
| 5 | ntdll!NtCreateFile | Returns to its caller |
| 6 | kernelbase.dll | Translates NTSTATUS into a Win32 result. On success, returns the handle. On failure, returns INVALID_HANDLE_VALUE and stores an error code |
| 7 | The program | Receives the handle and keeps going |
The handle is just a ticket number. The real object stays in the kernel. The program only holds the ticket, and uses it for later calls such as WriteFile(h, ...) and CloseHandle(h).
5.8 The Whole Chain in One Picture
┌───────────────────────────────────────────────────────────┐
│ USER MODE (ring 3) │
│ │
│ Your program: CreateFileW(L"notes.txt", ...) │
│ │ ▲ │
│ ▼ │ │
│ kernel32.dll ──► kernelbase.dll (Win32 work) │ │
│ │ │ │
│ ▼ │ │
│ ntdll.dll: NtCreateFile (stub) │ │
│ │ syscall handle │ │
└────────┼──────────────────────────────────────────┼───────┘
═════════╪═══════ border: ring 3 / ring 0 ═══════════╪════════
┌────────▼──────────────────────────────────────────┴───────┐
│ KERNEL MODE (ring 0) │
│ │
│ System service dispatch (SSDT) ──► NtCreateFile │
│ │ (ntoskrnl.exe) │
│ ▼ │
│ Object Manager + Security check + I/O Manager │
│ │ │
│ ▼ │
│ File system driver (NTFS) ──► disk driver (NVMe) │
└────────┼──────────────────────────────────────────────────┘
▼
SSD hardware (command via DMA, then an interrupt back)
The whole trip normally takes a tiny fraction of a millisecond when the data is in the cache. It takes longer if the SSD has to be reached.
5.9 A Second Example: MessageBox and VirtualAlloc
The same layers apply to every call. Here are two other trips, shown briefly.
Example A: VirtualAlloc. "Give me memory."
Program VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)
│
▼
kernel32 / kernelbase (Win32: checks the inputs)
│
▼
ntdll!NtAllocateVirtualMemory ──► syscall
│
▼ ring 0
Memory Manager finds a free range of virtual addresses and
sets it up (no physical RAM is used until touched)
│
▼
Back up: the program gets the starting address of the new memory
No driver and no hardware is involved. The Memory Manager is part of the kernel. This is the virtual memory idea from Chapter 3 (and Chapter 8). The result is an address, not a handle.
Example B: MessageBoxW. "Show a pop-up."
Program MessageBoxW(NULL, L"Hello", L"Title", MB_OK)
│
▼
user32.dll (the window and message part of Win32)
│
▼
win32u.dll (a small bridge that makes the window system calls)
│
▼ syscall (to the window-system part of the kernel, "win32k")
│
▼ ring 0
Window manager creates the pop-up; the graphics driver draws it
Unlike a file call, a window call goes through user32.dll and win32u.dll, not through the file Native API. It uses the second table of services (the "shadow" table from Section 4.2). The idea is the same, and you can still see ntdll.dll and kernel32.dll used along the way.
| Call | Starts in | Native or bridge layer | Kernel part | Driver and hardware? |
|---|---|---|---|---|
CreateFileW | kernel32 / kernelbase | ntdll!NtCreateFile | I/O and Object Managers | Yes (file system, disk) |
VirtualAlloc | kernel32 / kernelbase | ntdll!NtAllocateVirtualMemory | Memory Manager | No |
MessageBoxW | user32 | win32u.dll | Window system | Yes (graphics) |
5.10 Why This Knowledge Is Useful
| Situation | How the chain helps |
|---|---|
| A program says "Access denied" | The error began in the kernel's security check and was translated up |
| A program is slow reading tiny pieces | Each call is a full trip through the chain. Read in bigger blocks |
Security software shows NtCreateFile | Now you know it is the Native version of "create/open file" |
Process Monitor shows CreateFile | It shows the file operation at the kernel side. Section 6 lets you try |
| An old program works on Windows 11 | It uses Win32, which is stable. The layers below changed freely |
Summary
| Step | Layer | Mode |
|---|---|---|
| 1 | Application calls CreateFileW | User |
| 2 | kernelbase.dll checks inputs, builds structures, calls NtCreateFile | User |
| 3 | ntdll.dll stub runs syscall | User, then crosses the border |
| 4 | Kernel dispatches and validates (I/O, Object, Security) | Kernel |
| 5 | File system driver, then disk driver | Kernel |
| 6 | SSD does the work (DMA, interrupt) | Hardware |
| 7 | Result and handle return up the same road | Kernel, then user |