Windows定義了很多核心對象:程序對象、線程對象、互斥量對象、信号量對象、事件對象、檔案對象等等。在調用相應的函數建立這些對象後,我們都可以通過HANDLE類型的句柄來引用它們。
句柄必須通過句柄表才能找到所引用的核心對象。
Microsoft并未就句柄表釋出過任何官方的文檔。
通過windows公布的WRK(windows research kernel)源代碼,可以了解windows句柄表。雖然是基于WRK的,不能保證其他版本的windows系統也采用相同的機制,但是或許都是大同小異的。
windows使用句柄對程序中的各種對象進行引用。實際上windows句柄就是一個索引,它存儲了關聯對象在句柄表的索引值,每個索引對應句柄表中的一個表項。通過句柄存儲的索引,就可以很容易獲得該句柄項對應的對象的指針。
句柄表中存儲了很多了句柄表項;
句柄表是針對于程序而言的,在一個程序使用的句柄,直接在另一個程序中使用是毫無意義的。
在windows Server 2003(與WRK有相同的核心)中,句柄表是一個多層次的結構。
它的類型為:HANDLE_TABLE。定義如下:
typedef struct _HANDLE_TABLE {
ULONG_PTR TableCode;//指針指向句柄表的存儲結構。
struct _EPROCESS *QuotaProcess; // 所屬程序的指針
HANDLE UniqueProcessId; // 這個程序的 ProcessID
EX_PUSH_LOCK HandleTableLock[HANDLE_TABLE_LOCKS];//句柄表所,僅在句柄表擴充時使用。
LIST_ENTRY HandleTableList; // 所有的 HandleTAble 在核心中形成一個 List ,這是 Entry
EX_PUSH_LOCK hangleConventionEvent//若在通路句柄表時發生了競争則在此鎖上等待。
PHANDLE_TRACE_DEBUG_INFO DebugInfo;
LONG extrainfoPag;
ULONG FirstFree; // 空閑連結清單表頭句柄索引。
ULONG LastFree; // 最近被釋放的句柄索引。
ULONG NextHandleNeedingPool;//下一次句柄表擴充的起始句柄索引。
LONG HandleCount;//正在使用的句柄表項數量。
union{
ULONG Flags;//标志域
BOOLEAN StrictFIFO:1;//是否使用FIFO風格的重用。
};
} HANDLE_TABLE, *PHANDLE_TABLE;
句柄表項,它是HANDLE_TABLE_ENTRY結構,定義如下:
typedef struct _HANDLE_TABLE_ENTRY
{
union {
PVOID Object;//核心對象指針。
ULONG ObAttributes;//核心對象屬性。
PHANDLE_TABLE_ENTRY_INFO InfoTable;//
ULONG_PTR Value;
};
union {
union {
ACCESS_MASK GrantedAccess;
struct{
USHORT GrantedAccessIndex;
USHORT CreatorBackTraceIndex;
};
};
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
window提供的API:GetCurrentThread和GetCurrentProcess,可以傳回目前線程和程序的句柄。其實在句柄表中是沒有存儲目前程序的句柄和目前線程句柄。GetCurrentThread傳回句柄的值是-2,當我們以此句柄作為參數傳遞給windows其他API函數時,在函數内部如果檢測到該句柄值為-2,不會查找句柄表,立即傳回到線程對象位址。類似的調用GetCurrentProcess時,其實傳回的是-1,當使用此程序句柄時,同樣不需要查找句柄表,會立即傳回指向目前程序對象的指針。