Try to answer before you open the answers. Guessing is fine; checking your guess is how you learn.
QUICK REVIEW (5 minutes)
- List the layers a request passes through, from the application down to the hardware.
- Which DLLs hold the Win32 API, and which DLL holds the Native API?
- What does the
Wat the end ofCreateFileWmean? - What is the job of an
Nt...stub inntdll.dll? - Which CPU instruction does 64-bit Windows use to enter the kernel?
- What is the SSDT for?
- Which function do you call to learn why a Win32 call failed?
- What does the command
net helpmsg 5print? - What is an API set such as
api-ms-win-core-file-l1-1-0.dll? - What does a successful
CreateFileWhand back to the program?
ANSWER KEY — DO NOT READ UNTIL YOU'VE ANSWERED
Click to reveal answers
1. The layers
Application (and its language runtime) → Win32 API → Native API (ntdll.dll) → system call instruction → kernel (ntoskrnl.exe) → drivers → hardware.
2. Which DLLs
Win32 is spread over kernel32.dll, kernelbase.dll, user32.dll, gdi32.dll, advapi32.dll and others. The Native API is in ntdll.dll.
3. The W suffix
Wide: the function takes Unicode (UTF-16) text. The A version takes ANSI text.
4. Nt stub
It loads a service number into a register, runs the syscall instruction to enter the kernel, then returns the result.
5. The instruction
syscall (with sysret to return). 32-bit Windows used sysenter, and very old Windows used int 0x2E.
6. SSDT
The System Service Dispatch Table: the kernel's table that maps a service number to the kernel code that handles it.
7. Finding the reason
GetLastError(), called right after the failing call.
8. net helpmsg 5
Access is denied.
9. API set
An umbrella DLL name. It stands for a group of functions. Windows swaps it for the real DLL (such as kernelbase.dll) when the program loads.
10. The return value
A handle: a ticket number for the opened file. The real object stays in the kernel.
UNDERSTANDING QUESTIONS
Q1. Why can a program not simply call the kernel directly, or touch the disk itself?
Answer
Programs run in user mode (ring 3), where the CPU does not allow hardware access or access to other programs' memory. Only kernel code in ring 0 may do that. The kernel stands at the one door (the system call), checks every request and then acts. This protects the PC from buggy or malicious programs.Q2. Why does Windows keep Win32 stable but allow the Native API to change?
Answer
Millions of programs are built on Win32, so Microsoft promises its names and behaviour stay the same. The Native API and system call numbers are internal details. By keeping them private, Microsoft can rebuild the inside of Windows freely. Win32 absorbs the changes, so programs keep working.Q3. Why do many Win32 functions come in A and W versions, and which is better?
Answer
Old Windows used one-byte ANSI text, which cannot hold every language. Newer Windows uses Unicode. Microsoft kept the A versions so old programs still work. The A version converts the text and calls the W version, so W is the real one, handles every language and is slightly faster. Prefer W.Q4. Why does Win32 wrap the Native API instead of exposing it?
Answer
Win32 offers friendlier inputs, converts paths and text into the kernel's format, translates NTSTATUS codes into Win32 errors and hides changes that happen in the Native layer between versions. It gives one steady, documented interface.Q5. Why is a system call more expensive than a normal function call?
Answer
It crosses the ring 3 to ring 0 border. The kernel must save the program's state, check all inputs, do the work and restore the state. A normal call just jumps to nearby code in the same mode. This is why programs should avoid thousands of tiny calls.SCENARIO QUESTIONS (Troubleshooting)
S1. A program shows "Error 5" when saving into a folder. What does it mean, and which layer decided it?
Answer
Error 5 is `ERROR_ACCESS_DENIED`. The kernel's security check refused the request. The kernel produced `STATUS_ACCESS_DENIED` and Win32 translated it to 5. Check the folder's permissions, or whether the program needs to run with higher rights.S2. A crash report says "Faulting module: KERNELBASE.dll". Is that DLL corrupt?
Answer
Usually not. `kernelbase.dll` holds core Win32 code, so a failing call is often reported there, even when the real cause is the program's own mistake, such as a bad input. Look at the program, its recent changes and its other modules before blaming the DLL.S3. In Process Monitor you see hundreds of NAME NOT FOUND results. Is something broken?
Answer
Usually not. Programs often search several places for a file or registry key and take the first one that exists. A "not found" result for the first places is normal. It is only a problem if the program later fails because the item never turned up.S4. A file copy tool is very slow because it reads one byte at a time. How can the API chain explain it, and what fixes it?
Answer
Each byte means a call through Win32, Native API and a system call, with a ring switch each time. The overhead dominates. Reading and writing in large blocks, for example tens or hundreds of kilobytes, reduces the number of trips.S5. A program written for Windows 7 runs on Windows 11 even though the Native API and system call numbers changed. Why?
Answer
It calls Win32 functions (directly or via a runtime), not system calls. The Win32 contract stayed the same, and Windows 11 maps those calls to its own Native API and kernel. The program never sees the changed inside parts.INTERVIEW QUESTIONS
I1. Walk through what happens when a program calls CreateFileW.
Answer
The call goes to `kernel32.dll`, then `kernelbase.dll`, which checks the inputs, expands and converts the path, and builds the Native structures. It calls `ntdll!NtCreateFile`, a stub that loads the service number and runs `syscall`. The CPU switches to ring 0, the kernel looks up the service in the dispatch table, and the I/O and Object Managers check security and build a request. The file system driver and disk driver talk to the SSD. The result and a handle return the same way, `sysret` brings the CPU back to ring 3, and `kernelbase.dll` translates the NTSTATUS to a Win32 result.I2. What is the difference between Win32 error codes and NTSTATUS values?
Answer
Win32 errors are small numbers (such as 2 or 5) returned through `GetLastError`. NTSTATUS values are 32-bit codes from the Native API and kernel (such as `0xC0000022`), whose top bits show success, warning or error. Win32 translates NTSTATUS values into Win32 codes.I3. What is the difference between Nt and Zw functions?
Answer
In user mode they are effectively the same stub. Inside the kernel, `Nt` and `Zw` handle the caller's privilege and security checks differently, with `Zw` treating the call as coming from trusted kernel code. That difference matters mostly to driver writers.I4. What are API sets, and why do they exist?
Answer
They are virtual DLL names such as `api-ms-win-core-*.dll` that stand for a group of functions. Windows redirects them through a map to the real DLL that holds the code. This lets Microsoft move code between real DLLs, and between Windows editions, without breaking programs.I5. Why does Microsoft advise against calling ntdll.dll functions directly?
Answer
Most are undocumented, may change between Windows versions, and the system call numbers underneath change. A program using them can break after an update. Win32 is the documented, supported, backward-compatible contract.PRACTICAL TASK
Trace one call yourself. In Process Monitor, filter on one program (Notepad is fine) and save a file. Pick one CreateFile row and write down a chain in your own words: the program, the DLLs in the Stack tab (such as KERNELBASE.dll and ntdll.dll), the operation name, the path and the result. Then write the Win32 and Native function names you think were used, and the Win32 error number the program would see if the result were NAME NOT FOUND (use net helpmsg to check your answer).
Why This Matters
When a program fails to open a file, crashes or runs slowly, the cause is somewhere on this chain. Knowing the layers tells you where to look: the program's own call, the Win32 error, the kernel's security decision, or the device at the bottom.
CHAPTER SUMMARY
- A request travels: application → Win32 API → Native API (
ntdll.dll) →syscall→ kernel → driver → hardware, and the answer returns the same way. - Win32 is the documented, stable contract. It lives in
kernel32,kernelbase,user32,gdi32,advapi32and others. API sets are umbrella names that redirect to real DLLs. - A and W versions exist for history; Windows works in Unicode, so use W.
- The Native API (
NtandZwfunctions) is the last user-mode step, mostly undocumented and free to change, so Win32 wraps it. - A system call crosses from ring 3 to ring 0 using
syscall. The kernel finds the service through the SSDT, validates the request and does the work. - Errors: GetLastError (Win32 codes) versus NTSTATUS (Native and kernel codes). Translate with
net helpmsg. - You can see all of this safely with
dir,tasklist /m, PowerShell P/Invoke and Process Monitor.
REFERENCES AND RELATED CHAPTERS
- Previous: Chapter 22 — DLLs
- Related: Chapter 2 — CPU Internals (privilege levels), Chapter 7 (kernel and user mode), Chapter 9 (handles)
- Next: Chapter 24 — Windows Authentication (coming soon)
- Related: Chapter 23 Overview