Level 4 · Chapter 3
Kernel objects
The common language of Windows internals: how processes, files, events, and tokens all become the same kind of thing underneath.
Processes & threads mentioned a handle table without explaining what a handle actually points to. This chapter is about the Object Manager — the Executive component that gives Windows one uniform model for naming, referencing, securing, and managing the lifetime of practically every kind of kernel resource.
One model, many object types
Files, processes, threads, events, mutexes, semaphores, sections (memory mappings), tokens, and many more are all, underneath, kernel objects — instances of a specific object type, but all sharing the same fundamental machinery: a name (optional, but many objects have one), a security descriptor (the same kind covered in Security descriptors & ACLs), and a reference count. This uniformity is exactly why a single access-check algorithm (Access checks & the Security Reference Monitor) can apply to files, registry keys, and processes alike — from the Security Reference Monitor's point of view, they're all just objects with descriptors.
Handles: indirect, per-process references
User-mode code never touches a kernel object directly — it holds a handle, an opaque integer that's meaningful only within the context of the process holding it. Each process has its own handle table, mapping its handles to the underlying objects; the same handle value in two different processes can refer to two completely unrelated objects, because the table itself is per-process.
This indirection is what makes reference counting safe and automatic: opening a handle to an object increments its reference count; closing the handle decrements it. When the count reaches zero and no other references remain, the Object Manager tears the object down. Nothing about this requires user-mode code to know or care whether any other process also holds a reference to the same object — the accounting is handled uniformly, underneath, regardless of who's holding what.
Why leaked handles are a real, gradual problem
A process that opens handles and never closes them keeps the underlying objects alive indefinitely — the reference count never drops to zero, so the Object Manager has no signal that it's safe to release the resource. Over long uptimes, this is exactly the mechanism behind a class of production issues that look like "the system just gets slower over days": a handle leak (to files, registry keys, or GUI objects, as covered in USER & GDI objects) doesn't crash anything immediately, it just slowly consumes a finite resource until something else — often a completely unrelated operation — starts failing because the table or quota is exhausted.
A worked example: named vs. unnamed objects
Some objects (a mutex meant to coordinate two unrelated processes, say) are given a name, letting a second process find and open the same underlying object by looking it up through the Object Manager's namespace, rather than needing the original process to hand it a duplicated handle directly. Other objects (a private event used only within one process) are created unnamed — nothing outside that process's own handle table can reach them at all. This is a deliberate design choice each caller makes at creation time, trading discoverability against isolation depending on what the object is actually for.
A common mistake
Thinking of a handle as "basically the object" — as if closing it necessarily destroys the underlying resource immediately — misses the reference-counting model entirely. Closing your handle only removes your reference; if another process (or another part of the same process) still holds a reference, the object stays alive until every reference is gone. This is exactly why two processes can share access to the same named event or shared-memory section safely, each with its own independent handle, neither one able to unilaterally destroy it out from under the other.
Where this connects
- Processes & threads is itself one specific object type managed this same way — a process is, from the Object Manager's point of view, just another named, securable, reference-counted object.
- Security descriptors & ACLs covers what every object's security descriptor actually contains.