国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信

這篇具有很好參考價(jià)值的文章主要介紹了windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

應(yīng)用程序和驅(qū)動(dòng)程序的通信

一、基礎(chǔ)介紹

1.1 設(shè)備與驅(qū)動(dòng)的關(guān)系

設(shè)備由驅(qū)動(dòng)去創(chuàng)建,訪問(wèn)一個(gè)設(shè)備,是首先得訪問(wèn)驅(qū)動(dòng)。如果驅(qū)動(dòng)在卸載的時(shí)候沒(méi)有刪除符號(hào),r3下也是不能去訪問(wèn)設(shè)備的。

驅(qū)動(dòng)程序和系統(tǒng)其他組件之間的交互是通過(guò)給設(shè)備發(fā)送或者接受發(fā)給設(shè)備的請(qǐng)求來(lái)交互的。換句話說(shuō),一個(gè)沒(méi)有任何設(shè)備的驅(qū)動(dòng)是不能按規(guī)范方式和系統(tǒng)交互的。當(dāng)然也不會(huì)收到任何IRP,分發(fā)函數(shù)也失去了意義。如果驅(qū)動(dòng)程序要和應(yīng)用程序之間通信,則需要生成設(shè)備。此外還必須為設(shè)備生成應(yīng)用程序可以訪問(wèn)的符號(hào)鏈接。

也就是說(shuō),應(yīng)用程序與驅(qū)動(dòng)的交互是通過(guò)設(shè)備來(lái)完成的,設(shè)備成了中間橋梁。下文中的符號(hào)鏈接又成了設(shè)備名的中間橋梁。記住,核心中介是設(shè)備。其他都是為他們的通信提供的機(jī)制。

1.2 設(shè)備符號(hào)鏈接名與設(shè)備名

Ring3不能直接訪問(wèn)設(shè)備,需要中間橋梁。這個(gè)中間橋梁是Ring0驅(qū)動(dòng)為設(shè)備名注冊(cè)的鏈接符號(hào)(Symbol Link)。
windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信

從圖中可以看出,R3要訪問(wèn)設(shè)備,是通過(guò)設(shè)備符號(hào)名去訪問(wèn)設(shè)備的,而R3應(yīng)用層下的設(shè)備符號(hào)名和設(shè)備管理器中的設(shè)備符號(hào)名有出入,必須,也只能寫(xiě)成\.\設(shè)備符號(hào)名 的方式 ,系統(tǒng)會(huì)自動(dòng)轉(zhuǎn)為??\設(shè)備符號(hào)名 ,緊接著通過(guò)設(shè)備符號(hào)名這個(gè)中間橋梁可以轉(zhuǎn)化為真正的R0下的設(shè)備名。

也就是說(shuō),符號(hào)鏈接名在應(yīng)用層只是簡(jiǎn)單的符號(hào)轉(zhuǎn)化過(guò)程,有些類似宏定義,設(shè)備符號(hào)名主體是相同的。而設(shè)備名和設(shè)備符號(hào)名可以不相同。因?yàn)樵O(shè)備符號(hào)名僅僅是個(gè)中間橋梁。

總結(jié):

  1. R0下的設(shè)備名格式為\Device\自定義設(shè)備名
  2. R0下的設(shè)備符號(hào)名格式為\??\自定義符號(hào)名,其中自定義符號(hào)名自定義設(shè)備名可以不一致。
  3. R3下不能直接訪問(wèn)設(shè)備,只能用設(shè)備符號(hào)名去訪問(wèn)設(shè)備,但是也不能直接使用\??\設(shè)備符號(hào)名去獲得設(shè)備名
  4. R3要訪問(wèn)設(shè)備,必須使用\\.\設(shè)備符號(hào)名,這個(gè)設(shè)備符號(hào)名由R0給定。
1.3 通信機(jī)制
  1. 應(yīng)用程序和驅(qū)動(dòng)程序的通信是通過(guò)IRP (i/o request packet) (IO請(qǐng)求包) 來(lái)完成的。
  2. 利用其它進(jìn)程通信方式,如socket、pip、共享內(nèi)存等(注意r0的api調(diào)用方式不一致)

二、IRP方式

2.1 定義IO控制碼

可以看做一種通信協(xié)議,宏定義:

#define CTL_CODE( DeviceType, Function, Method, Access ) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))

可以看到,這個(gè)宏四個(gè)參數(shù),自然是一個(gè)32位分成了4部分:

  • 高16位存儲(chǔ)設(shè)備類型
  • 14~15位訪問(wèn)權(quán)限
  • 2~13位操作功能
  • 最后0/1兩位就是確定緩沖區(qū)是如何與I/O和文件系統(tǒng)數(shù)據(jù)緩沖區(qū)進(jìn)行數(shù)據(jù)傳遞方式

自定義CTL_CODE

#define IOCTL_TEST_BUFFERED  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
  • IOCTL_TEST_BUFFERED:生成的IRP的MinorFunction
  • FILE_DEVICE_UNKNOWN:設(shè)備對(duì)象的類型。設(shè)備類型可參考:http://blog.csdn.net/liyun123gx/article/details/38058965
  • 0x900 :自定義的IO控制碼。自己定義時(shí)取0x800到0xFFF,因?yàn)?x0到0x7FF是微軟保留的。
  • METHOD_BUFFERED:緩沖區(qū)進(jìn)行數(shù)據(jù)傳遞方式
  • FILE_ANY_ACCESS :數(shù)據(jù)的操作模式。
內(nèi)存訪問(wèn)方式

有四種方式:

#define METHOD_BUFFERED     0
#define METHOD_IN_DIRECT    1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER      3

METHOD_BUFFERED:表示系統(tǒng)將用戶的輸入輸出都經(jīng)過(guò)pIrp->AssociatedIrp.SystemBuffer來(lái)緩沖,因此這種方式的通信比較安全。
windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信

METHOD_IN_DIRECTMETHOD_OUT_DIRECT:表示系統(tǒng)會(huì)將輸入緩沖在pIrp->AssociatedIrp.SystemBuffer中,并將輸出緩沖區(qū)鎖定,然后在內(nèi)核模式下重新映射一段地址,這樣也是比較安全的。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT可稱為"直接方式",是指系統(tǒng)依然對(duì)Ring3的輸入緩沖區(qū)進(jìn)行緩沖,但是對(duì)Ring3的輸出緩沖區(qū)并沒(méi)有緩沖,而是在內(nèi)核中進(jìn)行了鎖定。這樣Ring3輸出緩沖區(qū)在驅(qū)動(dòng)程序完成I/O請(qǐng)求之前,都是無(wú)法訪問(wèn)的,從一定程度上保障了安全性。這兩種方式,對(duì)于Ring3的輸入緩沖區(qū)和METHOD_BUFFERED方式是一致的。對(duì)于Ring3的輸出緩沖區(qū),首先由系統(tǒng)鎖定,并使用pIrp->MdlAddress來(lái)描述這段內(nèi)存,驅(qū)動(dòng)程序需要使用MmGetSystemAddressForMdlSafe函數(shù)將這段內(nèi)存映射到內(nèi)核內(nèi)存地址(OutputBuffer),然后可以直接寫(xiě)入OutputBuffer地址,最終在驅(qū)動(dòng)派遣例程返回后,由系統(tǒng)解除這段內(nèi)存的鎖定。

METHOD_IN_DIRECT和METHOD_OUT_DIRECT方式的區(qū)別,僅在于打開(kāi)設(shè)備的權(quán)限上,當(dāng)以只讀權(quán)限打開(kāi)設(shè)備時(shí),METHOD_IN_DIRECT方式的IoControl將會(huì)成功,而METHOD_OUT_DIRECT方式將會(huì)失敗。如果以讀寫(xiě)權(quán)限打開(kāi)設(shè)備,兩種方式都會(huì)成功。
windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信

METHOD_NEITHER:“其他方式”,雖然通信的效率提高了,但是不夠安全。驅(qū)動(dòng)的派遣函數(shù)中輸入緩沖區(qū)可以通過(guò)I/O堆棧(IO_STACK_LOCATION)的stack->Parameters.DeviceIo Control.Type3InputBuffer得到。輸出緩沖區(qū)可以通過(guò)pIrp->UserBuffer得到。由于驅(qū)動(dòng)中的派遣函數(shù)不能保證傳遞進(jìn)來(lái)的用戶輸入和輸出地址,因此最好不要直接去讀寫(xiě)這些地址的緩沖區(qū)。應(yīng)該在讀寫(xiě)前使用ProbeForRead和ProbeForWrite函數(shù)探測(cè)地址是否可讀和可寫(xiě)。

METHOD_ NEITHER方式是不進(jìn)行緩沖的,在驅(qū)動(dòng)中可以直接使用Ring3的輸入輸出內(nèi)存地址,驅(qū)動(dòng)程序可以通過(guò)pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer得到Ring3的輸入緩沖區(qū)地址(其中pIrpStack是IoGetCurrentIrpStackLocation(pIrp)的返回);通過(guò)pIrp-> UserBuffer得到Ring3的輸出緩沖區(qū)地址。

由于METHOD_NEITHER方式并不安全,因此最好對(duì)Type3InputBuffer讀取之前使用ProbeForRead函數(shù)進(jìn)行探測(cè),對(duì)UserBuffer寫(xiě)入之前使用ProbeForWrite函數(shù)進(jìn)行探測(cè),當(dāng)沒(méi)有發(fā)生異常時(shí),再進(jìn)行讀取和寫(xiě)入操作。
windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信
windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信

2.2 定義驅(qū)動(dòng)設(shè)備名,符號(hào)鏈接名

關(guān)于在Ring0層中要設(shè)置驅(qū)動(dòng)設(shè)備名的同時(shí)還要設(shè)置符號(hào)鏈接名的原因,是因?yàn)橹挥蟹?hào)鏈接名才可以被用戶模式下的應(yīng)用程序識(shí)別。

如果IoCreateDevice中沒(méi)有指定設(shè)備名稱,那么I/O管理器會(huì)自動(dòng)分配一個(gè)數(shù)字作為設(shè)備的名稱。

// 驅(qū)動(dòng)設(shè)備名:設(shè)備與設(shè)備之間通信
#define DEVNAME L"\\Device\\kmdfDriver2"

// 符號(hào)鏈接名:設(shè)備與Ring3之間通信
#define LNKNAME L"\\??\\kmdfDriver2"
2.3 設(shè)備同驅(qū)動(dòng)通信

驅(qū)動(dòng)程序要做的最后一步,先用IoCreateDevice函數(shù)創(chuàng)建設(shè)備對(duì)象,再用IoCreateSymbolicLink將符號(hào)鏈接名與設(shè)備對(duì)象名稱關(guān)聯(lián),大功告成,等待IO控制碼。


// 創(chuàng)建設(shè)備對(duì)象名稱
RtlInitUnicodeString(&DeviceObjectName,DEVICE_OBJECT_NAME);
// 創(chuàng)建設(shè)備對(duì)象
Status = IoCreateDevice(DriverObject,NULL,
    &DeviceObjectName,
    FILE_DEVICE_UNKNOWN,
    0, FALSE,
    &DeviceObject);
if (!NT_SUCCESS(Status))
{
   
    return Status;
}

// 創(chuàng)建設(shè)備連接名稱
RtlInitUnicodeString(&DeviceLinkName, DEVICE_LINK_NAME);
// 將設(shè)備連接名稱與設(shè)備名稱關(guān)聯(lián)
Status = IoCreateSymbolicLink(&DeviceLinkName,&DeviceObjectName);

if (!NT_SUCCESS(Status))
{
   
    IoDeleteDevice(DeviceObject);
    return Status;
}       

驅(qū)動(dòng)程序鋪墊打理好之后,應(yīng)用程序就可以由符號(hào)鏈接名通過(guò)CreateFile函數(shù)獲取到設(shè)備句柄DeviceHandle,再用本場(chǎng)的主角,DeviceIoControl通過(guò)這個(gè)DeviceHandle發(fā)送控制碼了。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-405179.html

BOOL WINAPI DeviceIoControl(
  _In_         HANDLE hDevice,       // CreateFile函數(shù)打開(kāi)的設(shè)備句柄
  _In_         DWORD dwIoControlCode,// 自定義的控制碼
  _In_opt_     LPVOID lpInBuffer,    // 輸入緩沖區(qū)
  _In_         DWORD nInBufferSize,  // 輸入緩沖區(qū)的大小
  _Out_opt_    LPVOID lpOutBuffer,   // 輸出緩沖區(qū)
  _In_         DWORD nOutBufferSize, // 輸出緩沖區(qū)的大小
  _Out_opt_    LPDWORD lpBytesReturned, // 實(shí)際返回的字節(jié)數(shù),對(duì)應(yīng)驅(qū)動(dòng)程序中pIrp->IoStatus.Information。
  _Inout_opt_  LPOVERLAPPED lpOverlapped // 重疊操作結(jié)構(gòu)指針。同步設(shè)為NULL,DeviceIoControl將進(jìn)行阻塞調(diào)用;否則,應(yīng)在編程時(shí)按異步操作設(shè)計(jì)
);
HANDLE CreateFile(
  LPCTSTR lpFileName,                         // 打開(kāi)的文件名
  DWORD dwDesiredAccess,                    // 訪問(wèn)權(quán)限
  DWORD dwShareMode,                      // 共

到了這里,關(guān)于windows驅(qū)動(dòng)開(kāi)發(fā)7:應(yīng)用程序和驅(qū)動(dòng)程序的通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • LCD驅(qū)動(dòng)程序——Framebuffer應(yīng)用編程

    LCD驅(qū)動(dòng)程序——Framebuffer應(yīng)用編程

    在 Linux 系統(tǒng)中通過(guò) Framebuffer 驅(qū)動(dòng)程序來(lái)控制 LCD。 Frame 是幀的意思 , buffer 是緩沖的意思 ,這意味著 Framebuffer 就是一塊內(nèi)存,里面保存著一幀圖像。Framebuffer 中保存著一幀圖像的每一個(gè)像素顏色值,假設(shè) LCD 的分辨率是 1024x768,每一個(gè)像素的顏色用 32 位來(lái)表示,那么 Frame

    2024年02月06日
    瀏覽(20)
  • 5.2.10.應(yīng)用程序如何調(diào)用驅(qū)動(dòng) mknod /dev/test c 250 0 創(chuàng)建設(shè)備文件,應(yīng)用app 程序 調(diào)用 我們 驅(qū)動(dòng) 殼子

    5.2.10.應(yīng)用程序如何調(diào)用驅(qū)動(dòng) mknod /dev/test c 250 0 創(chuàng)建設(shè)備文件,應(yīng)用app 程序 調(diào)用 我們 驅(qū)動(dòng) 殼子

    5.2.10.應(yīng)用程序如何調(diào)用驅(qū)動(dòng) 5.2.10.1、驅(qū)動(dòng)設(shè)備文件的創(chuàng)建 (1)何為設(shè)備文件 ? ??索引驅(qū)動(dòng) (2)設(shè)備文件的關(guān)鍵信息是:設(shè)備號(hào) = 主設(shè)備號(hào) + 次設(shè)備號(hào),使用ls -l去查看設(shè)備文件,就可以得到這個(gè)設(shè)備文件對(duì)應(yīng)的主次設(shè)備號(hào)。 ????????4顆LED不可能 都占用 主設(shè)備號(hào),設(shè)備號(hào)

    2024年02月16日
    瀏覽(28)
  • 第五章 I/O管理 五、輸入/輸出應(yīng)用程序接口&設(shè)備驅(qū)動(dòng)程序接口

    第五章 I/O管理 五、輸入/輸出應(yīng)用程序接口&設(shè)備驅(qū)動(dòng)程序接口

    目錄 一、應(yīng)用程序接口 二、阻塞和非阻塞I/O 阻塞I/O: 非阻塞I/O: 三、設(shè)備驅(qū)動(dòng)程序 以前的統(tǒng)一接口不適用了,現(xiàn)在改為了幾種不同的接口 阻塞I/O: 應(yīng)用程序發(fā)出I/O系統(tǒng)調(diào)用,進(jìn)程需轉(zhuǎn)為阻塞態(tài)等待。 eg:字符設(shè)備接口―一從鍵盤(pán)讀一個(gè)字符get 非阻塞I/O: 應(yīng)用程序發(fā)出I/O系統(tǒng)調(diào)

    2024年02月07日
    瀏覽(46)
  • ODBC 在指定的DSN中,驅(qū)動(dòng)程序和應(yīng)用程序之間的體系結(jié)構(gòu)不匹配

    ODBC 在指定的DSN中,驅(qū)動(dòng)程序和應(yīng)用程序之間的體系結(jié)構(gòu)不匹配

    常規(guī)辦法就是64位或32位匹配,如果解決不了,往下看。 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓解決方案↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 解壓AccessDatabaseEngine_X64.exe,用orca編輯器打開(kāi)AceRedist.

    2024年02月02日
    瀏覽(22)
  • 事件驅(qū)動(dòng)編程:如何在應(yīng)用程序中處理用戶輸入和交互

    [toc] 引言 1.1. 背景介紹 隨著互聯(lián)網(wǎng)技術(shù)的快速發(fā)展,應(yīng)用程序被廣泛應(yīng)用于人們的生活和工作中。在這些應(yīng)用程序中,用戶輸入和交互是必不可少的組成部分。如何優(yōu)雅地處理用戶輸入和交互,讓?xiě)?yīng)用程序更加符合用戶的使用習(xí)慣,是擺在每個(gè)程序員面前的一個(gè)重要問(wèn)題。

    2024年02月07日
    瀏覽(32)
  • LangChain入門(mén):構(gòu)建LLM驅(qū)動(dòng)的應(yīng)用程序的初學(xué)者指南

    LangChain入門(mén):構(gòu)建LLM驅(qū)動(dòng)的應(yīng)用程序的初學(xué)者指南

    LangChain DemoGPT ????????你有沒(méi)有想過(guò)如何使用大型語(yǔ)言模型(LLM)構(gòu)建強(qiáng)大的應(yīng)用程序?或者,也許您正在尋找一種簡(jiǎn)化的方式來(lái)開(kāi)發(fā)這些應(yīng)用程序?那么你來(lái)對(duì)地方了!本指南將向您介紹LangChain,這是一個(gè)簡(jiǎn)化構(gòu)建LLM驅(qū)動(dòng)的應(yīng)用程序的過(guò)程的工具。我們還將深入研究?

    2024年02月12日
    瀏覽(28)
  • Node.js 中的事件驅(qū)動(dòng)編程:構(gòu)建強(qiáng)大應(yīng)用程序的利器

    引言: 在當(dāng)今高度并發(fā)的網(wǎng)絡(luò)環(huán)境下,構(gòu)建高效、響應(yīng)迅速的應(yīng)用程序是開(kāi)發(fā)人員的一項(xiàng)重要任務(wù)。Node.js,作為一種基于事件驅(qū)動(dòng)編程模型的 JavaScript 運(yùn)行環(huán)境,為開(kāi)發(fā)人員提供了一個(gè)強(qiáng)大的工具。本文將介紹 Node.js 中的事件模型以及如何使用事件驅(qū)動(dòng)編程模式構(gòu)建強(qiáng)大的

    2024年02月10日
    瀏覽(26)
  • Rabbit R1是一款A(yù)I驅(qū)動(dòng)的小工具,可以代替你使用應(yīng)用程序

    Rabbit R1是一款A(yù)I驅(qū)動(dòng)的小工具,可以代替你使用應(yīng)用程序

    ??每周跟蹤AI熱點(diǎn)新聞動(dòng)向和震撼發(fā)展 想要探索生成式人工智能的前沿進(jìn)展嗎?訂閱我們的簡(jiǎn)報(bào),深入解析最新的技術(shù)突破、實(shí)際應(yīng)用案例和未來(lái)的趨勢(shì)。與全球數(shù)同行一同,從行業(yè)內(nèi)部的深度分析和實(shí)用指南中受益。不要錯(cuò)過(guò)這個(gè)機(jī)會(huì),成為AI領(lǐng)域的領(lǐng)跑者。點(diǎn)擊訂閱,與

    2024年02月19日
    瀏覽(21)
  • 探索在云原生環(huán)境中構(gòu)建的大數(shù)據(jù)驅(qū)動(dòng)的智能應(yīng)用程序的成功案例,并分析它們的關(guān)鍵要素。

    探索在云原生環(huán)境中構(gòu)建的大數(shù)據(jù)驅(qū)動(dòng)的智能應(yīng)用程序的成功案例,并分析它們的關(guān)鍵要素。

    ??個(gè)人主頁(yè):程序員 小侯 ??CSDN新晉作者 ??歡迎 ??點(diǎn)贊?評(píng)論?收藏 ?收錄專欄:云計(jì)算 ?文章內(nèi)容:云原生 ??希望作者的文章能對(duì)你有所幫助,有不足的地方請(qǐng)?jiān)谠u(píng)論區(qū)留言指正,大家一起學(xué)習(xí)交流!?? 在云原生環(huán)境中構(gòu)建大數(shù)據(jù)驅(qū)動(dòng)的智能應(yīng)用程序已經(jīng)成為許多

    2024年02月10日
    瀏覽(27)
  • Windows 驅(qū)動(dòng)程序簽名教程(一) --- 開(kāi)發(fā)測(cè)試篇

    1.使用微軟WHQL簽名 2.使用2013-2015年簽發(fā)的驅(qū)動(dòng)簽名,已過(guò)期未吊銷(xiāo)未拉黑(不知道什么時(shí)候打個(gè)補(bǔ)丁會(huì)修復(fù)). 1.使用微軟WHQL簽名 2.使用過(guò)期簽名的sha1 sha256都可以正常跑 1.使用微軟WHQL簽名,SHA256的簽名需要打補(bǔ)丁支持(KB3033929). 2.SHA1簽名 1.Windows 10 可以直接 輸入命令: 2.如果還不

    2024年02月15日
    瀏覽(21)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包