標籤:reference 組成 rom mod hwnd microsoft ring 為什麼 查詢
今天特別困啊,這是為什嗎?!!剛剛把第一章看了一下,困到不行,所以寫blog清醒一下。
第一章標題是“錯誤處理”,看了之後嚇了一跳,難道第一章就講這麼高大上的東西?!不是不是,我現在的理解是,這章主要還是帶我們感受一下以後遇到問題如何知道這個問題的描述。
我們在使用函數後,總會有一個結果:失敗也好,成功也好。而這個結果,最終還是要以標識的形式落在地上的,章節內主要講的是返回LONG/DWORD類型的情況。每個函數最後會返回一個錯誤碼給調用線程。
想要看返回的是啥,這裡提供了一種方法:DWORD GetLastError();
在windows裡面,有一個檔案(WinError.h)存放了錯誤碼列表,這個檔案很大,只取一個元素出來參考一下就好了。
//// MessageId: ERROR_SUCCESS//// MessageText://// The operation completed successfully.//#define ERROR_SUCCESS 0L
每個錯誤由三個元素組成:
一個錯誤Id,也就是上面的MessageId所標識的,也是宏;
一個是錯誤描述,也就是MessageText所標識的;
一個是編號。
建議使用Id而不是編號。
然後有一段話沒看明白:一些Windows函數調用成功可能是緣於不同的原因。例如,建立一個具名事件核心對象時,以下兩種情況均會成功:對象實際完成建立,或者存在一個同名的事件核心對象。應用程式也許需要知道成功的原因。為返回這種資訊,Microsoft選擇採用"上一個錯誤碼"(last error code)機制。所以,特定函數調用成功時,可以調用GetLastError來確定額外的資訊。對於具有這種行為的函數,Platform SDK文檔會清楚指明能以這種方式調用GetLastError。文檔中提供了CreateEvent函數的一個例子;如果已經存在具名事件,就返回ERROR_ALREADY_EXISTS。(以後懂了再回頭看吧)
我們可以通過調試視窗來查看上一個錯誤碼以及文本描述,我試了一下,的確可以的。
還有vs內建的小工具,error look up:
下面就來看一下獲得文本描述的關鍵函數:
12345678 |
DWORD FormatMessage( DWORD dwFlags, LPCVOID pSource, DWORD dwMessageId, DWORD dwLanguageId, PTSTR pszBuffer, DWORD nSize, va_list *Arguments); |
FormatMessage可以支援多種語言,比如英語,漢語等,上面的例子中我們就看到了,返回的是漢語。
除了WinError.h中的代碼,我們可以自訂錯誤碼返回:VOID SetLastError(DWORD dwErrCode);
書中還給了我們一個例子:
思路是擷取使用者輸入的錯誤碼,然後擷取系統語言(中文,英文),然後利用FormatMessage將查詢結果返回。
1234567891011121314151617181920212223242526272829303132333435363738394041 |
case IDOK: // Get the error code DWORD dwError = GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE); HLOCAL hlocal = NULL; // Buffer that gets the error message string // Use the default system locale since we look for Windows messages. // Note: this MAKELANGID combination has 0 as value DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); // Get the error code‘s textual description BOOL fOk = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwError, systemLocale, ( PTSTR ) &hlocal, 0, NULL); if (!fOk) { // Is it a network-related error? HMODULE hDll = LoadLibraryEx(TEXT( "netmsg.dll" ), NULL, DONT_RESOLVE_DLL_REFERENCES); if (hDll != NULL) { fOk = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwError, systemLocale, ( PTSTR ) &hlocal, 0, NULL); FreeLibrary(hDll); } } if (fOk && (hlocal != NULL)) { SetDlgItemText(hwnd, IDC_ERRORTEXT, ( PCTSTR ) LocalLock(hlocal)); LocalFree(hlocal); } else { SetDlgItemText(hwnd, IDC_ERRORTEXT, TEXT( "No text found for this error number." )); } break ; |
dwError變數記錄的就是錯誤碼;
hlocal是記錄描述字串的;
systemLocale是指出要用什麼語言來顯示文本描述,根據兩個特定的常量(即LANG_NEUTRAL和SUBLANG_NEUTRAL)來產生語言識別項,這兩個常量聯合到一起將產生一個0值--即作業系統的預設語言;
下面就來看FormatMessage中傳遞的參數吧:
FORMAT_MESSAGE_FROM_SYSTEM:我們希望獲得與一個系統定義的錯誤碼對應的字串,
FORMAT_MESSAGE_ALLOCATE_BUFFER:要求該函數分配一塊足以容納錯誤文本描述的記憶體。此塊記憶體的控制代碼將在hlocal變數中返回,
FORMAT_MESSAGE_IGNORE_INSERTS:允許我們獲得含有%預留位置的訊息。這些預留位置將被Windows用來提供更多上下文相關資訊;
第三個參數指出想要尋找的錯誤碼;
第四個參數指出要用什麼語言來顯示文本描述;
fOK記錄是否查詢成功,如果查詢失敗,則判斷該錯誤是否與網路有關(這裡暫時也不懂),否則就可以輸出了。
總結
通過這一章大概瞭解如何自訂錯誤碼,以及如何通過錯誤碼擷取錯誤描述。請選中你要儲存的內容,粘貼到此文字框
Windows核心編程讀書筆記1