聊完了CreateFile的調用過程,我們再來看一看三個非常重要的API函數DeviceIoControl、ReadFile、WriteFile:
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice,
_In_ DWORD dwIoControlCode,
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped);
hDevice—通過CreateFile打開的裝置句柄
dwIoControlCode—應用程式調用驅動程式的控制指令
lpInBuffer—應用程式傳遞到驅動程式資料的緩沖區位址
nInBufferSize—緩沖區長度
nOutBuffer—驅動程式傳回資料到應用程式的緩沖區位址
nOutBufferSize—緩沖區長度
lpBytesReturned—驅動程式實際傳回的資料長度
lpOverlapped—重疊結構,異步調用函數時使用
DeviceIoControl的調用過程比較簡單,API通過系統調用進入核心,核心中兩次調用ObReferenceObjectByHandle,一次為了擷取句柄對應的裝置對象(實際上是檔案對象),另一次是為了擷取Event句柄對應的事件對象,該對象用于處理使用者模式下的同步問題;順着裝置對象的堆疊往上爬,獲得了頂層裝置對象,之後就準備了一個IRP,通過IoCallDriver調用了驅動程式中的OnMajorDeviceIoControl函數,這些函數前一章已經分析過,了解起來應該不成問題。
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
hFile—通過CreateFile打開的裝置句柄
lpBuffer—應用程式傳遞到驅動程式資料的緩沖區位址
nNumberOfBytesToWrite—緩沖區長度
lpNumberOfBytesWriten—實際寫操作的長度
lpOverlapped—重疊結構,異步調用函數時使用
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
hFile—通過CreateFile打開的裝置句柄
lpBuffer—驅動程式傳回資料到應用程式的緩沖區位址
nNumberOfBytesToRead—緩沖區長度
lpNumberOfBytesRead—驅動程式實際傳回的資料長度
lpOverlapped—重疊結構,異步調用函數時使用
從上面的函數調用圖可以看出:
1, WriteFile、ReadFile、DeviceIoControl三個函數異曲同工,走的路線很相近
2, 在windows核心層,WriteFile生成一個MajorFunction為IRP_MJ_WRITE的IRP
ReadFile生成一個MajorFunction為IRP_MJ_READ的IRP
DeviceIoControl生成一個MajorFunction為IRP_MJ_DEVICE_CONTROL的IRP
3, 在windows核心層,WriteFile函數生成的IO_STACK_LOCATION消息參數聯合體需要轉換成Write結構體
ReadFile函數生成的IO_STACK_LOCATION消息參數聯合體需要轉換成Read結構體
DeviceIoControl函數生成的IO_STACK_LOCATION消息參數聯合體需要轉換成DeviceIoControl結構體
4, 隻要驅動支援,WriteFile,ReadFile完全可以由DeviceIoControl替代
參考資料:
1, <<Windows核心情景分析>>