天天看點

windows核心句柄表學習

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,當使用此程序句柄時,同樣不需要查找句柄表,會立即傳回指向目前程序對象的指針。