2014-01-30 43 views
5

我意識到無法通過任何類型的Win API調用來確定在任何給定時間線程隊列中有多少消息。我有一個應用程序不起作用,因爲PostMessage有時會失敗(可能是由於隊列增長到10000,儘管我不明白它會如何變大)。這是一個間歇性的問題,我正好在發生時發生了幾次內存轉儲。 顯然,隊列在某處而本文將闡述如何得到它http://moyix.blogspot.com/2008_09_01_archive.html從內存轉儲中查找線程消息隊列中的消息數

在Windows中的每個線程(由_ETHREAD strucutre代表)在其線程控制塊(或Tcb的,這是一個 場_KTHREAD)叫做 Win32Thread。此字段指向一個數據結構_W32THREAD,其中 在Windows圖形 子系統的內核模式部分win32k.sys中定義。您可以通過在WinDbg中發佈「dt win32k!_W32THREAD」來檢查_W32THREAD 結構;但是,如果你 開始逆向工程win32k.sys,你很快就會發現這裏給出的信息還遠遠沒有完成。實際上,_W32THREAD是一個大得多的數據結構,其中包括有關當前桌面,鍵盤佈局,已安裝窗口掛鉤的信息以及對我們而言最重要的輸入消息隊列的信息。在Windows XP SP2中, 消息隊列在_W32THREAD偏移0xD0發現,看起來像:

typedef struct _MSG_QUEUE { PMSG_QUEUE_ENTRY Head; 
PMSG_QUEUE_ENTRY Tail; unsigned long NumberOfMessages; } MSG_QUEUE; 

基本上我試圖找到一個指針MSG_QUEUE(這會給我NumberOfMessages,再加上我可以從頭開始列舉它們)。然而,它不看我可以通過分析內存轉儲找到指向_ETHREAD,_KTHREAD和_W32THREAD的任何指針。他們在哪裏存儲,他們在進程內存空間?我必須在內核模式下運行嗎?我是否需要爲win32k.sys加載符號?還有什麼我需要做的?謝謝。

+0

只是好奇:什麼時候PostMessage失敗時說GetLastError()? – manuell

+0

通常是ERROR_NOT_ENOUGH_QUOTA,但是在最新的報告中沒有錯誤(它可能是0x12,可能來自某些其他早期錯誤) –

+2

KTHREAD和相關結構處於內核模式,但內存轉儲只捕獲用戶模式。所以信息不在轉儲文件中。 –

回答

1

這不是所有WinDbg命令的完整答案,但可能仍然有幫助。

消息隊列只能在內核模式下訪問,所以需要內核轉儲或使用SysInternals livekd。 使用-y開關設置符號路徑。

livekd -y srv*d:\debug\symbols*http://msdl.microsoft.com/download/symbols 

一旦你在內核模式下,找到你想調試

!process 0 0 executable.exe 

然後得到進程的線程

!process <process> 4 

具有Win32Thread不等於所有線程的過程0可能有趣。

博客文章Jumping the queues描述了Windows 7的其餘部分。 我無法立即關注,文章實際上並未描述要使用哪些WinDbg命令。我記得在Windows XP上它更容易。