Windows对象管理
体系结构

Windows NT操作系统体系结构中，对象管理子系统管理所有的资源。资源被表示为对象。对象管理子系统保持着对每个对象的引用计数。任何访问对象的系统调用都必须通过对象管理子系统。Windows对象可分为内核对象、用户对象、GDI对象：
用户对象（User interface object）：支持窗口管理。每个对象仅有一个句柄，句柄不能复制或继承，不能引用其他用户会话中的进程的用户句柄。任何进程只要有对某个用户句柄的安全访问权限，即可以访问该用户对象，即用户对象在当前会话下是全局的。一个进程最多有 65536 个用户对象句柄。用户对象包括：快捷键表HACCEL、插入点HCaret、鼠标指针HCURSOR、DDE 会话、窗口钩子HOOK、图标 HICON、菜单 HMENU、窗口 HWND、窗口位置Window position。
GDI 对象：支持图形。每个对象仅有一个句柄，句柄为进程私有。一个进程最多有 65536 个 GDI 对象句柄。GDI 对象包括：位图 HBITMAP、画刷 HBRUSH、设备环境HDC、增强型图元文件（EMF）、EMF 设备环境、字体 HFONT、内存 DC、图元文件Metafile、图元文件 DC、调色板 HPALETTE、画笔 HPEN、区域（Region）HRGN。
内核对象：支持内存管理、进程执行、进程间通信。内核对象句柄是进程私有的，必须创建或者打开内核对象以获取其句柄。当进程创建或打开内核对象时，进程的句柄表中增加一个条目指向内核对象实例。进程的句柄表的索引称为句柄（handle）。对象管理子系统使用句柄与命名两种方式管理对象实例。句柄在一个进程内部是线程共享的，但在进程之间不是直接可复用，需要特别方式在进程间传递对象句柄。一个进程任何时刻最多拥有 224，即大约 16,000,000 个句柄。句柄按照对象的分类可分为文件句柄、事件句柄、进程句柄等。一个进程对一个对象可以有多个句柄，以便按照不同权限来访问对象。
对象可分为内核对象（Kernel objects）与执行对象（Executive objects）。内核对象表示一些基本资源，如物理设备、同步服务等等。用户态的程序不能访问内核对象。用户态的系统服务与应用程序使用执行对象，这是Windows Executive对外暴露的对象，用来封装一个或多个内核对象。执行对象还用于实现 NT 子系统或 POSIX 子系统的一些功能。
Windows NT 暴露的执行对象包括:
| 类别 | 描述 | 创建 / 获取句柄系统调用 | 创建 / 获取句柄函数 | 释放句柄函数 | 未通知状态 | 通知状态 | 等待成功的副作用 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 目录 | 用来存放内核对象。多级嵌套的目录将所有内核对象组织成一个树形结构 | NtCreateDirectoryObject NtOpenDirectoryObject |  |  |  |  | 无 |
| 进程 | 线程的集合，拥有共同的虚拟内存空间与控制信息 | NtCreateProcess NtOpenProcess | CreateProcess OpenProcess GetCurrentProcess | CloseHandle TerminateProcess | 进程仍然活动时 | 进程终止运行时 （TerminateProcess ExitProcess） | 无 |
| 线程 | 进程内部，执行程序的实体。 | NtCreateThread NtOpenThread | CreateThread CreateThreadEx OpenThread GetCurrentThread | CloseHandle TerminateThread | 线程仍然活动时 | 线程终止运行时 （TerminateThread ExitThread） | 无 |
| 作业 | 进程的集合 | NtCreateJobObject NtOpenJobObject | CreateJobObject | CloseHandle | 当作业的时间尚未结束时 | 当作业的时间已经结束时 | 无 |
| 文件 | 一个打开的计算机文件或 I/O 设备。 | NtCreateFile NtOpenFile | CreateFile | CloseHandle DeleteFile | 当 I/O 请求正在处理时 | 当 I/O 请求处理完毕时 | 无 |
| 文件映射对象 | 一块内存区域，映射到一个文件。 | NtCreateSection NtOpenSection | CreateFileMapping | CloseHandle |  |  |  |
| 访问令牌 | 一个对象的访问权。 | NtCreateToken NtDuplicateToken NtOpenProcessToken NtOpenThreadToken | CreateRestrictedToken DuplicateToken DuplicateTokenEx OpenProcessToken OpenThreadToken | CloseHandle |  |  |  |
| 事件 | 封装了某些信息的一个对象，用于通知某些进程。 | NtCreateEvent NtOpenEvent | CreateEvent CreateEventEx OpenEvent | CloseHandle | ResetEvent，或 PulseEvent，或自动重置事件等待成功 | 当调用 SetEvent，或 PulseEvent | 自动重置事件等待成功后将自动重置 |
| 信号量 | 用于串行化访问某些资源的对象。 | NtCreateSemaphore NtOpenSemaphore | CreateSemaphore CreateSemaphoreEx OpenSemaphore | CloseHandle | 当数量 <=0 时 | 当数量 >0 时（ReleaseSemaphore） | 数量减 1 |
| 互斥锁 | 用于串行化访问某些资源的对象。 | 无 | CreateMutex CreateMutexEx OpenMutex | CloseHandle | 被其他线程拥有时 | 未被其他线程拥有时 | 等待成功的线程获得 CPU 所有权 |
| 临界区域 | 使得指定的代码段被串行执行 | 无 | InitializeCriticalSection InitializeCriticalSectionAndSpinCount | DeleteCriticalSection | 被其他线程拥有时（试图 EnterCriticalSection） | 未被其他线程拥有时（LeaveCriticalSection） | 等待成功的线程获得 CPU 所有权 |
| 定时器 | 按照固定时间间隔通知某些进程的对象。 | NtCreateTimer NtOpenTimer | CreateWaitableTimer CreateWaitableTimerEx | CloseHandle | CancelWaitableTimer 或自动重置定时器等待成功 | 当时间到时（SetWaitableTimer） | 自动重置定时器等待成功将 reset |
| Timer queue |  | 无 |  |  |  |  |  |
| Timer-queue timer |  | 无 |  |  |  |  |  |
| 注册表键值 | Windows 注册表条目的键值，数据类型不是 HANDLE 而是 HKEY |  | RegCreateKeyEx RegOpenKeyEx | RegCloseKey |  |  |  |
| 桌面 | 包含 GUI 元素的一个逻辑显示面，数据类型是 HDESK | 无 | CreateDesktop OpenDesktop GetThreadDesktop | CloseDesktop |  |  |  |
| WindowStation | 包含一些桌面对象、一块剪贴板对象、以及其他对象的对象，数据类型是 HWINSTA | 无 | CreateWindowStation OpenWindowStation GetProcessWindowStation | CloseWindowStation |  |  |  |
| 剪贴板 | 用于其它对象的临时存储空间。 | 无 | OpenClipboard | CloseClipboard |  |  |  |
| 符号链接 | 对其他对象的引用 | NtCreateSymbolicLinkObject NtOpenSymbolicLinkObject |  |  |  |  |  |
| 事件日志 |  | 无 | OpenEventLog RegisterEventSource OpenBackupEventLog | CloseEventLog |  |  |  |
| 目录下更改通知 | 若指定的目录下发生了文件名、属性等更改，则唤起本事件 |  | FindFirstChangeNotification | FindCloseChangeNotification | 没有发生指定监视类型的修改 | 发生了指定监视类型的修改 | 重置事件状态；若需要监视下一次更改，使用循环搭配 FindNextChangeNotification |
| 堆内存 |  | 无 | HeapCreate GetProcessHeap GetProcessHeaps | HeapDestroy 不应释放进程的缺省堆 |  |  |  |
| I/O 完成端口 |  | NtCreateIoCompletion NtOpenIoCompletion | CreateIoCompletionPort | CloseHandle |  |  |  |
| Mailslot |  | NtCreateMailslotFile  | CreateMailslot | CloseHandle |  |  |  |
| 内存资源通知 |  |  | CreateMemoryResourceNotification | CloseHandle |  |  |  |
| 模块 | 只有自己 LoadLibrary 加载的 DLL 才需要释放；数据类型为 HMODULE；WinMain 函数的 hInstance 参数是指向 EXE 主程序的 HMODULE（数据类型为 HINSTANCE） | 无 | LoadLibrary LoadLibraryEx GetModuleHandle GetModuleHandleEx WinMain 函数的 hInstance 参数 | FreeLibrary |  |  |  |
| 管道 | 管道可以是双工（双向传输）的；创建管道的一方称为服务端，连接到已存在或将要存在的管道的一方称为客户端 | NtCreateNamedPipeFile | CreateNamedPipe CreatePipe CreateFile | CloseHandle DisconnectNamedPipe |  |  |  |
| 套接字 | Unix 下的套接字只是普通 fd，而 Windows 下的套接字一般而言和普通（文件系统）文件不一样，推荐使用专门的套接字 API 操作；数据类型是 SOCKET（UINT_PTR） | 无 | WSASocket WSAAccept | closesocket |  |  | 与文件类似 |
| 资源更新 | 使用 UpdateResource 更新某个 PE 模块中的资源（Resource，包括字符串、图标等） | 无 | BeginUpdateResource | EndUpdateResource |  |  |  |