當前位置:編程學習大全網 - 源碼下載 - XP系統鍵盤windows鍵被屏蔽了怎麽恢復

XP系統鍵盤windows鍵被屏蔽了怎麽恢復

對於用過Windows的人,幾乎沒有人不知道Ctrl+Alt+Del組合鍵,尤其是在使用經常死機的Windows9x時,使用它的頻率更高,這壹組合鍵是專門為了系統安全起見提供的緊急出口。VC知識庫在線雜誌第11期,ac952_z_cn在他的個人專欄中寫過壹篇關於這方面的文章:?WINDOWS NT/2000下如何屏蔽CTRL+ALT+DEL?。因此本文側重於介紹在Windows XP中如何實現屏蔽CTRL+ALT+DEL組合鍵,也就是任務管理器,任務切換組合鍵(Alt+Tab),任務欄和?開始?菜單(Ctrl+Esc,VK_LWIN,VK_RWIN)。這個方法也能應用於Windows 2000環境。在Windows 9x/Me系統中,屏蔽Ctrl+Alt+Del和各種任務開關鍵的方法是通過下面的方法實現的:BOOL bOldState;SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &bOldState, 0);MS大佬認為這種方法很業余,所以在Windows NT/2000/XP中對此進行了修改。在這些較新的Windows版本中用戶登陸使用Winlogon和GINA?Graphical Identification and Authentication,意思是圖形化的身份認證,挺嚇唬人的是不是!其實就那麽回事。Winlogon是Windows系統的壹部分,它專門提供交互式登陸支持,而GINA則是Winlogon用來實現認證的壹個DLL?這個DLL就是msgina.dll。WlxInitialize、WlxActivateUserShell便是其中輸出,當然不知這兩個,還有別的。前者進行自身的初始化,後者激活用戶的外殼程序。Windows就是用這個DLL來實現用戶名+口令的身份認證的,但是開發人員可以用自己的GINA代替msgina.dll。例如,實現智能卡、視網膜掃描儀、DNA檢查等等認證機制來代替輸入用戶名+口令形式的身份檢查。 下面的表格中列出了與GINA有關的全部函數。其中有壹個是WlxLoggedOnSAS,當按下Ctrl+Alt+Del 鍵時,Winlogon便調用這個函數。(表壹)GINA 函數壹覽表 函數 描述WlxActivateUserShell激活用戶外殼程序WlxDisplayLockedNotice允許GINA DLL 顯示鎖定信息WlxDisplaySASNotice 當沒有用戶登陸時,Winlogon調用此函數WlxDisplayStatusMessageWinlogon 用壹個狀態信息調用此函數進行顯示WlxGetConsoleSwitchCredentials Winlogon調用此函數讀取當前登陸用戶的信任信息,並透明地將它們傳到目標會話WlxGetStatusMessage Winlogon 調用此函數獲取當前狀態信息WlxInitialize 針對指定的窗口位置進行GINA DLL初始化WlxIsLockOk 驗證工作站正常鎖定WlxIslogoffOk 驗證註銷正常WlxLoggedOnSAS 用戶已登陸並且工作站沒有被加鎖,如果此時接收到SAS事件,則Winlogon 調用此函數WlxLoggedOutSAS 沒有用戶登陸,如果此時收到SAS事件,則Winlogon 調用此函數WlxLogoff 請求註銷操作時通知GINA DLLWlxNegotiate 表示當前的Winlogon版本是否能使用GINA DLLWlxNetworkProviderLoad 在加載網絡服務提供程序收集了身份和認證信息後,Winlogon 調用此函數WlxRemoveStatusMessage Winlogon 調用此函數告訴GINA DLL 停止顯示狀態信息WlxScreensaverNotify 允許GINA與屏幕保護操作交互WlxShutdown 在關閉之前Winlogon 調用此函數,允許GINA實現任何關閉任務,例如從讀卡器中退出智能卡WlxStartApplication 當系統需要在用戶的上下文中啟動應用程序時調用此函數WlxWkstaLockedSAS當工作站被鎖定,如果接收到壹個SAS,則Winlogon 調用此函數在默認情況下,GINA顯示登陸對話框,用戶輸入用戶名及口令。所以要想屏蔽掉Ctrl+Alt+Del,則可以寫壹個新的MyGina.dll,其中提供接口調用msgina.dll的函數WlxLoggedOnSAS,從而實現Ctrl+Alt+Del屏蔽。或者編寫壹個鍵盤驅動程序來實現。難道屏蔽Ctrl+Alt+Del真的象上述所說的那麽麻煩嗎?有沒有更好的方法呢?答案是肯定的。所以忘掉GINA吧,使用操作系統的策略設置完全可以搞掂這個問題。方法是進入"開始"菜單,選擇"運行",然後在運行對話框中輸入"gpedit.msc",啟動Windows系統的組策略編輯器。在左邊窗格查看"用戶配置管理模板系統登錄/註銷",則在右邊窗格策略裏不難發現"禁用任務管理器"壹項。組策略編輯器通過對這個策略的設置可以屏蔽掉Ctrl+Alt+Del。如果要通過編寫代碼來實現,則必須操作下面的註冊表項:HKCUSoftwareMicrosoftWindowsCurrentVersionPoliciesSystemDisableTaskMgr = dword:1如此設置之後,則在Windows XP中,如果用戶按下Ctrl+Alt+Del,則會彈出壹個出錯對話框,註意這裏假設在控制面板中?用戶帳號?管理的?選擇登錄和註銷選項?設置啟用了?使用歡迎屏幕?壹項。否則,XP將使用Windows的傳統登錄模式,要求用戶輸入帳戶名。並且Ctrl+Alt+Del組合鍵的 行為也和傳統的行為壹樣,註冊表中DisableTaskMgr的設置也只是將登錄/註銷對話框中的任務管理器按鈕屏蔽或置灰。 有人可能會問,有關任務管理器的文檔又沒有明確說明,那妳是怎麽知道DisableTaskMgr是用來禁用任務管理器的呢?告訴妳吧, 我是在使用GPEDIT時發現的。GPEDIT是壹個非常有用的工具,不僅可以用它來編輯策略,還可以用它來發現策略。利用這個工具可以輕松控制Windows的許多東西,從許可權限的存取到是否使用IE的傳統外觀,從是否顯示對話框中的Places Bar到是否用Ctrl+Alt+Del 啟動任務管理器。總之用它可以配置上百個界面行為,因此它是壹個足以讓系統管理員垂延三尺的工具。壹旦找到了感興趣的策略,那如何知道相應的註冊表位置呢?有兩種方法。第壹種是比較粗魯的辦法:在修改策略的前後將註冊表輸出到壹個.reg文件,然後比較它們有什麽不同。所有的策略無外乎以下的四個註冊表鍵:// 用戶指定HKEY_CURRENT_USERSoftwarePoliciesHKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPolicies// 機器指定HKEY_LOCAL_MACHINESoftwarePoliciesHKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionPolicies第二種方法是直搗信息源頭--檢查描述策略的管理模板文件(.adm)。下面是Windows XP的system.adm文件對 DisableTaskMgr的描述:(Windows 2000對此的描述稍有不同,其細節請參考Windows 2000的資源開發包)CATEGORY !!CADOptions#if version >= 4EXPLAIN !!CADOptions_Help#endifKEYNAME "SoftwareMicrosoftWindowsCurrentVersionPoliciesSystem"POLICY !!DisableTaskMgr#if version >= 4SUPPORTED !!SUPPORTED_Win2k#endifEXPLAIN !!DisableTaskMgr_HelpVALUENAME "DisableTaskMgr"END POLICY;; More Ctrl+Alt+Del policies here...;END CATEGORY ; Ctrl+Alt+Del optionsDisableTaskMgr_Help="防止用戶啟動''任務管理器''(Taskmgr.exe)。nn如果該設置被啟用,並且用戶試圖啟動任務管理器,系統會顯示消息,解釋是壹個策略禁止了這個操作。nn任務管理器讓用戶啟動或終止程序,監視計算機性能,查看及監視計算機上所有運行中的程序 (包含系統服務), 搜索程序的執行文件名,及更改程序運行的優先順序。"DisableTaskMgr="刪除任務管理器"以上是DisableTaskMgr的描述片斷正是在這段描述中KEYNAME 和VALUENAME指定了註冊表的鍵值對。利用這種方法,妳可以為自己的應用程序創建管理模板和策略,但編輯和瀏覽.adm模板文件的編輯器必須支持Unicode字符。如Notepad或者WordPad等都可以。此外,使用管理模板文件,系統管理員可以用它為整個組織配置需要的策略?由此可以看出,此文件在系統中的地位舉足輕重!有關模板管理文件格式的詳細信息請參考平臺SDK。最後需要強調的是DisableTaskMgr只是禁用Ctrl+Alt+Del的功能。下面我們來討論如何捕獲它的按鍵序列。要想截獲Ctrl+Alt+Del,有三種可選擇的方法:1、 編寫壹個GINA代理;此方法我們在以後的文章中介紹。實際上,ac952_z_cn的個人專欄文章:?WINDOWS NT/2000下如何屏蔽CTRL+ALT+DEL?使用的就是這種方法。2、 編寫壹個鍵盤驅動程序;本文例子程序使用的方法。3、 用自己的程序代替任務管理器程序TaskMgr.exe。屏蔽Ctrl+Alt+Del解決方案的具體實現細節請參考本文的例子代碼。下面讓我們來解決屏蔽任務切換鍵序列的問題,這些鍵序列包括Alt+Tab、Ctrl+Esc、Alt+Esc、VK_LWIN/VK_RWIN以及任務欄。在很早以前的Window 3.1年代,處理這個問題的方法是通過WM_SYSKEYDOWN實現。到了Windows 9x時期,本文前面提到過對這個問題的處理方法,使用SPI_SETSCREENSAVERRUNNING。但是進入Windows NT 4.0 (SP3 +),Windows 2000以及Windows XP時代,對這個問題的處理已經有所不同,必須寫壹個低級的鍵盤驅動鉤子。不要怕,因為要實現這個鉤子並不是很難。本文下面會介紹如何實現這個鍵盤鉤子。壹般來講,系統級鉤子必須是壹個DLL。下面是本文提供的壹個鍵盤鉤子DLL的源代碼片斷(TaskKeyHook.dll):頭文件//////////////////////////////////////////////////////////////////TaskKeyHook.h//#define DLLIMPORT __declspec(dllimport)DLLIMPORT BOOL DisableTaskKeys(BOOL bEnable, BOOL bBeep);DLLIMPORT BOOL AreTaskKeysDisabled();實現文件////////////////////////////////////////////////////////////////// TaskKeyHook.cpp//#define _WIN32_WINNT 0x0500 // for KBDLLHOOKSTRUCT#include // MFC core and standard components#define DLLEXPORT __declspec(dllexport)//////////////////// App (DLL) object//class CTaskKeyHookDll : public CWinApp {public:CTaskKeyHookDll() { }~CTaskKeyHookDll() { }} MyDll;////////////////////////////////////////////////// 下面的代碼表示這壹部分在此DLL所有實例之間***享// 低級鍵盤鉤子壹定是系統級的鉤子//#pragma data_seg (".mydata")HHOOK g_hHookKbdLL = NULL; // 鉤子句柄BOOL g_bBeep = FALSE; // 按下非法鍵時蜂鳴響鈴#pragma data_seg ()#pragma comment(linker, "/SECTION:.mydata,RWS") // 告訴鏈接器:建立數據***享段//////////////////////////////////// 低級鍵盤鉤子// 截獲任務轉換鍵:不傳遞直接返回//LRESULT CALLBACK MyTaskKeyHookLL(int nCode, WPARAM wp, LPARAM lp){KBDLLHOOKSTRUCT *pkh = (KBDLLHOOKSTRUCT *) lp;if (nCode==HC_ACTION) {BOOL bCtrlKeyDown =GetAsyncKeyState(VK_CONTROL)>>((sizeof(SHORT) * 8) - 1);if ((pkh->vkCode==VK_ESCAPE && bCtrlKeyDown) // Ctrl+Esc// Alt+TAB(pkh->vkCode==VK_TAB && pkh->flags & LLKHF_ALTDOWN) // Alt+Esc(pkh->vkCode==VK_ESCAPE && pkh->flags & LLKHF_ALTDOWN)(pkh->vkCode==VK_LWIN pkh->vkCode==VK_RWIN)) { // 開始菜單if (g_bBeep && (wp==WM_SYSKEYDOWNwp==WM_KEYDOWN))MessageBeep(0); // 蜂鳴return 1; // 不再往CallNextHookEx傳遞,直接返回}}return CallNextHookEx(g_hHookKbdLL, nCode, wp, lp);}////////////////////////////////////////////////// 是否屏蔽任務鍵序列?也就是說鍵盤鉤子是否安裝?// 註:這裏假設沒有其它鉤子做同樣的事情//DLLEXPORT BOOL AreTaskKeysDisabled(){return g_hHookKbdLL != NULL;}////////////////////////////////////////////////// 屏蔽任務鍵:安裝低級鍵盤構// 返回當前是否屏蔽標誌(TRUE/FALSE)//DLLEXPORT BOOL DisableTaskKeys(BOOL bDisable, BOOL bBeep){if (bDisable) {if (!g_hHookKbdLL) {g_hHookKbdLL = SetWindowsHookEx(WH_KEYBOARD_LL,MyTaskKeyHookLL, MyDll.m_hInstance, 0);}} else if (g_hHookKbdLL != NULL) {UnhookWindowsHookEx(g_hHookKbdLL);g_hHookKbdLL = NULL;}g_bBeep = bBeep;return AreTaskKeysDisabled();}TaskKeyHook 輸出兩個函數:DisableTaskKeys 和 AreTaskKeysDisabled。前者安裝WH_KEYBOARD_LL 鉤子;後者判斷這個鉤子是否安裝。此鍵盤鉤子的處理思路是截獲Alt+Tab,Ctrl+Esc,Alt+Esc以及Windows 鍵VK_LWIN/VK_RWIN,關於這兩個鍵,稍候會有詳細描述。當鉤子碰到這些鍵時,它直接返回到調用者,而不是將處理傳遞給CallNextHookEx 。LRESULT CALLBACK MyTaskKeyHookLL(...){if (/* 任務鍵*)return 1; // 立即返回return CallNextHookEx(...);}TaskKeyHook的大部分實現都很簡單。只有壹個地方用到了壹點小技巧:既使用#pragma data_seg 命名包含全程數據的數據段,並且用#pragma comment (linker...)告訴鏈接器讓這個數據段為***享段。實現細節請參考源代碼。本文附帶的例子程序(TrapKeys.exe)匯集了上述幾個有關屏蔽鍵盤按鍵序列的功能,除此之外,它還有壹個功能就是禁用任務欄。因為既然禁用了任務轉換鍵,那麽壹般來說,也必然要禁用任務欄,否則禁用任務轉換鍵就沒有意義了。禁用任務欄的具體方法如下:HWND hwnd = FindWindow("Shell_traywnd", NULL);//找到任務欄EnableWindow(hwnd, FALSE); // 禁用任務欄如圖四是例子程序運行畫面:圖四 TrapKeys程序運行畫面以下是TrapKeys程序的實現代碼://///////////////////////////////////////////////// TrapKeys.cpp//#include "stdafx.h"#include "resource.h"#include "StatLink.h"#include "TaskKeyMgr.h"////////////////////// 主對話框//class CMyDialog : public CDialog {public:CMyDialog(CWnd* pParent = NULL) : CDialog(IDD_MYDIALOG, pParent) { }protected:HICON m_hIcon;CStaticLink m_wndLink1;CStaticLink m_wndLink2;CStaticLink m_wndLink3;virtual BOOL OnInitDialog();// 命令/UI 的更新處理afx_msg void OnDisableTaskMgr();afx_msg void OnDisableTaskKeys();afx_msg void OnDisableTaskbar();afx_msg void OnUpdateDisableTaskMgr(CCmdUI* pCmdUI);afx_msg void OnUpdateDisableTaskKeys(CCmdUI* pCmdUI);afx_msg void OnUpdateDisableTaskbar(CCmdUI* pCmdUI);afx_msg LRESULT OnKickIdle(WPARAM,LPARAM);DECLARE_MESSAGE_MAP()};///////////////////////////////////////////////////////// 標準的MFC 對話框應用類代碼。//class CMyApp : public CWinApp {public:virtual BOOL InitInstance() {// 初始化app:運行對話框CMyDialog dlg;m_pMainWnd = &dlg;dlg.DoModal();return FALSE;}virtual int ExitInstance() {// 為了按全起見,在退出程序的時候,將所有禁用的項目復原CTaskKeyMgr::Disable(CTaskKeyMgr::ALL, FALSE);return 0;}} theApp;BEGIN_MESSAGE_MAP(CMyDialog, CDialog)ON_COMMAND(IDC_DISABLE_TASKKEYS,OnDisableTaskKeys)ON_COMMAND(IDC_DISABLE_TASKBAR, OnDisableTaskbar)ON_COMMAND(IDC_DISABLE_TASKMGR, OnDisableTaskMgr)ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKKEYS, OnUpdateDisableTaskKeys)ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKBAR, OnUpdateDisableTaskbar)ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKMGR, OnUpdateDisableTaskMgr)ON_MESSAGE(WM_KICKIDLE,OnKickIdle)END_MESSAGE_MAP()///////////////////////////////////////////////// 初始化對話框:子類化超鏈接柄加栽圖標//BOOL CMyDialog::OnInitDialog(){CDialog::OnInitDialog();// 初始化超鏈接m_wndLink1.SubclassDlgItem(IDC_EMAIL,this);m_wndLink2.SubclassDlgItem(IDC_VCKBASEURL,this);m_wndLink3.SubclassDlgItem(IDC_VCKBASELINK,this);// 自己設置對話框圖標。MFC不會為對話框應用程序設置它m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);SetIcon(m_hIcon, TRUE); // 打圖標SetIcon(m_hIcon, FALSE); // 小圖標return TRUE;}////////////////////////////////////////////////////////// 命令/UI 更新處理:寫這些東西應該很輕松。void CMyDialog::OnDisableTaskKeys(){CTaskKeyMgr::Disable(CTaskKeyMgr::TASKKEYS,!CTaskKeyMgr::AreTaskKeysDisabled(), TRUE); // 蜂鳴}void CMyDialog::OnUpdateDisableTaskKeys(CCmdUI* pCmdUI){pCmdUI->SetCheck(CTaskKeyMgr::AreTaskKeysDisabled());}void CMyDialog::OnDisableTaskbar(){CTaskKeyMgr::Disable(CTaskKeyMgr::TASKBAR,!CTaskKeyMgr::IsTaskBarDisabled());}void CMyDialog::OnUpdateDisableTaskbar(CCmdUI* pCmdUI){pCmdUI->SetCheck(CTaskKeyMgr::IsTaskBarDisabled());}void CMyDialog::OnDisableTaskMgr(){CTaskKeyMgr::Disable(CTaskKeyMgr::TASKMGR,!CTaskKeyMgr::IsTaskMgrDisabled());}void CMyDialog::OnUpdateDisableTaskMgr(CCmdUI* pCmdUI){pCmdUI->SetCheck(CTaskKeyMgr::IsTaskMgrDisabled());}////////////////////////////////////////////////////////// 要想讓ON_UPDATE_COMMAND_UI正常工作,這是必需的。//LRESULT CMyDialog::OnKickIdle(WPARAM wp, LPARAM lCount){UpdateDialogControls(this, TRUE);return 0;}按上述方法盡管禁用了任務欄,但是還有壹個機關沒有處理,那就是按下Windows鍵仍然可以彈出?開始?菜單。顯然在處理VK_LWIN之前,任務欄不會檢查是否被啟用。壹般來講,如果某個窗口被屏蔽掉,那麽它就不再會處理用戶在這個窗口的輸入?這就是所謂的禁用(Disable)的含義。通常調用EnableWindow(FALSE)後自然就達到了這個目的。但是處理VK_LWIN/VK_RWIN按鍵的代碼決不會去檢查任務欄啟用/禁用狀態。對此,本文的處理辦法仍然是利用鍵盤鉤子。修改壹下TaskKeyHook實現,增加對Windows鍵的捕獲。這樣按下?開始?菜單鍵之後什麽也不會發生。希望沒有漏掉其它的按鍵。如果哪位讀者發現漏掉了什麽鍵,請和我聯系,以便把它加到鍵盤鉤子中去。為了簡單起見,我在類CTaskKeyMgr中封裝了所有禁用的函數。下面是這個類的定義擊實現文件:TaskKeyMgr////////////////////////////////////////// TaskKeyMgr.h//#pragma once#include "TaskKeyHook.h"/////////////////////////////////////////////////////////////////////// 使用這個類禁用任務鍵,任務管理器或任務欄。// 用相應的標誌調用Disable,如:CTaskMgrKeys::Disable(CTaskMgrKeys::ALL);//class CTaskKeyMgr {public:enum {TASKMGR = 0x01, // 禁用任務管理器(Ctrl+Alt+Del)TASKKEYS = 0x02, //禁用任務轉換鍵(Alt-TAB, etc)TASKBAR = 0x04, //禁用任務欄ALL=0xFFFF //禁用所有東西L};static void Disable(DWORD dwItem,BOOL bDisable,BOOL bBeep=FALSE);static BOOL IsTaskMgrDisabled();static BOOL IsTaskBarDisabled();static BOOL AreTaskKeysDisabled() {return ::AreTaskKeysDisabled(); // 調用 DLL}};CPP實現////////////////////////////////////////////////////////////////// TaskKeyMgr.cpp//#include "StdAfx.h"#include "TaskKeyMgr.h"#define HKCU HKEY_CURRENT_USER// 用於禁用任務管理器策略的註冊表鍵值對LPCTSTR KEY_DisableTaskMgr ="SoftwareMicrosoftWindowsCurrentVersionPoliciesSystem";LPCTSTR VAL_DisableTaskMgr = "DisableTaskMgr";///////////////////////////////////////////// 禁用相關的任務鍵//// dwFlags = 表示禁用什麽// bDisable = 禁用為 (TRUE) ,否則為啟用 (FALSE)// bBeep = 按下非法鍵是否蜂鳴(指針對任務鍵)//void CTaskKeyMgr::Disable(DWORD dwFlags, BOOL bDisable, BOOL bBeep){// 任務管理器 (Ctrl+Alt+Del)if (dwFlags & TASKMGR) {HKEY hk;if (RegOpenKey(HKCU, KEY_DisableTaskMgr,&hk)!=ERROR_SUCCESS)RegCreateKey(HKCU, KEY_DisableTaskMgr, &hk);if (bDisable) { // 禁用任務管理器(disable TM): set policy = 1DWORD val=1;RegSetValueEx(hk, VAL_DisableTaskMgr, NULL,REG_DWORD, (BYTE*)&val, sizeof(val));} else { // 啟用任務管理器(enable TM)RegDeleteValue(hk,VAL_DisableTaskMgr);}}// 任務鍵 (Alt-TAB etc)if (dwFlags & TASKKEYS)::DisableTaskKeys(bDisable,bBeep); // 安裝鍵盤鉤// 任務欄if (dwFlags & TASKBAR) {HWND hwnd = FindWindow("Shell_traywnd", NULL);EnableWindow(hwnd, !bDisable);}}BOOL CTaskKeyMgr::IsTaskBarDisabled(){HWND hwnd = FindWindow("Shell_traywnd", NULL);return IsWindow(hwnd) ? !IsWindowEnabled(hwnd) : TRUE;}BOOL CTaskKeyMgr::IsTaskMgrDisabled(){HKEY hk;if (RegOpenKey(HKCU, KEY_DisableTaskMgr, &hk)!=ERROR_SUCCESS)return FALSE; // 沒有此鍵,不禁用DWORD val=0;DWORD len=4;return RegQueryValueEx(hk, VAL_DisableTaskMgr,NULL, NULL, (BYTE*)&val, &len)==ERROR_SUCCESS && val==1;}這個類中的函數都是靜態的,實際上CTaskKeyMgr完全就是壹個名字空間。妳可以在自己的程序中隨心所欲地使用它。例如,禁用任務轉換按鍵和任務欄,但是不禁用Ctrl+Alt+Del:CTaskKeyMgr::Disable(CTaskKeyMgr::TASKKEYS CTaskKeyMgr::TASKBAR, TRUE);此外,還有幾個函數是用來檢查當前禁用了哪些東西,甚至可以在用戶按下禁用鍵時發出蜂鳴聲?自己去享受Paul的源代碼吧!

  • 上一篇:slorais 10 有什麽特別的?
  • 下一篇:終極黑科技源代碼
  • copyright 2024編程學習大全網