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

您的位置:首頁技術(shù)文章
文章詳情頁

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

瀏覽:166日期:2023-08-27 17:46:38

第三章 編寫內(nèi)核模式驅(qū)動程序

翻譯: Kendiv

更新: Monday, February 07, 2005

在下一章中,我們會經(jīng)常訪問那些僅在內(nèi)核模式下才有效的系統(tǒng)資源。大量的示例代碼都被設(shè)計為內(nèi)核驅(qū)動例程( Kernel-mode driver routine )。因此,需要有關(guān)開發(fā)此種軟件的基本知識。因為我不能假定所有讀者都有這方面的經(jīng)驗,我會在此簡要地介紹一下內(nèi)核模式驅(qū)動程序編程,不過這僅集中在如何使用驅(qū)動開發(fā)向?qū)Вㄔ诒緯獗P上)。

本章還將討論 Windows 2000 服務(wù)控制管理器( Service Control Manager , SCM )的基本知識,這包括 SCM 如何允許在運行時加載、控制和卸載驅(qū)動程序, resulting in wonderfully short change-build-test turnaround cycles 。本章的題目或許會讓人有些誤解,驅(qū)動一詞通常與控制硬件的底層軟件相關(guān)。事實上,很多內(nèi)核程序員每天都在做這些事情。不過, Windows 2000 的驅(qū)動程序分層模式允許做比這更多的事情。內(nèi)核驅(qū)動程序可以完成任意復(fù)雜的任務(wù),若不考慮它們運行于更高的 CPU 特權(quán)級別上而且使用不同的開發(fā)接口,那它們很像用戶模式下的 DLL 。在此,我們將使用這種強大的開發(fā)技術(shù)來偵測 Windows 2000 的內(nèi)部秘密,使用內(nèi)核驅(qū)動程序就像駕駛從狹小的用戶模式飛往 Windows 2000 內(nèi)核的太空飛船。

創(chuàng)建一個驅(qū)動程序的骨架

即使長時間開發(fā) Win32 應(yīng)用程序和庫的開發(fā)人員,在首次編寫內(nèi)核驅(qū)動程序時,也會感覺像是一個絕對的初學(xué)者。這是因為,內(nèi)核模式下的代碼運行在一個完全不同的操作系統(tǒng)環(huán)境中。 Win32 開發(fā)人員的工作僅局限在屬于 Windows 2000 Win32 子系統(tǒng)的幾個系統(tǒng)組件上。其他開發(fā)人員可能編寫 POSI 或 OS/2 應(yīng)用程序, Windows 2000 的附加子系統(tǒng)為它們提供支持。感謝子系統(tǒng)這個概念, Windows 2000 就像一個變色龍 --- 它可通過這些子系統(tǒng)(前面提及的)導(dǎo)出不同的應(yīng)用程序開發(fā)接口來模擬不同的操作系統(tǒng)。與此相反,內(nèi)核模式的代碼可以看到“真實”的 Windows 2000 操作系統(tǒng)。它們使用的接口可以稱之為“最終邊界”。當(dāng)然,這并不是說,內(nèi)核模式完全擺脫了子系統(tǒng)。在第二章中,我們看到 win32k.sys 就是 Win32 GUI 和窗口管理器在內(nèi)核模式下的分支,將它們放在內(nèi)核是出于性能考慮。然而, win32k.sys 導(dǎo)出的 API 函數(shù)集合中只有一小部分出現(xiàn)在了 gdi32.dll 和 user32.dll 中,這也意味著只有這一小部分函數(shù)可以作為 Win32 API 函數(shù)來使用,因此, Win32K 決不只是 Win32 踏入內(nèi)核世界的一腳,實際上,應(yīng)把它看作是一個高性能的內(nèi)核模式的圖形引擎。

Windows 2000 DDK Device Driver Kit

由于內(nèi)核模式下的編程使用了不同的系統(tǒng)接口,在 Win32 編程中經(jīng)常使用的頭文件和庫都將無法在內(nèi)核模式下使用。針對 Win32 開發(fā),微軟提供了 Platform Software Development Kit ( SDK )。而與內(nèi)核模式的驅(qū)動開發(fā)相關(guān)的是, Windows 2000 Device Driver Kit ( DDK )。隨文檔一起, DDK 還提供了特殊的頭文件和導(dǎo)入庫,這些都是 Windows 2000 內(nèi)核模塊必須的接口。安裝完 DDK 之后,接下來你應(yīng)該打開 Visual C/C++ ,把 DDK 的路徑加入到編譯器和鏈接器的目錄列表中。在主菜單中選擇 Tools à Options ,然后單擊 DirectorIEs 。在目錄選擇下拉列表中選擇 Include files ,然后將 DDK 的適當(dāng)路徑加入,如 3-1 所示。默認情況下, DDK 將安裝到 NTDDK 目錄下, included 文件位于 NTDDKinc 子目錄中。需要注意的是,請將新添加的路徑置于原有路徑的上方,這樣就會使用新的頭文件或者庫。

圖 3-1 添加 DDK 頭文件路徑

圖 3-2 添加 DDK 導(dǎo)入庫路徑

在添加完 DDK 頭文件路徑后,用同樣的方法添加導(dǎo)入庫的路徑。 DDK 包含兩組導(dǎo)入庫,一組叫做 free ( release ) builds ,另一組叫做 checked ( debug ) builds 。其對應(yīng)的目錄為: NTDDKlibfrei386 和 NTDDKlibchki386 ,參見 3-2

DDK 開發(fā)環(huán)境與 Win32 模式有所不同,下面給出二者之間的一些明顯區(qū)別:

l 對于 Win32 程序員來說,主要的頭文件是 windows.h ,對于內(nèi)核模式代碼來說,應(yīng)使用 ntddk.h 替代之。

l 主進入點函數(shù)叫做 DirverEntry() ,而不再是 WinMain() 或 main() 。 列表 3-1 給出了它們的原型。

l 不能再使用一些常見的 Win32 數(shù)據(jù)類型,如 BYTE 、 Word 和 DWORD 。 DDK 使用 UCHAR 、 USHORT 、 ULONG 等。不過,很容易就能定義你自己喜歡的類型, 列表 3-2 給出了這樣的一個示例。

NTSTATUS DriverEntry ( PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath);

列表 3-1 DriverEntry 函數(shù)的原型

typedef UCHAR BYTE, *PBYTE;

typedef USHORT WORD, *PWORD;

typedef ULONG DWORD, *PDWORD;

列表 3-2 定義常見的 Win32 數(shù)據(jù)類型

此外,還需要注意 Windows NT 4.0 和 Windows 2000 所使用的 DDK 之間的差別,有三點不同需要注意,如下:

l 默認情況下, Windows NT 4.0 DDK 的主目錄叫做 DDK ,而 Windows 2000 DDK 叫做 NTDDK

l 在 Windows NT 4.0 DDK 中,主要的頭文件 ntddk.h 位于主目錄之下。而在 Windows 2000 DDK 中,該文件被移到了 NTDDKDDK 子目錄下。

l 導(dǎo)入庫的路徑也發(fā)生了變化: libi386free 變成了 libfrei386 , libi386checked 變成了 libchki386 。

我不知道微軟的這種改變有什么實際意義,不過為了生活,我們還是需要了解其變化 J 。

可定制的驅(qū)動程序向?qū)?

開發(fā)內(nèi)核驅(qū)動程序的主要困難在于 Visual C/C++ 沒有提供此種類型的工程向?qū)АP疫\的是, MSDN 里有一系列不錯的關(guān)于 Windows NT 內(nèi)核驅(qū)動開發(fā)的文章,是 Ruediger R.Asche. 在 1994 至 1995 年編寫的。其中的兩篇文章( Asche 1995a , 1995b )詳細說明了如何在 Visual C/C++ 中加入自定義的驅(qū)動程序向?qū)В@些文章給了我很大的幫助,盡管原始向?qū)У妮敵鑫募荒軡M足我的所有需求,但這是一個很好的開始。我提供的內(nèi)核驅(qū)動向?qū)⒒?Ruediger Asche 的原始向?qū)Мa(chǎn)生的輸出文件。

我提供的驅(qū)動向?qū)У乃性创a位于本書光盤的 srcw2k_wiz 目錄。通過閱讀這些代碼,你會發(fā)現(xiàn)它實際的標題“ SBS Windows 2000 Code Wizard ”。事實上,這是一個一般性的 Windows 2000 程序骨架生成器,該生成器可以產(chǎn)生多種類型的程序,包括 Win32 DLL 和應(yīng)用程序。不過,光盤中的配置文件針對內(nèi)核驅(qū)動開發(fā)做了一定的修改。基本上來說,我提供的向?qū)且粋€文件轉(zhuǎn)換器,它讀取一組文件,然后按照一些簡單的規(guī)則將它們進行轉(zhuǎn)換,最后將結(jié)果寫入另一組文件中。輸入文件是模板,輸出文件是 C 工程文件。通過修改模板文件,該向?qū)Э梢宰兂梢粋€ DLL 向?qū)У鹊取1仨毺峁?7 個模板文件(如果丟失了某一個,會產(chǎn)生錯誤):

l 擴展名為 .tw 的文件是 workspace 模板,此種文件將會被保存為 Visual Studio 的工程文件 .dsw 。

l 擴展名為 .tp 的文件是工程模板,此種文件將被保存為 .dsp 文件。工程文件由于之關(guān)聯(lián)的 workspace 文件引用,工程文件還包含生成工程的所有配置選項。

l 擴展名為 .tc 、 .th 、 .tr 和 .td 的文件都是 C 代碼文件,這些文件最后會變成相應(yīng)的 .c 、 .h 、 .rc 和 .def 文件。

l 擴展名為 .ti 的是 icon 文件,該文件會被直接保存為 .ico 文件。

這七個文件是一個新工程所必需的。 .def 文件以一種較老風(fēng)格的方法從 DLL 中導(dǎo)出 API 函數(shù),不過我更喜歡 __declspec(dllexport) 方式。因為驅(qū)動程序通常不導(dǎo)出函數(shù),所以我省略了 .td 模板,導(dǎo)致的結(jié)果是,在開始時,向?qū)蟾嬉粋€錯誤。我還省略了資源腳本和 icon 文件,不過經(jīng)驗告訴我,最好提供它們。采用的轉(zhuǎn)換規(guī)則也非常簡單,僅包含一個很短的字符串替換列表。在掃描模板文件時,轉(zhuǎn)換器查找以 % 號開始的轉(zhuǎn)義符。當(dāng)它找到后,會根據(jù) % 后的字符來決定執(zhí)行什么樣的動作。 3-1 列出了驗證過的轉(zhuǎn)義符。

表 3-1 中有幾處需參考配置文件 ---w2k_wiz.ini 。 示例 3-1 給出了其默認設(shè)置。在使用向?qū)е埃銘?yīng)該將光盤 srcw2k_wizrelease 目錄下的 w2k_wiz.exe 、 w2k_wiz.ini 和所有的 w2k_wiz.t* 模板文件復(fù)制到你的硬盤上,然后編輯配置文件,將對應(yīng)內(nèi)容改為你自己的設(shè)置。你還需要修改 Include 、 Free 和 Checked ,使其和你的 DDK 安裝相匹配。如果你使用 Visual C/C++ 6.0 ,可以不改變 Root 的值。如果不,則將其設(shè)為你存放工程文件的根目錄。如果以一個反斜線結(jié)尾,它將作為默認值。在 示例 3-1 中,其鍵值為: HKEY_CURRENT_USERSoftWareMicrosoftoDevStudio6.0Directories ,而 WorkspaceDir 用來存放基本的工作目錄。

鍵入 w2k_wiz MyDriver 來執(zhí)行該向?qū)В鼤?dāng)前目錄下創(chuàng)建名為 MyDriver 的工程目錄,該目錄將存放向?qū)傻?MyDriver.dsw 、 MyDriver.dsp 、 MyDriver.c 、 MyDriver.h 、 MyDriver.rc 和 MyDriver.ico 文件。如果你指定了具體的路徑,則會在你指定的路徑下創(chuàng)建該目錄。另一個合法的命令選項是星號,如: w2k_wiz *MyDriver 。在此種情況下,向?qū)Р粫诋?dāng)前目錄下創(chuàng)建工程目錄,而是去查找 Visual C/C++ 維護的默認的工程根目錄,即 w2k_wiz.ini 中的 Root 所指向的位置。

w2k_wiz.ini

08-27-2000 Sven B. Schreiber

sbs@orgon.com

[Settings]

Text = <SBS Windows 2000 Code Wizard Project>

Company = <MyCompany>

Author = <MyName>

Email = <my@email>

Prefix = <MyPrefix>

Include = E:NTDDKinc

Free = E:NTDDKlibfrei386

Checked = E:NTDDKlibchki386

Root = HKEY_CURRENT_USERSoftwareMicrosoftDevStudio6.0DirectoriesWorkspaceDir

示例 3-1. 向?qū)еС值淖远x選項

運行驅(qū)動向?qū)?

現(xiàn)在,來試試這個驅(qū)動向?qū)А?示例 3-2 給出了在 Windows 2000 控制臺下執(zhí)行 w2k_wiz *TestDrv 后的輸出。這將在 Visual C/C++ 默認的工程根目錄下創(chuàng)建一個名為 TestDrv 的工程目錄。

顯然,除了將 .td 模板轉(zhuǎn)換為 .def 時出了錯,其余轉(zhuǎn)換都成功的完成了。因為該向?qū)傻尿?qū)動程序骨架不需要 .def 文件,所以不需要提供 .td 模板文件。現(xiàn)在,用 Visual C/C++ 打開一個新的 WorkSpace ,然后你會發(fā)現(xiàn)一個名為 TestDrv 的新目錄,該目錄中包含一個名為 TestDrv.dsw 的 WorkSpace 文件。該文件可以被正確的打開。接下來,你因該為生成項目選擇活動的配置信息。驅(qū)動向?qū)傻?.dsp 文件提供了如下兩個可用配置:

1. Win2k Kernel-mode Driver(debug)

2. Win2k Kernel-mode Driver(release)

默認情況下,將使用 debug 配置來生成項目,但是你可在任何時候從 Visual C/C++ 菜單 Build/Set Active Configuration 來選擇不同的項目配置。最后,你要將光盤中的 srccommonincludeDrvInfo.h 復(fù)制到你自己的頭文件目錄中。在打開 TestDrv.rc 時,應(yīng)使用文本模式來打開(如 3-3 所示),這是因為該文件使用了來自 DrvInfo.h 中的復(fù)雜的宏定義,這些宏會導(dǎo)致資源編輯器異常退出。這個錯誤從 Visual C/C++ 5.0 開始,在我印象中,一直沒有被改正過。和編輯器不同,資源編譯器( Resource Compiler )可以正常的處理這些宏。

圖 3-3. 以文本模式打開 TestDrv.c 、 TestDrv.h 和 TestDrv.rc

現(xiàn)在,已經(jīng)為第一次編譯做好了所有準備。在示例 3-3 中,我通過選擇 Build/Rebuild 菜單來建立 Driver 的 Release 版,看起來一切都正常。順便說一下,頭兩行末尾的省略號表示我截斷了 Build 命令的輸出。

鏈接器會在 Debug 或 Release 目錄下創(chuàng)建了一個名為 TestDrv.sys 的可執(zhí)行文件,這依賴于你的生成配置。 Test Driver 的 Release 版大小為 5.5KB ,其 Debug 版為 8KB 。你可以使用本書光盤中的 MFVDasm 或 PEView 來驗證 TestDrv.sys 是否包含有效的代碼和數(shù)據(jù)。

深入驅(qū)動程序的骨架

列表 3-3 展示了向?qū)傻?TestDrv.c 。與之相關(guān)的頭文件 TestDrv.h 在 列表 3-4 中。在 列表 3-3 中,請注意標題處的 <MyName> 和 <MyCompany> 標志。如果 w2k_wiz.ini 中的作者和公司名稱正確,那你自己的名字和相應(yīng)的公司名稱將會替代它們。

// TestDrv.c

// 08-07-2000 <MyName>

// Copyright @2005 <MyCompany>

#define _TESTDRV_SYS_

#include <ntddk.h>

#include 'TestDrv.h'

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

// DISCLAIMER

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

/*

This software is provided 'as is' and any express or implied

warranties, including, but not limited to, the implied warranties of

merchantability and fitness for a particular purpose are disclaimed.

In no event shall the author <MyName> be liable for any

direct, indirect, incidental, special, exemplary, or consequential

damages (including, but not limited to, procurement of substitute

goods or services; loss of use, data, or profits; or business

interruption) however caused and on any theory of liability,

whether in contract, strict liability, or tort (including negligence

or otherwise) arising in any way out of the use of this software,

even if advised of the possibility of such damage.

*/

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

// REVISION HISTORY

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

/*

08-07-2000 V1.00 Original version.

*/

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

// GLOBAL DATA

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

PRESET_UNICODE_STRING (usDeviceName, CSTRING (DRV_DEVICE));

PRESET_UNICODE_STRING (usSymbolicLinkName, CSTRING (DRV_LINK ));

PDEVICE_OBJECT gpDeviceObject = NULL;

PDEVICE_CONTEXT gpDeviceContext = NULL;

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

// DISCARDABLE FUNCTIONS

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

NTSTATUS DriverInitialize (PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath);

NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath);

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

#ifdef ALLOC_PRAGMA

#pragma alloc_text (INIT, DriverInitialize)

#pragma alloc_text (INIT, DriverEntry)

#endif

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

// DEVICE REQUEST HANDLER

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

NTSTATUS DeviceDispatcher (PDEVICE_CONTEXT pDeviceContext,

PIRP pIrp)

{

PIO_STACK_LOCATION pisl;

DWORD dInfo = 0;

NTSTATUS ns = STATUS_NOT_IMPLEMENTED;

pisl = IoGetCurrentIrpStackLocation (pIrp);

switch (pisl->MajorFunction)

{

case IRP_MJ_CREATE:

case IRP_MJ_CLEANUP:

case IRP_MJ_CLOSE:

{

ns = STATUS_SUCCESS;

break;

}

}

pIrp->IoStatus.Status = ns;

pIrp->IoStatus.Information = dInfo;

IoCompleteRequest (pIrp, IO_NO_INCREMENT);

return ns;

}

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

// DRIVER REQUEST HANDLER

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

NTSTATUS DriverDispatcher (PDEVICE_OBJECT pDeviceObject,

PIRP pIrp)

{

return (pDeviceObject == gpDeviceObject

? DeviceDispatcher (gpDeviceContext, pIrp)

: STATUS_INVALID_PARAMETER_1);

}

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

void DriverUnload (PDRIVER_OBJECT pDriverObject)

{

IoDeleteSymbolicLink (&usSymbolicLinkName);

IoDeleteDevice (gpDeviceObject);

return;

}

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

// DRIVER INITIALIZATION

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

NTSTATUS DriverInitialize (PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath)

{

PDEVICE_OBJECT pDeviceObject = NULL;

NTSTATUS ns = STATUS_DEVICE_CONFIGURATION_ERROR;

if ((ns = IoCreateDevice (pDriverObject, DEVICE_CONTEXT_,

&usDeviceName, FILE_DEVICE_CUSTOM,

0, FALSE, &pDeviceObject))

== STATUS_SUCCESS)

{

if ((ns = IoCreateSymbolicLink (&usSymbolicLinkName,

&usDeviceName))

== STATUS_SUCCESS)

{

gpDeviceObject = pDeviceObject;

gpDeviceContext = pDeviceObject->DeviceExtension;

gpDeviceContext->pDriverObject = pDriverObject;

gpDeviceContext->pDeviceObject = pDeviceObject;

}

else

{

IoDeleteDevice (pDeviceObject);

}

}

return ns;

}

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

NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath)

{

PDRIVER_DISPATCH *ppdd;

NTSTATUS ns = STATUS_DEVICE_CONFIGURATION_ERROR;

if ((ns = DriverInitialize (pDriverObject, pusRegistryPath))

== STATUS_SUCCESS)

{

ppdd = pDriverObject->MajorFunction;

ppdd [IRP_MJ_CREATE ] =

ppdd [IRP_MJ_CREATE_NAMED_PIPE ] =

ppdd [IRP_MJ_CLOSE ] =

ppdd [IRP_MJ_READ ] =

ppdd [IRP_MJ_WRITE ] =

ppdd [IRP_MJ_QUERY_INFORMATION ] =

ppdd [IRP_MJ_SET_INFORMATION ] =

ppdd [IRP_MJ_QUERY_EA ] =

ppdd [IRP_MJ_SET_EA ] =

ppdd [IRP_MJ_FLUSH_BUFFERS ] =

ppdd [IRP_MJ_QUERY_VOLUME_INFORMATION] =

ppdd [IRP_MJ_SET_VOLUME_INFORMATION ] =

ppdd [IRP_MJ_DIRECTORY_CONTROL ] =

ppdd [IRP_MJ_FILE_SYSTEM_CONTROL ] =

ppdd [IRP_MJ_DEVICE_CONTROL ] =

ppdd [IRP_MJ_INTERNAL_DEVICE_CONTROL ] =

ppdd [IRP_MJ_SHUTDOWN ] =

ppdd [IRP_MJ_LOCK_CONTROL ] =

ppdd [IRP_MJ_CLEANUP ] =

ppdd [IRP_MJ_CREATE_MAILSLOT ] =

ppdd [IRP_MJ_QUERY_SECURITY ] =

ppdd [IRP_MJ_SET_SECURITY ] =

ppdd [IRP_MJ_POWER ] =

ppdd [IRP_MJ_SYSTEM_CONTROL ] =

ppdd [IRP_MJ_DEVICE_CHANGE ] =

ppdd [IRP_MJ_QUERY_QUOTA ] =

ppdd [IRP_MJ_SET_QUOTA ] =

ppdd [IRP_MJ_PNP ] = DriverDispatcher;

pDriverObject->DriverUnload = DriverUnload;

}

return ns;

}

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

// END OF PROGRAM

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

列表 3-3. 驅(qū)動程序骨架的源代碼

// TestDrv.h

// 08-07-2000 <MyName>

// Copyright @2005 <MyCompany>

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

// PROGRAM IDENTIFICATION

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

#define DRV_BUILD 1

#define DRV_VERSION_HIGH 1

#define DRV_VERSION_LOW 0

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

#define DRV_DAY 07

#define DRV_MONTH 02

#define DRV_YEAR 2005

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

// Customize these settings by editing the configuration file

// D:etc32w2k_wiz.ini

#define DRV_MODULE TestDrv

#define DRV_NAME <SBS Windows 2000 Code Wizard Project>

#define DRV_COMPANY <MyCompany>

#define DRV_AUTHOR <MyName>

#define DRV_EMAIL <my@email>

#define DRV_PREFIX <MyPrefix>

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

// HEADER FILES

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

#include 'drvinfo.h' // defines more DRV_* items

////////////////////////////////////////////////////////////////////

#ifndef _RC_PASS_

////////////////////////////////////////////////////////////////////

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

// CONSTANTS

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

#define FILE_DEVICE_CUSTOM 0x8000

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

// STRUCTURES

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

typedef struct _DEVICE_CONTEXT

{

PDRIVER_OBJECT pDriverObject;

PDEVICE_OBJECT pDeviceObject;

}

DEVICE_CONTEXT, *PDEVICE_CONTEXT, **PPDEVICE_CONTEXT;

#define DEVICE_CONTEXT_ sizeof (DEVICE_CONTEXT)

////////////////////////////////////////////////////////////////////

#endif // #ifndef _RC_PASS_

////////////////////////////////////////////////////////////////////

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

// END OF FILE

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

列表 3-4. 驅(qū)動程序骨架的頭文件

成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
91久久精品国产91性色tv| 欧美一区二视频| 日韩午夜在线观看| 老色鬼精品视频在线观看播放| 国产精品五区| 亚洲色图欧美偷拍| 一区免费视频| √…a在线天堂一区| 亚洲图片在线| 国产精品久久久久一区二区三区共| 欧美伊人影院| 国产欧美一区二区精品秋霞影院| 成人性生交大片免费看中文网站| 欧美精品粉嫩高潮一区二区| 狠狠色狠狠色综合系列| 欧美人动与zoxxxx乱| 奇米精品一区二区三区在线观看| 色综合久久88色综合天天6| 免费高清在线视频一区·| 欧美亚洲一区二区三区四区| 精品一区二区三区av| 777久久久精品| 国产麻豆91精品| 91精品国产欧美一区二区18| 国产成人高清在线| 337p日本欧洲亚洲大胆精品| 成人av网址在线| 2020日本不卡一区二区视频| 菠萝蜜视频在线观看一区| 精品国产免费久久| 91热门视频在线观看| 欧美国产日产图区| 激情自拍一区| 亚洲夂夂婷婷色拍ww47| 久久久一二三| 久久99久久99| 欧美xxxx在线观看| 91丨九色丨国产丨porny| 久久久不卡影院| 欧美日韩视频一区二区三区| 亚洲色图在线播放| 亚洲一区成人| 免费看欧美女人艹b| 91精品国产综合久久婷婷香蕉| 成人中文字幕在线| 久久久精品国产免费观看同学| 99视频精品在线| 亚洲国产激情av| 国产一区清纯| 樱桃视频在线观看一区| 老司机午夜精品视频在线观看| 男女激情视频一区| 欧美一区二区三区的| 91香蕉视频黄| 亚洲欧美aⅴ...| 老司机亚洲精品| 粉嫩一区二区三区在线看| 国产清纯美女被跳蛋高潮一区二区久久w | 亚洲精品国产无天堂网2021| 亚洲一区二区三区四区五区午夜| 日韩av在线发布| 7799精品视频| 欧美日韩一区二区三区在线观看免 | 日韩一区二区精品葵司在线| 成人av电影在线播放| 国产精品人人做人人爽人人添| 午夜亚洲视频| 国产精品一区一区三区| 亚洲国产精品ⅴa在线观看| 亚洲一区二区三区四区中文| 国产精品1024| 国产精品人成在线观看免费| 久久国产高清| 国产精品自在在线| 中文字幕一区二区三区蜜月| 色噜噜狠狠色综合中国| 波多野结衣中文字幕一区| 亚洲制服丝袜av| 欧美一区二区福利在线| 一区二区视频欧美| 免费美女久久99| 国产精品网站在线播放| 色婷婷av一区| 色综合色狠狠综合色| 亚洲成人免费在线| 日韩欧美aaaaaa| 一区二区欧美日韩| 国产成人免费在线观看不卡| 亚洲激情欧美激情| 日韩欧美区一区二| 久久av最新网址| 成人美女在线观看| 亚洲综合无码一区二区| 日韩一级片在线观看| 亚洲毛片播放| 国产精品自在在线| 一区二区三区久久| www国产成人免费观看视频 深夜成人网| 国产精品日韩欧美一区二区三区| 国产成人啪午夜精品网站男同| 亚洲美女在线一区| 欧美一级xxx| 国产日韩视频| 成人app软件下载大全免费| 性做久久久久久久久| 精品99久久久久久| 久久国产日本精品| 99国产精品国产精品毛片| 视频一区视频二区中文| 久久久久久电影| 色老汉av一区二区三区| 欧美精品二区| 国产一区二区三区四区五区美女| 一区二区激情小说| 久久免费美女视频| 欧美视频精品在线观看| av不卡在线| 99久久综合精品| 乱一区二区av| 一区二区高清免费观看影视大全| 久久蜜臀精品av| 在线一区二区观看| 亚洲东热激情| 成人爱爱电影网址| 久久激情五月激情| 夜夜嗨av一区二区三区网页| 久久精品亚洲麻豆av一区二区 | 国产成人丝袜美腿| 日韩av在线播放中文字幕| 中文欧美字幕免费| 精品日韩av一区二区| 欧美中文字幕不卡| 国产区日韩欧美| 欧美久久电影| 成人午夜免费av| 精品一区二区三区久久久| 午夜精品久久久久久久久久久| 国产精品美女一区二区三区| 日韩欧美电影一区| 欧美日本一区二区三区四区| 国产精品一区二区欧美| 亚洲国产欧美国产综合一区| 欧美xxx在线观看| 成人综合婷婷国产精品久久| 经典三级一区二区| 日韩电影在线一区二区| 一区二区三区四区乱视频| 国产欧美日韩另类视频免费观看| 欧美一区二区三区在线观看视频 | 在线观看一区二区视频| 亚洲精品乱码久久久久久蜜桃91| 91网站最新网址| 盗摄精品av一区二区三区| 激情五月播播久久久精品| 日韩福利视频导航| 午夜久久久影院| 亚洲午夜精品网| 亚洲色图自拍偷拍美腿丝袜制服诱惑麻豆| 国产欧美一区二区三区沐欲| 精品欧美一区二区三区精品久久| 欧美精品在线观看一区二区| 欧美亚洲综合一区| 日本高清无吗v一区| 久久精选视频| 老司机精品视频网站| 久久精品官网| 欧美亚洲网站| 欧美亚洲色图校园春色| 亚洲一区二区三区在线观看视频| 亚洲午夜激情在线| 国产精品videossex久久发布| 91免费视频网址| 91女厕偷拍女厕偷拍高清| 91丝袜美腿高跟国产极品老师 | 免费在线一区观看| 午夜精品aaa| 亚瑟在线精品视频| 日日夜夜精品免费视频| 视频一区在线视频| 免费成人av资源网| 激情文学综合网| 国产一区二区免费在线| 国产精品一区专区| 久久久久久久欧美精品| 欧美暴力喷水在线| 黄色国产精品| 国产日本精品| 日韩av一二三| 激情一区二区三区| 日本欧美一区二区| 日本不卡视频在线| 欧美96一区二区免费视频| 日本成人中文字幕| 久久精品国产第一区二区三区| 日韩 欧美一区二区三区| 日本在线不卡视频| 精品一区二区三区久久| 国产成a人无v码亚洲福利| 99久久精品免费| 好看的亚洲午夜视频在线|