成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

《Undocumented Windows 2000 Secrets》翻譯 --- 第三章(4)

瀏覽:207日期:2023-08-27 11:55:30

第三章 編寫內核模式驅動程序

翻譯: Kendiv

更新: Thursday, February 10, 2005

表 3-4 列出了定義于 列表 3-8 中的函數,同時還給出了簡短的介紹。其中的一些函數的名字,如 w2kServiceStart() 和 w2kServiceControl() 和 SC 管理器的原生 API 函數 ---StartService() 和 ControlService() 比較類似。這沒有什么不一致,在這些外包函數的核心位置都能找到對這些原生函數的調用。外包函數和原生函數的主要區別在于: StartService() 和 ControlService() 的操作對象是服務句柄,而 w2kServiceOpen() 和 w2kServiceClose() 則是服務的名稱。這些名字會在內部調用 w2kServiceOpen() 和 w2kServiceClose() 轉化為對應的句柄, w2kServiceOpen() 和 w2kServiceClose() 會依次調用 OpenService() 和 CloseServiceHandle() 。

w2kServiceAdd

向系統中增加一個服務 / 驅動程序

w2kServiceClose

關閉一個服務句柄

w2kServiceConnect

連接到服務控制管理器

w2kServiceContinue

繼續執行暫停的服務 / 驅動程序

w2kServiceControl

停止、暫停、繼續、查詢或通知一個已加載的服務 / 驅動程序

w2kServiceDisconnect

斷開和服務控制管理器的連接

w2kServiceLoad

加載和啟動(可選的)一個服務 / 驅動程序

w2kServiceLoadEx

加載和啟動(可選的)一個服務 / 驅動程序(自動生成名稱)

w2kServiceManager

打開 / 關閉一個臨時的服務控制管理器句柄

w2kServiceOpen

獲取一個已加載的服務 / 驅動程序的句柄

w2kServicePause

暫停一個正在運行的服務 / 驅動程序

w2kServiceRemove

從系統中移除一個服務 / 驅動程序

w2kServiceStart

啟動一個已加載的服務 / 驅動程序

w2kServiceStop

停止一個正在運行的服務 / 驅動程序

w2kServiceUnload

停止和卸載一個服務 / 驅動程序

w2kServiceUnloadEx

停止和卸載一個服務 / 驅動程序(自動生成名稱)

表 3-4. w2k_lib.dll 提供的 SC 管理器的外包函數

表 3-4 中函數的典型用法都需遵循如下的指導方針:

l 使用 w2kServiceLoad() 或 w2kServiceLoadEx() 來加載一個服務。后一個函數會根據可執行文件的路徑和版本信息自動生成服務的顯示名稱。邏輯變量 fStart 用來確定是否在成功加載服務后自動執行該服務。在成功的情況下,該函數會為后續的調用返回一個管理器句柄。如果服務已經加載或服務已經開始運行而 fStart 為 TRUE ,調用該函數不會返回任何錯誤。但如果發生錯誤,如有必要,發生錯誤的服務會被自動卸載。

l 使用 w2kServiceUnload() 和 w2kServiceUnloadEx() 來卸載一個服務,這需要用到 w2kServiceLoad() 或 w2kServiceLoadEx() 返回的管理器句柄。 w2kServiceUnloadEx() 會根據可執行文件的路徑自動生成服務名稱。如果你已經關閉了管理器句柄,可使用 w2kServiceConnect() 來或取一個新的管理器句柄或者簡單的傳遞一個 NULL (這表示使用臨時的管理器句柄)。管理器句柄會由 w2kServiceUnload() 自動關閉。如果服務已經有刪除標志,則不會返回任何錯誤,但并不會立即刪除服務,這是因為打開的設備句柄還存在著。

l 使用 w2kServiceStart() 、 w2kServiceStop() 、 w2kServicePause() 或 w2kServiceContinue() 來控制一個服務。這些函數也需要使用 w2kServiceLoad() 或 w2kServiceLoadEx() 返回的管理器句柄。如果你提供一個值為 NULL 的管理器句柄,則使用臨時管理器句柄。如果指定的服務已處于所要求的狀態,則不會返回任何錯誤。

l 調用 w2kServiceDisconnect() 來關閉一個管理器句柄。你可以在任何時候調用 w2kServiceConnect() 來獲取一個管理器句柄。

w2kServiceLoadEx() 是一個十分強大的函數。它會構建自動加載一個服務時所需的全部參數,但你要提供可執行文件的路徑。 SC 管理器的 CreateService() 函數所需要的服務名稱將從可執行文件名(會去掉文件的擴展名)中派生出來。為了給新創建的服務構建一個適當的用于顯示名稱, w2kServiceLoadEx() 會嘗試從文件的版本信息中讀取 FileDescription 字符串。如果可執行文件中不包含版本信息,或者 FileDescription 字符串不可用,則將使用缺省的服務名稱。

和 w2kServiceLoad() 不同, w2kServiceLoadEx() 支持路徑中的環境變量。換句話說,如果路徑字符串中包含如 %SystemRoot% 或 %TEMP% 這樣的子串,它們會被相應系統變量的當前值替換掉。 w2kServiceUnloadEx() 是 w2kServiceLoadEx() 的很好的搭檔,它會從提供的路徑中提取服務的名稱,與前面提及的展開過程類似,并將提取出來的服務名稱傳遞給 w2kServiceUnload() 。這兩個函數是需要加載 / 卸載第三方設備驅動的應用程序的理想搭檔,只需提供這些驅動的全路徑即可。本書的光盤中包含一個這樣的示例程序。

控制臺模式的工具 -----w2k_load.exe 是一個通用的內核驅動程序加載 / 卸載器,它為 w2kServiceLoadEx() 和 w2kServiceUnloadEx() 提供了簡單的命令行接口。其源代碼可以在隨書 CD 的 srcw2k_load 目錄下找到。 列表 3-9 給出了相關的代碼,該工具僅是一種示意性的實現。因為大量的工作都是由 w2k_lib.dll 中的 w2kServiceLoadEx() 和 w2kServiceUnloadEx() 完成的。

// =================================================================

// GLOBAL STRINGS

// =================================================================

Word awUsage [] =

L'rn'

L'Usage: ' SW(MAIN_MODULE) L' <driver path>rn'

L' ' SW(MAIN_MODULE) L' <driver path> %srn'

L' ' SW(MAIN_MODULE) L' <driver name> %srn';

WORD awUnload [] = L'/unload';

WORD awOk [] = L'OKrn';

WORD awError [] = L'ERRORrn';

// =================================================================

// COMMAND HANDLERS

// =================================================================

BOOL WINAPI DriverLoad (PWORD pwPath)

{

SC_HANDLE hManager;

BOOL fOk = FALSE;

_printf (L'rnLoading '%s' ... ', pwPath);

if ((hManager = w2kServiceLoadEx (pwPath, TRUE)) != NULL)

{

w2kServiceDisconnect (hManager);

fOk = TRUE;

}

_printf (fOk ? awOk : awError);

return fOk;

}

// -----------------------------------------------------------------

BOOL WINAPI DriverUnload (PWORD pwPath)

{

BOOL fOk = FALSE;

_printf (L'rnUnloading '%s' ... ', pwPath);

fOk = w2kServiceUnloadEx (pwPath, NULL);

_printf (fOk ? awOk : awError);

return fOk;

}

// =================================================================

// MAIN PROGRAM

// =================================================================

DWORD Main (DWORD argc, PTBYTE *argv, PTBYTE *argp)

{

_printf (atAbout);

if (argc == 2)

{

DriverLoad (argv [1]);

}

else

{

if ((argc == 3) && (!lstrcmpi (argv [2], awUnload)))

{

DriverUnload (argv [1]);

}

else

{

_printf (awUsage, awUnload, awUnload);

}

}

return 0;

}

// =================================================================

// END OF PROGRAM

// =================================================================

列表 3-9. 加載 / 卸載設備驅動

表 3-4 中剩余的庫函數在更低一級的層面上工作,它們都在 w2k_lib.dll 內部使用。當然,如果你喜歡的話,你也可以從你的程序里調用它們。從 列表 3-8 給出的它們的源代碼中,可以很容易得出它們的使用方式。

枚舉服務和驅動

有時很有必要知道系統當前加載了那個服務或驅動,以及它們現在處于什么狀態。為了實現這一目的, SC 管理器提供了另一個名為 EnumServiceStatus() 的強大函數。該函數需要一個管理器句柄和一個類型為 ENUM_SERVICE_STATUS 的數組,該數組中將包含有關當前已加載的服務或驅動的信息。這個列表可以根據服務 / 驅動的類型和狀態來過濾。如果調用者提供的緩沖區不能一次性的容納所有項目,可反復調用該函數直到獲取所有的項目。

不過很難預先計算出所需的緩沖區大小,這是因為緩沖區必須為那些大小未知的字符串提供額外的空間,這些字符串由 ENUM_SERVICE_STATUS 的成員引用。幸運的是, EnumServiceStatus() 會返回剩余的項目所需的字節數,因此可以通過反復嘗試得出確定的緩沖區大小。 列表 3-10 給出了 SERVICE_STATUS 和 ENUM_SERVICE_STATUS 結構的定義。這些聲明位于 Win32 頭文件 WinSvc.h 中。

typedef struct _SERVICE_STATUS

{

DWORD dwServiceType;

DWORD dwCurrentState;

DWORD dwControlAccepted;

DWORD dwWin32ExitCode;

DWORD dwServiceSpecificExitCode;

DWORD dwCheckPoint;

DWORD dwWaitHint;

} SERVICE_STATUS, *LPSERVICE_STATUS;

typedef struct _ENUM_SERVICE_STATUS

{

LPTSTR lpServiceName;

LPTSTR lpDisplayName;

SERVICE_STATUS ServiceStatus;

} ENUM_SERVICE_STATUS;

列表 3-10 SERVICE_STATUS 和 ENUM_SERVICE_STATUS 結構的定義

列表 3-11 給出的 w2kServiceList() 函數是來自 w2k_lib.dll 工具庫的另一個好東東。它省略了前面提到的動作,并返回一個隨時可用的結構,該結構中包含所有請求的數據以及一對擴展結構。該函數將返回一個指向 W2K_SERVICES 結構的指針,該結構定義于 w2k_lib.h ,在 列表 3-11 的頂部給出了其定義。隨 ENUM_SERVICE_STATUS 結構數組 aess[] , W2K_SERVICES 結構體還包含四個附加成員。 dEntrIEs 表示向狀態數組中復制了多少項目, dBytes 表示返回的 W2K_SERVICES 結構的大小。 dDisplayName 和 dServiceName 被分別設置為 aess[] 中的 lpDisplayName 和 lpServiceName 字符串的最大長度。這些值將提供很大的方便,尤其是當你編寫一個控制臺模式的程序,在屏幕上輸出服務 / 驅動列表,并要求名稱列采用合適的對齊方式。

為了提供精確的系統快照, w2kServiceList() 試圖通過一次調用 EnumServiceStatus() 來獲取所有的項目。為此目的,該函數首先提供一個長度為 0 的緩沖區,這通常會導致返回 ERROR_MORE_DATA 錯誤代碼。在此種情況下, EnumServiceStatus() 將返回需要的緩沖區大小,然后按照此大小分配適當的緩沖區,然后再次調用 EnumServiceStatus() 。此時, EnumServiceStatus() 應該返回成功。不過,這存在一個很小的概率事件 --- 在兩次調用 EnumServiceStatus() 之間另一個項目可能會被增加到列表中。因此,將會在一個循環中重復這一過程直到所有的一切都正確或者一個非 ERROR_MORE_DATA 的錯誤返回。

// -----------------------------------------------------------------

typedef struct _W2K_SERVICES

{

DWORD dEntries; // number of entries in aess[]

DWORD dBytes; // overall number of bytes

DWORD dDisplayName; // maximum display name length

DWORD dServiceName; // maximum service name length

ENUM_SERVICE_STATUS aess []; // service/driver status array

}

W2K_SERVICES, *PW2K_SERVICES, **PPW2K_SERVICES;

#define W2K_SERVICES_ sizeof (W2K_SERVICES)

#define W2K_SERVICES__(_n)

(W2K_SERVICES_ + ((_n) * ENUM_SERVICE_STATUS_))

// -----------------------------------------------------------------

PW2K_SERVICES WINAPI w2kServiceList (BOOL fDriver,

BOOL fWin32,

BOOL fActive,

BOOL fInactive)

{

SC_HANDLE hManager;

DWORD dType, dState, dBytes, dResume, dName, i;

PW2K_SERVICES pws = NULL;

if ((pws = w2kMemoryCreate (W2K_SERVICES_)) != NULL)

{

pws->dEntries = 0;

pws->dBytes = 0;

pws->dDisplayName = 0;

pws->dServiceName = 0;

if ((fDriver || fWin32) && (fActive || fInactive))

{

if ((hManager = w2kServiceConnect ()) != NULL)

{

dType = (fDriver ? SERVICE_DRIVER : 0) |

(fWin32 ? SERVICE_WIN32 : 0);

dState = (fActive && fInactive

? SERVICE_STATE_ALL

: (fActive

? SERVICE_ACTIVE

: SERVICE_INACTIVE));

dBytes = pws->dBytes;

while (pws != NULL)

{

pws->dEntries = 0;

pws->dBytes = dBytes;

pws->dDisplayName = 0;

pws->dServiceName = 0;

dResume = 0;

if (EnumServicesStatus (hManager, dType, dState,

pws->aess, pws->dBytes,

&dBytes, &pws->dEntries,

&dResume))

break;

dBytes += pws->dBytes;

pws = w2kMemoryDestroy (pws);

if (GetLastError () != ERROR_MORE_DATA) break;

pws = w2kMemoryCreate (W2K_SERVICES_ + dBytes);

}

w2kServiceDisconnect (hManager);

}

else

{

pws = w2kMemoryDestroy (pws);

}

}

if (pws != NULL)

{

for (i = 0; i < pws->dEntries; i++)

{

dName = lstrlen (pws->aess [i].lpDisplayName);

pws->dDisplayName = max (pws->dDisplayName, dName);

dName = lstrlen (pws->aess [i].lpServiceName);

pws->dServiceName = max (pws->dServiceName, dName);

}

}

}

return pws;

}

列表 3-11. 枚舉服務 / 驅動程序

w2kServiceList() 需要四個邏輯類型的參數,以確定要返回的列表的內容。通過 fDriver 和 fWin32 參數,你可以分別選擇是否包含驅動程序或服務。如果這兩個參數都為 TRUE ,那么返回的列表將同時包含驅動和服務。 fActive 和 fInactive 標志用于控制加于列表上的狀態過濾器。。 fInactive 參數選擇剩余的模塊,也就是說,這些模塊已經加載但已經停止運行。如果所有的四個參數都為 FALSE ,函數返回的 W2K_SERVICES 結構將包含一個空的狀態數組。光盤中的示例代碼包含一個簡單的服務 / 驅動瀏覽器,它被設計為 Win32 控制臺模式,并依賴于 w2k_lib.dll 中的 w2kServiceList() 。它使用 W2K_SERVICES 結構(參見 列表 3-11 )中的 dDisplayName 和 dServiceName 成員來為所有的名稱選擇合適的水平對齊方式。你可以在光盤的 srcw2k_svc 目錄下找到此工具的源代碼。其可執行文件對應光盤中的 binw2k_svc.exe 。 示列 3-4 列出了在我的機器上運行該工具,列出的所有活動的內核驅動程序(使用命令選項 /drivers /active )。

在下一章中,我們將開始開發一個可實際工作的內核驅動程序,它會偵測內核使用的內存,并且會 Crack 基本的內存管理數據結構。這個工程將伴隨你閱讀第 4 、 5 和 6 章,在每一章中,該驅動程序都會被加強。最后將得到一個通用的 Windows 2000 Kernel Spy 。

標簽: Windows系統
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
亚洲自拍偷拍图区| 国产欧美日韩精品在线| 欧美精品电影在线播放| 亚洲欧美另类小说视频| 丁香婷婷综合色啪| 久久国产日韩欧美| 中文字幕一区二区视频| 成人免费视频一区| 久久青青草综合| 自拍av一区二区三区| 97se亚洲国产综合在线| 欧美日韩一级黄| 亚洲成人免费电影| 亚洲一本视频| 国产亚洲综合色| 成人毛片视频在线观看| 欧美日韩在线直播| 午夜视频在线观看一区| 亚洲一二三区精品| 久久影院视频免费| 国产福利一区二区三区视频在线| 先锋a资源在线看亚洲| 国产精品久久久久久久午夜片| 欧美日韩视频一区二区三区| 欧美大片在线观看| 韩国v欧美v日本v亚洲v| 91传媒视频在线播放| 亚洲成人tv网| 国产模特精品视频久久久久| 中文字幕日本乱码精品影院| 欧美一区激情| 久久综合久久综合九色| 成人福利在线看| 日韩亚洲欧美在线| 国产激情视频一区二区在线观看| 欧美日韩在线直播| 精品一区二区综合| 欧美自拍丝袜亚洲| 亚洲成人免费观看| 国产伦精品一区二区三| 亚洲综合一二区| 亚洲五月婷婷| 中文字幕一区二区三区不卡| 成人av在线资源网站| 精品女同一区二区| 91在线视频播放| 91女厕偷拍女厕偷拍高清| 2022国产精品视频| 99re亚洲国产精品| 国产欧美精品一区| 在线日韩av永久免费观看| 亚洲欧美影音先锋| 99在线热播精品免费99热| 色婷婷av一区二区三区之一色屋| 调教+趴+乳夹+国产+精品| 色综合久久久久| 精品综合久久久久久8888| 91精品国产综合久久福利| 成人黄色片在线观看| 久久综合九色综合欧美就去吻| 一区二区三区日韩精品视频| 欧美中文字幕| 亚洲午夜久久久久| 久久一区中文字幕| 精品在线一区二区三区| 欧美一区二区三区在线| www.激情成人| 久久精品夜色噜噜亚洲aⅴ| 成人国产精品免费观看视频| 久久久精品欧美丰满| 久久天堂av综合合色蜜桃网| 欧美三区不卡| 亚洲色欲色欲www在线观看| 亚洲一区二区动漫| 青青草97国产精品免费观看| 欧美久久久久免费| youjizz久久| 中文在线资源观看网站视频免费不卡| 亚洲激情欧美| 日韩和欧美一区二区三区| 精品少妇一区二区三区免费观看| 黄色亚洲免费| 蜜臀av亚洲一区中文字幕| 欧美一区二区三区性视频| 欧美色图首页| 日本亚洲一区二区| 久久久久久久久99精品| 国产亚洲午夜| 国产91在线|亚洲| 亚洲人成网站色在线观看| 91久久免费观看| 91一区二区三区在线播放| 亚洲一区自拍偷拍| 日韩一级成人av| 亚洲国产91| 国产麻豆视频一区二区| 国产精品久99| 欧美日韩国产大片| 欧美日韩一区二| 首页亚洲欧美制服丝腿| 亚洲精品一区二区三区福利| 极品中文字幕一区| 美脚の诱脚舐め脚责91| 国产亚洲一本大道中文在线| 欧美日韩一区二区高清| 午夜精品在线看| 欧美精品一二三| 亚洲一区二区不卡免费| 欧美猛男男办公室激情| 午夜精品一区二区三区四区| 一区二区三区中文免费| 欧美日韩国产美| 欧美日本亚洲韩国国产| 一区二区成人在线观看| 欧美日韩亚洲另类| 伊人久久综合| 精彩视频一区二区三区| 国产色婷婷亚洲99精品小说| 欧美亚洲色图校园春色| 国产激情一区二区三区四区| 国产精品福利av| 色欲综合视频天天天| 欧美精品18| 日韩va欧美va亚洲va久久| 欧美精品一区男女天堂| 国产精品毛片在线看| 国产一区二区精品久久| 久久精品欧美一区二区三区不卡 | 欧美久久在线| 午夜激情久久久| 精品剧情v国产在线观看在线| 激情综合视频| av资源网一区| 午夜一区二区三区视频| 精品久久国产老人久久综合| 国产亚洲精品v| 麻豆成人久久精品二区三区小说| 国产精品久久久久aaaa| 欧美图片一区二区三区| 国产精品v欧美精品v日韩| 免费看欧美美女黄的网站| 国产人伦精品一区二区| 色婷婷亚洲精品| 欧美福利网址| 国产福利一区在线观看| 亚洲一区免费视频| 精品福利一区二区三区免费视频| 久久久久国内| 欧美日韩综合精品| 激情五月婷婷综合网| 国产三级精品三级在线专区| 日韩午夜激情视频| 性伦欧美刺激片在线观看| 亚洲少妇30p| 精品国产乱码久久久久久久久| 国产日韩一区| 99久久精品免费看| 欧美aaaaaa午夜精品| 中文字幕在线一区| 日韩欧美一级精品久久| 一区二区三区在线观看网站| 精品国一区二区三区| 91精彩视频在线观看| 一区二区三区成人精品| 99精品1区2区| 韩日精品视频一区| 亚洲最快最全在线视频| 中文字幕一区三区| 欧美大片在线观看| 欧美日韩一区二区三区在线| 欧美日韩久久| 风间由美中文字幕在线看视频国产欧美 | 99热精品国产| 欧美三日本三级三级在线播放| 一本一道久久综合狠狠老精东影业| 成人毛片视频在线观看| 蜜桃av一区二区三区电影| 亚洲美女视频在线观看| 天天操天天干天天综合网| 成人免费在线观看入口| 精品久久99ma| 欧美一区二区三区电影| 美女精品在线| 激情欧美丁香| 亚洲无线视频| 色综合欧美在线视频区| 粉嫩aⅴ一区二区三区四区| 久久精品国产99久久6| 亚洲国产日产av| 综合激情网...| www久久精品| 国产欧美中文在线| 日韩视频123| 欧美一区二区三区四区在线观看| 色噜噜夜夜夜综合网| 1024亚洲| 亚洲国产免费| 亚洲激情综合| 伊人久久av导航| 国语精品中文字幕|