久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

WDM驅動程序開發(fā)之驅動框架篇:KDriver類

 wfsy1983 2011-06-03
一,、Overview
    KDriver類提供了一個設備驅動程序的框架。這個類的職責包括初始化驅動程序,,把I/O請求傳遞給它們的目標設備對象,。
    KDriver是一個抽象類,驅動編寫人員必須寫一個新的類來繼承它,。新的子類必須重寫DriverEntry函數(shù),,這是當系統(tǒng)載入驅動程序時框架要調用的函數(shù)。這個派生類會有一個構造函數(shù),,但是構造函數(shù)不允許有參數(shù),。一般來說,,最好不要寫這么一個構造函數(shù)。把一切的初始化工作放在DriverEntry函數(shù)里來進行,。對于任何給定的驅動,,只能有一個KDriver類的實例存在,而且這個實例是框架自動創(chuàng)建的,。任何調用者可以通過調用DriverInstance靜態(tài)函數(shù)來獲得一個指向這個唯一實例的指針,。
    驅動編寫人員必須做的另一件事情是通知框架:哪個類作為驅動框架來提供服務??蚣芴峁┝硕x了一個宏定義DECLARE_DRIVER_CLASS來實現(xiàn)這個事情,。任何一個驅動程序里都必須調用一次且只能調用一次這個宏,一般是在擁有DriverEntry函數(shù)的組件里,。這個宏必須放在任何函數(shù)之外,,因為它事實上聲明一個可以被框架調用的函數(shù)。宏的參數(shù)應該是繼承了KDriver類的那個類的名字,。
    除了DriverEntry,,KDriver還有其他兩個成員函數(shù)來做初始化的工作:RequestReinitialization() 和 Reinitialize()。一個驅動程序在DriverEntry函數(shù)里調用RequestReinitialization()函數(shù)來指示系統(tǒng)調用 Reinitialize()函數(shù),,作為第二級初始化,。而Reinitialize()函數(shù)是一個可被重寫的虛函數(shù),。
    如果想要系統(tǒng)具有卸載(Unload)驅動的功能,,就要在function.h文件里做一個聲明:#define DRIVER_FUNCTION_UNLOAD。這是虛函數(shù)Unload()的得到聲明,。這個函數(shù)在基類中的實現(xiàn)代碼調用了DeleteDevices() 函數(shù)來為這個驅動程序創(chuàng)建的每個設備調用析構函數(shù),。
    其他成員函數(shù)對驅動程序創(chuàng)建的設備進行管理。GetDeviceListHead()函數(shù)取得驅動創(chuàng)建的一系列設備對象中的第一個(head),。DeleteDevices()遍歷列表,,并為每一個設備對象調用析構函數(shù)。IsDevicePresent()使驅動程序確認設備是否已經(jīng)被刪除,。
    盡管通常情況下框架會將I/O請求直接派遣給目標設備對象,,KDriver還是保留了一個特性:可以派生一個成員函數(shù)在I/O請求被派遣給設備對象之前對它進行檢測或預處理。這個特性通過調用EnableDispatchFilter()函數(shù)來啟用,這會使所有的I/O請求被重寫的DispatchFilter()函數(shù)處理后再派遣,。另外,,要啟用這個特性,還必須在function.h文件中聲明:#define DRIVER_FUNCTION_DISPATCH_FILTERING,。
    總結:不要在KDriver的子類中定義構造函數(shù)和析構函數(shù),,把初始化工作放在DriverEntry函數(shù)里,清理工作放在Unload函數(shù)里,。
   
二,、Member Functions
   
1,、DriverEntry (Initializes the driver)
    框架自動調用這個函數(shù)進行初始化工作,所有繼承KDriver的子類必須重寫這個函數(shù),。
【函數(shù)原型】
    NTSTATUS DriverEntry( PUNICODE_STRING RegistryPath );
【Parameters】
    RegistryPath      系統(tǒng)儲存驅動信息的注冊表路徑
【Returns】
    返回值用來說明驅動的初始化工作是否成功,。除了STATUS_SUCCESS之外的返回值將阻止系統(tǒng)加載這個驅動程序。如果這個函數(shù)里調用了
RequestReinitialization函數(shù),,那么不太可能返回一個STATUS_SUCCESS之外的值,。
【Comments】
    DriverEntry的職責使初始化驅動程序。具體工作有三點:(1)從注冊表中提取參數(shù)(2)保告和分配資源的使用(3)創(chuàng)建設備對象,。如果可能的話,,系統(tǒng)會把驅動的參數(shù)儲存在注冊表中相應的驅動目錄下的Parameters鍵里。KRegistryKey類封裝了操作注冊表的方法,。
    資源使用情況報告有助于沖突檢測,。在兩個驅動同時要求分配資源時,這個報告將會成為系統(tǒng)有限給哪個驅動分配資源的一個依據(jù),。關于更多的報告和分配資源的細節(jié),,可以參看KResourceRequest和KResourceAssignment類中的描述。
    這個函數(shù)在PASSIVE_LEVEL級別上運行,。
2,、AddDevice (Plug and Play entry point called to configure new device object (WDM only))
    當即插即用子系統(tǒng)檢測倒該驅動對應的設備時,框架會自用調用這個函數(shù),。
    前提是必須在function.h文件里聲明#define DRIVER_FUNCTION_ADD_DEVICE
【函數(shù)原型】
    NTSTATUS AddDevice( PDEVICE_OBJECT PnPDeviceObject );
【Parameters】
    PnPDeviceObject   一個指向系統(tǒng)創(chuàng)建的設備對象的指針,,來表示檢測到的設備。
【Returns】
    成功就返回TRUE,。
【Comments】
    這個函數(shù)里進行什么操作依賴于驅動的類型,。迷你驅動(minidriver)由于在類驅動(class driver)或總線驅動(bus driver)的上層,一般會創(chuàng)建一個設備對象并把它壓到設備堆棧里,,這個堆棧是物理設備所屬的總線所擁有的,。
    對大多數(shù)驅動,參數(shù)PnPDeviceObject代表物理設備對象(PDO),。PDO是物理設備在在操作系統(tǒng)中的設備表現(xiàn)形式,。系統(tǒng)用對象來模仿對設備的即插即用操作,比如使設備開始(starting),、停止(stopping),、把設備刪除(removing)、減低電源消耗(powering down),。
    AddDevice經(jīng)常創(chuàng)建一個新的設備對象叫做功能設備對象(FDO),。FDO的目的是使應用程序和更高級別上的驅動程序能夠通過PDO控制設備。PDO是物理設備在驅動程序里的表現(xiàn)形式,。因此,,對于同樣的物理設備有兩種設備對象來表示:PDO是為了系統(tǒng)的使用,,F(xiàn)DO是為了驅動的使用。
    為了創(chuàng)建FDO,,驅動要創(chuàng)建一個KPnpDevice類的派生類的實例,。KPnpDevice類和KDevice類很相似,但是增加了更強大的處理IRP_MJ_PNP和IRP_MJ_POWER這兩種IRP的功能,。
    為了建立一個PDO和FDO之間的聯(lián)系,,AddDevice還經(jīng)常要創(chuàng)建一個KPnpLowerDevice類的實例,或者它的派生類的實例,。這個實例的創(chuàng)建將FDO連接到PDO,,或者連接到最后一個設備,而這個設備連接到了PDO,。然后驅動就可以處理發(fā)給PDO的IRP,。在表示FDO的類的實例中嵌入一個KPnpLowerDevice類或者它的子類的實例,是一個不錯的選擇,。
對于有些類型的迷你驅動,,比如說HID(人機交互設備),這個參數(shù)代表的就是FDO而不是PDO。這是因為類驅動在迷你驅動上設置了鉤子(hooks),鉤住了迷你驅動的AddDevice入口并創(chuàng)建了FDO,。詳細請看KPnpLowerDevice類,。
3、Unload (Clean up)
    當系統(tǒng)卸載驅動時框架自動調用這個函數(shù)
    前提是必須在function.h文件中聲明 #define DRIVER_FUNCTION_UNLOAD
【函數(shù)原型】
    VOID Unload( void );
【Comments】
    這是一個虛函數(shù),。它在基類中的實現(xiàn)代碼中調用了DeleteDevices()函數(shù),。
    在function.h文件中聲明 DRIVER_FUNCTION_UNLOAD 使系統(tǒng)可以卸載驅動。但并不強制重寫這個函數(shù),,因為它不是一個純虛函數(shù),。換句話說,如果你定義了DRIVER_FUNCTION_UNLOAD而不重寫函數(shù),,也可以得到默認的卸載行為(刪除設備)。但是如果你有其他的需要,,就要重寫這個函數(shù),。如果重寫了這個函數(shù),它應該調用子類的函數(shù)或者自己調用DeleteDevices()函數(shù),。
    Unload函數(shù)應該負責釋放驅動程序中申請的所有對象占用的內存,。
    如果驅動在初始化時通過 KResourceRequest 請求了資源,那么在Unload函數(shù)里應該釋放資源,,細節(jié)參看ReleaseResources()函數(shù),。
    總之,Unload要確保在卸載驅動時釋放所有的系統(tǒng)對象(包括內存)和未處理的事件(它們會使系統(tǒng)調用驅動程序),。最好的做法是析構頂級對象,,而不是析構它們包含的子級對象,。
    這個函數(shù)運行在PASSIVE_LEVEL級別上。
4,、Reinitialize (Secondary initialization operations)
    框架調用這個函數(shù)作為先前調用RequestReinitialization函數(shù)的回復,。Reinitialize函數(shù)給當前驅動提供了一個在系統(tǒng)其他驅動都初始化完畢之后再進行二次初始化的機會。
    前提是必須在function.h文件中聲明#define DRIVER_FUNCTION_REINITIALIZATION,。
【函數(shù)原型】
VOID Reinitialize(
   PVOID Context,
   ULONG Count
);
【Parameters】
    Context     是傳給RequestReinitialization函數(shù)的參數(shù),。
    Count       指這個函數(shù)調用的次序號,系統(tǒng)每調用一次這個函數(shù)就會給傳進來的這個參數(shù)加1,。
【Comments】
    這是一個純虛函數(shù)(pure virtual function),,在繼承KDriver的子類里必須提供這個函數(shù)。
    需要前后兩次初始化的驅動程序把這個函數(shù)安排在DriverEntry()函數(shù)中調用了RequestReinitialization函數(shù)以后執(zhí)行,。Context參數(shù)是調用RequestReinitialization函數(shù)時提供的參數(shù)傳遞過來的,。
    這個例程可以通過成員變量m_RegistryPath來控制注冊表路徑。
    這個例程可以在必須進行額外的初始化時調用RequestReinitialization函數(shù),。
    這個函數(shù)運行在PASSIVE_LEVEL級別上,。
5、RequestReinitialization (Request secondary initialization)
    這個函數(shù)的作用是:在系統(tǒng)其他驅動都初始化完畢后,,使當前驅動可以執(zhí)行一些額外的初始化代碼,。
    前提是必須在function.h文件中聲明#define DRIVER_FUNCTION_REINITIALIZATION。
【函數(shù)原型】
    VOID RequestReinitialization( PVOID Context );
【Parameters】
    Context       任意類型的參數(shù),,最終是要傳遞給Reinitialize函數(shù)處理的,,默認是NULL。
【Comments】
    一些其行為依賴于其他驅動的驅動程序,,必須有能力在其他程序初始化之前和之后兩次進行初始化,。如果驅動有這樣的需求,它可以在DriverEntry里進行一部分初始化,,然后把另一部分初始化工作安排在后來調用的代碼中,。RequestReinitialization的調用使框架在所有驅動都執(zhí)行完它們的DriverEntry函數(shù)后調用Reinitialize()函數(shù)。
    這個函數(shù)需要在DriverEntry函數(shù)里調用,。調用這個函數(shù)的話,,DriverEntry必須返回STATUS_SUCCESS。如果還有額外的初始化操作,,這個函數(shù)還有可能被Reinitialize函數(shù)調用,。
    這個函數(shù)只能運行在PASSIVE_LEVEL級別上。
    支撐它的系統(tǒng)服務是IoRegisterDriverReinitialization,。
6,、DisableUnload (Disable unloading of this driver)
    這個函數(shù)將驅動對象的Unload例程的地址設為NULL。
    前提是在function.h文件中聲明#define DRIVER_FUNCTION_UNLOAD 。
【函數(shù)原型】
    VOID DisableUnload( void );
【Comments】
    調用這個函數(shù)是為了阻止驅動被卸載,。如果當前的設備狀態(tài)下,,當前驅動程序不能夠被完美的卸載掉,那么調用這個函數(shù)是有用的,。驅動只能等到隨后調用了EnableUnload()函數(shù)后才可以被卸載,。
7、EnableUnload (Enable unloading of this driver)
    這個函數(shù)把Unload例程的地址寫回系統(tǒng)驅動對象,。
    前提是在function.h文件中聲明#define DRIVER_FUNCTION_UNLOAD ,。
【函數(shù)原型】
    VOID EnableUnload( void );
【Comments】
    在調用DisableUnload函數(shù)之后,用這個函數(shù)可以重新允許驅動被卸載,。
8,、GetDeviceListHead (Get head of list of devices created by driver)
    獲得一個指向驅動創(chuàng)建的處于設備列表最前面的那個設備對象的指針。
【函數(shù)原型】
    KDevice* GetDeviceListHead( void );
【Returns】
    返回一個指向當前驅動創(chuàng)建的KDevice派生類實例的指針,。如果驅動沒有創(chuàng)建任何設備對象,,函數(shù)返回NULL。
【Comments】
    驅動創(chuàng)建的設備對象集合被連成一個鏈表,,鏈表最前面的那個(the head of the list)存儲在驅動對象里,。創(chuàng)建的這個鏈表可以使最后被創(chuàng)建的設備處于鏈表的最前端(the head)。
    這個函數(shù)可以在任何中斷級別上調用(any IRQL),。
9,、DeleteDevices (Delete all devices created by driver)
    函數(shù)刪除驅動創(chuàng)建的所有設備對象。
【函數(shù)原型】
    VOID DeleteDevices( void );
【Comments】
    這個函數(shù)遍歷當前驅動的設備列表,,分別調用它們的析構函數(shù)并釋放它們的存儲空間,。需要注意的是KDevice的析構函數(shù)是虛函數(shù),一般來說一個驅動需要通告Unload()函數(shù)來間接調用它,。DeleteDevices也可用于清除一個在DriverEntry里初始化失敗的驅動程序,。
    這個函數(shù)運行在PASSIVE_LEVEL級別上。   
10,、ReleaseResources (Releases resources claimed by driver)
    用于釋放驅動申請的資源,。
【函數(shù)原型】
    NTSTATUS ReleaseResources( void );
【Returns】
    返回STATUS_SUCCESS表示資源釋放成功。
【Comments】
    這個函數(shù)可以釋放任何通過 KResourceRequest::Submit 為驅動分配的資源,。如果資源是被一個或一些特殊的設備申請的,,你必須調用KDevice::ReleaseResources來釋放。
    支撐它的系統(tǒng)調用是IoAssignResources,。
    這個函數(shù)只能在PASSIVE_LEVEL級別上調用。
11,、EnableDispatchFilter (Enable dispatch filter)
    這個函數(shù)可以使能或制止所有的I/O請求調用一個可重寫的DispatchFilter函數(shù),。
    前提是必須在function.h文件中聲明#define DRIVER_FUNCTION_DISPATCH_FILTERING 。
【函數(shù)原型】
    VOID EnableDispatchFilter( BOOLEAN enable );
【Parameters】
    enable        為TRUE就允許I/O請求調用DispatchFilter,,為FALSE就不允許,。
【Comments】
    默認情況下,,類庫框架將所有派遣者調用(Read, Write, DeviceControl, etc.) 直接對應到目標設備對象的一個成員函數(shù)上。然而,,當派遣過濾器被使能后,,框架會調用虛函數(shù)DispatchFilter。這種做法只有在KDriver的DispatchFilter()函數(shù)被重寫的情況下才有意義,。這種機制允許驅動類(the driver class)在所有的I/O請求被傳遞給KDevice子類之前對它們進行預處理,。
    這個函數(shù)可能在任何中斷級別上被調用(any IRQL)。
12,、DispatchFilter (Overridable dispatch entry point)
    這是一個可以被重寫的虛函數(shù),,實現(xiàn)對發(fā)送給派遣函數(shù)的I/O請求進行預處理。
【函數(shù)原型】
NTSTATUS DispatchFilter(
   KDevice* pDevice,
   KIrp I,
   NTSTATUS (KDevice::*func)(KIrp)
);
【Parameters】
    pDevice         I/O請求發(fā)送的目標類KDevice派生類的實例的地址
    I               I/O請求
    func            一般情況下*pDevice里處理該請求的成員函數(shù)的地址
【Returns】
    返回值是一種STATUS_xxxx形式的常量,,用來告知I/O管理器I/O請求的當前狀態(tài),。
【Comments】
    當派遣過濾器使能后,框架會將所有派遣者調用連到這個KDriver類的可重寫的函數(shù),。這使驅動類(the driver class)可以先于所有KDevice子類的函數(shù)看到I/O請求,,并且可能提供一個單一的處理點來監(jiān)聽驅動接收到的所有I/O請求。
    這個函數(shù)負責處理I/O請求,,或者它自己處理,,或者傳遞給設備對象(the device object)提供的函數(shù)處理。它必須返回一個I/O請求的狀態(tài)給I/O管理器,。
    它的基類的實現(xiàn)代碼中只是簡單的將I/O請求傳遞給了設備類(the device class):
NTSTATUS KDriver::DispatchFilter(
   KDevice* pDevice,
   KIrp I,
   NTSTATUS (KDevice::*func)(KIrp)
)
{
   return (pDevice->*func)(I);
}
13,、DriverObject (Accessor to retrieve pointer to system driver object)
    獲得一個和KDriver派生類實例一致的系統(tǒng)對象指針。
【函數(shù)原型】
    PDRIVER_OBJECT DriverObject( void );
【Returns】
    當系統(tǒng)最初調用驅動時,,返回一個用來傳給框架使用的系統(tǒng)驅動對象指針,。
    這個函數(shù)決不會返回NULL。
【Comments】
    當調用一個系統(tǒng)服務,,用到系統(tǒng)驅動對象指針時,,就會用到這個函數(shù)。這個指針存儲在KDriver子類的唯一實例中,。
    這個函數(shù)可能在任何中斷級別上被調用(any IRQL),。
   
14、RegistryPath (Accessor to retrieve registry path)
【函數(shù)原型】
    PUNICODE_STRING RegistryPath( void );
【Returns】
    返回一個字符串指針來說明系統(tǒng)存儲與當前驅動相關信息的注冊表鍵,。
【Comments】
    在系統(tǒng)最初調用驅動時,,這個函數(shù)相當于一個存儲在框架里的成員變量的存取器(accessor)。
    這個函數(shù)可能在任何中斷級別上被調用(any IRQL),。但是,,這個字符串一旦被存在分頁內存里,它就只能在PASSIVE_LEVEL級別上被引用。
15,、DriverInstance (Accessor to return pointer to single instance of KDriver)
【函數(shù)原型】
    KDriver* DriverInstance( void );
【Returns】
    返回KDriver派生類的唯一實例的地址,。
【Comments】
    KDriver類的構造函數(shù)不允許多于一個的派生類實例出現(xiàn)??蚣軙詣觿?chuàng)建這個實例,。這個函數(shù)返回這個實例的地址。如果需要,,我們可以放心的把返回值強制轉換成KDriver派生類的類型,。
    這個函數(shù)可能在任何中斷級別上被調用(any IRQL)。
16,、IsDevicePresent (Test if a device still exists or has been deleted)
    測試一個設備仍然存在著還是已經(jīng)被刪除,。
【函數(shù)原型】
    BOOLEAN IsDevicePresent( PDEVICE_OBJECT pDevice );
【Parameters】
    pDevice       被測試的系統(tǒng)設備對象的地址
【Returns】
    如果被測試的設備對象存在于驅動創(chuàng)建的設備列表中,就返回TRUE,;否則返回FALSE,。
【Comments】
    參數(shù)是一個系統(tǒng)設備對象的指針。KDevice類重載了一個類型轉換操作符(cast operator)使得編譯器可以自動把一個KDevice派生類的實例轉化成PDEVICE_OBJECT類型,。
    一個驅動程序只能測試它自己創(chuàng)建的設備對象,。
    這個函數(shù)可能在任何中斷級別上被調用(any IRQL)。
17,、DECLARE_DRIVER_CLASS (Macro to declare the driver class to the framework)
    宏定義指明哪個類作為驅動程序框架,。
【宏原型】
    DECLARE_DRIVER_CLASS( cpp_classname, driver_class_string )
【Parameters】
    cpp_classname        驅動類的名字(the driver class)
    driver_class_string  一個沒有終止符的Unicode字符串(null terminated),指明驅動的類,,用來存放系統(tǒng)注冊表資源信息,,可為NULL。
【Comments】
    框架創(chuàng)建的每個驅動都指定一個類作為驅動類(the driver class),。這個類繼承自KDriver類,,并且當系統(tǒng)最初調用驅動時,框架會自動創(chuàng)建一個此類的唯一實例,。
    框架要求驅動編寫人員用DECLARE_DRIVER_CLASS宏定義來指明驅動類,。這個宏調用必須出現(xiàn)在一個聲明了這個類的源文件的模塊里(通常是一個包含文件in an include file)。這個宏調用必須在所有{}之外,。
    這個宏調用實際上定義了一個函數(shù),,動態(tài)分配一塊非分頁內存區(qū)給指定類的實例。這個宏定義假定這個類有一個缺省的構造函數(shù),,由于這個原因,,這個類不能定義一個帶參數(shù)的構造函數(shù)。
 
本文來自CSDN博客,,轉載請標明出處:http://blog.csdn.net/kaizitop/archive/2008/03/22/2206680.aspx

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內容,,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多